痞子衡嵌入式:降低刷新率是定位LCD花屏顯示問題的第一大法(i.MXRT1170, 1280x480 LVDS)

来源:https://www.cnblogs.com/henjay724/archive/2020/06/04/13044745.html
-Advertisement-
Play Games

痞子衡最近這段時間在參與一個基於i.MXRT1170的大項目(先保個密),需要做一個開機動畫功能,板子連接的LCD屏解析度是1280x480,因為開機動畫要求達到30fps,並且要畫質清晰,如果是從SD卡裡讀mp4或者jpeg去解碼,這麼高解析度的圖像(暫不考慮低解析度的圖片再用PXP模塊去拉伸的方... ...



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是i.MXRT1170上LCD花屏顯示問題的分析解決經驗

  痞子衡最近這段時間在參與一個基於i.MXRT1170的大項目(先保個密),需要做一個開機動畫功能,板子連接的LCD屏解析度是1280x480,因為開機動畫要求達到30fps,並且要畫質清晰,如果是從SD卡裡讀mp4或者jpeg去解碼,這麼高解析度的圖像(暫不考慮低解析度的圖片再用PXP模塊去拉伸的方案)解碼耗時比較長,恐怕難以達成30fps,所以痞子衡打算直接把圖片的裸rgb數據事先存在Flash里,然後LCD模塊直接去刷Flash里的數據去顯示。

  板子上的SPI NOR Flash有兩種,預設是八線DDR高性能Flash,還有一個可選的四線SDR普通Flash,痞子衡做好的代碼在預設高性能Flash上跑得沒問題,換到另一塊rework為普通四線Flash上就出問題了,顯示完全是花屏,沒有一點圖片的影子,到底是怎麼回事?跟著痞子衡一起去發現答案吧。

一、項目板卡簡圖

  先來看一下這個項目板卡簡圖,簡圖裡只示意了痞子衡今天要分享的LCD問題相關的器件,顯示屏是TM103XDKP13控制器驅動的LVDS介面屏,跟i.MXRT連接的話需要有一個RGB2LVDS轉接。Flash都是選的旺巨集的,一個是MX25UW51345(200MHz,8bit,DDR),還有一個是MX25U25645(133MHz,4bit,SDR)。此外還有兩個16bit的W9825G6KH組成的32bit SDRAM做顯存,總容量是64MB。

二、在Flash中準備好圖片裸數據

  首先我們需要在Flash中存入圖片數據,1280x480-24bpp (rgb888)圖片一張的裸數據大小是1800KB,32MB的Flash最大可以存18張圖片,為了給程式存儲留點空間,我們就存17張,從Flash偏移0x100000處開始存圖片。

2.1 截取一段mp4視頻

  痞子衡本地有一個NXP十周年宣傳視頻(MP4格式),原始解析度是1920x1080,可以先用ffmpeg或者格式工廠將其轉換成1280x480,然後可以直接用Windows自帶的圖片軟體里的Trim功能截取其中一段,30fps幀率的視頻截取1秒就夠了。

2.2 使用ScreenToGif軟體分離出圖片

  這時候可以用非常好用的GIF製作軟體ScreenToGif打開這個1秒的MP4,可以看到一共有31張圖片,可以刪掉其中一些留下17張,然後將其保存為圖片(當前版本僅能保存為png格式),可以再用格式工廠軟體將圖片格式轉為jpg,存在D:/nxp_logo文件夾下。

2.3 Python腳本轉成rgb888裸數據

  有了17張jpg圖片,這時候寫一個Python腳本(jpg2rgb.py),藉助Image庫將17張jpg圖片中的rgb數據全部抽取出來保存在一個bin文件中,下麵腳本使用命令為 python jpg2rgb.py D:/nxp_logo/ -o startup_video_white_rgb888_17f.bin 。

import sys, os
import argparse
import Image

parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-o", "--output", required=True, metavar="PATH", type=argparse.FileType('wb'))
parser.add_argument("input", help="JPEG Image folder.")
args = parser.parse_args()

imgFiles = []

# 獲取指定文件夾中所有jpg圖片路徑
imgFolder = os.path.abspath(args.input)
inputFiles = os.listdir(imgFolder)
for idx in range(len(inputFiles)):
    imgFiles.append(os.path.join(imgFolder, inputFiles[idx]))

for idx in range(len(imgFiles)):
    # 使用Image庫打開jpg圖片
    imgObj = Image.open(imgFiles[idx])
    pixelBuf = imgObj.getdata()
    # 抽取rgb裸數據寫入bin文件
    for i in range(len(pixelBuf)):
        for j in range(len(pixelBuf[i])):
            args.output.write(chr(pixelBuf[i][len(pixelBuf[i]) - j - 1]))
args.output.close()

2.4 將圖片裸數據bin文件下載進Flash

  現在可以藉助MCUBootUtility的通用編程器功能將startup_video_white_rgb888_17f.bin文件燒錄進Flash里0x100000處偏移的地方。至此,準備工作已經就緒。

三、引出LCD花屏顯示問題

  現在讓我們開始設計開機動畫程式,可以基於 \SDK_2.x.x_MIMXRT1170-EVK\boards\evkmimxrt1170\jpeg_examples\sd_jpeg 常式,將其中的LCD配置,Pinmux配置稍微改一下,適配這個項目的板子,然後主函數可以精簡如下(sd卡讀,libjpeg解碼函數全部去掉):

#define APP_FB_HEIGHT 480
#define APP_FB_WIDTH  1280
/* LCD frame buffer byte per pixel, RGB888 format, 24-bit. */
#define APP_FB_BPP 3

const uint32_t s_imagePics = 17;
const uint32_t s_imageStartAddr = 0x30100000;

int main(void)
{
    uint8_t *imageAddr = (uint8_t *)s_imageStartAddr;
    uint32_t imageBytes = APP_FB_HEIGHT * APP_FB_WIDTH * APP_FB_BPP;

    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_BootClockRUN();
    BOARD_ResetDisplayMix();
    APP_InitDisplay();

    while (1)
    {
        /* Wait for the previous set frame buffer active. */
        while (s_newFrameShown == false);

        /* Now new frame is ready, pass it to LCDIF. */
        s_newFrameShown = false;
        g_dc.ops->setFrameBuffer(&g_dc, 0, imageAddr);

        imageAddr += imageBytes;
        if ((uint32_t)imageAddr >= (s_imageStartAddr + imageBytes * s_imagePics))
        {
            break;
        }
    }
}

static void APP_BufferSwitchOffCallback(void *param, void *switchOffBuffer)
{
    s_newFrameShown = true;
}

  這時候把代碼下載進高性能DDR Flash的那塊板子,我們的代碼可以鏈接到TCM里執行,這樣不占用運行時Flash訪問帶寬,不與LCD搶帶寬。斷電重啟可以看到在60Hz的LCD刷新率下,開機動畫效果顯示杠杠的。

  現在把代碼下載進普通SDR Flash的板子試試,可以看到LCD顯示花屏了,完全沒有圖像的影子,這時候該怎麼定位問題?

四、嘗試降低LCD刷新率

  在嘗試降低LCD刷新率之前,痞子衡額外做了一些debug工作來確認是不是Flash焊接的問題,首先是調試器掛上去查看PC指針停在哪裡,經調試發現,PC指針是在TCM里,根據工程map文件可以查到其地址對應的是程式的結尾,說明代碼正常跑完了,這至少證明晶元能夠正常從Flash啟動。

  然後痞子衡又對程式作了一些改動,將Flash中的圖片數據拷貝到SDRAM中,讓LCD模塊去刷SDRAM,這時候圖像顯示是正常的,這幾乎就可以定位問題了,是普通SDR Flash帶寬不夠,Flash訪問速度撐不起60Hz刷新率。

#define DEMO_HSW        (1U)
#define DEMO_HBP        (48U)
#define DEMO_HFP        (16U)
#define DEMO_VSW        (1U)
#define DEMO_VBP        (3U)
#define DEMO_VFP        (5U)

static void BOARD_InitLcdifClock(void)
{
    /*
     * The pixel clock is (height + VSW + VFP + VBP) * (width + HSW + HFP + HBP) * frame rate.
     *
     * For 60Hz frame rate, the TM103XDKP13 pixel clock should be 40MHz.
     *
     */
    const clock_root_config_t lcdifv2ClockConfig = {
        .clockOff = false,
        .mfn      = 0,
        .mfd      = 0,
        .mux      = 4, /*!< PLL_528. */
        .div      = 12,
    };

    CLOCK_SetRootClock(kCLOCK_Root_Lcdifv2, &lcdifv2ClockConfig);
}

  讓我們嘗試降低LCD刷新率來驗證是不是Flash帶寬的問題,在BOARD_InitLcdifClock()函數中修改lcdifv2ClockConfig.div的值,慢慢增大該值,經痞子衡測試,當div設為22時(即對應LCD刷新率為33.9Hz),終於能夠正常顯示開機動畫了。

五、關於帶寬的分析

  現在給出痞子衡的觀點,對於一個新項目,如果首次測試LCD顯示,建議先從低刷新率開始,只有低刷新率調試通過,再逐漸增大刷新率,否則會因為帶寬問題浪費不少時間。
  最後再讓我們通過理論公式來推算這款普通SDR Flash能支持最大的刷新率,計算公式其實很簡單:

LCD最大刷新率 = (Flash時鐘頻率 * Flash數據位) / 圖片大小 = 133MHz * 4bit / (1280 * 480 * 24bit) = 36.08Hz

  理論計算值36.08Hz跟我們實測值33.9Hz很接近,那點差值應該是FLEXSPI和eLCDIF模塊的開銷。

  至此,i.MXRT1170上LCD花屏顯示問題的分析解決經驗痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時發佈到我的 博客園主頁CSDN主頁微信公眾號 平臺上。

微信搜索"痞子衡嵌入式"或者掃描下麵二維碼,就可以在手機上第一時間看了哦。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 過場CG: 接到公司領導的文件指示,“小熊”需要在6月底去海外執行一個行動代號為【定時任務】的營救計劃,這個計劃關係到公司某個項目的生死(數據安全漏洞),作戰部擬定兩個作戰方案: 方案一:使用務定時任務框架quartz; 方案二:使用windows Service服務。 最終的作戰方案為:兩者配套使 ...
  • 文章篇幅較長,閱讀完大概20min,建議收藏閱讀, 讀完會有收穫。歡迎點贊關註 原文鏈接:https://www.softwaretestinghelp.com/types-of-software-testing/ 有多少軟體測試類型呢? 我們作為測試人員瞭解很多種不同的軟體測試類型,例如功能測試( ...
  • 1.先停止資料庫伺服器 service mysqld stop 2.vim /etc/my.cnf 3.配置文件添加skip-grant-tables [root@VM_0_8_centos ~]# vim /etc/my.cnf # For advice on how to change sett ...
  • 1.linux常用命令及其參數 1.1 ls相關,文件與目錄的檢視 基本用法:ls [-options] 文件或者目錄名稱 ls [--color={never, auto, always}] 文件名或者目錄名稱 ls [--full-time] 文件名或目錄名稱 選項與參數: -a : 全部的文件 ...
  • 1. linux文件許可權和幾種表示方法 文件長度大約最大為255bytes或128個漢字字元 linux文件許可權有幾種表示方法: 使用ls -al 即可查詢到目錄的許可權內容: 2.文件許可權說明: 格式為: drwxr-xr-x o 第一組為『文件擁有者可具備的許可權』,以『initial-setup- ...
  • 基於阿裡雲代理設置centos鏡像,安裝docker,設置ntp;基於daocloud安裝docker-comspoe ...
  • 現在信息泄露越來越嚴重,而強大的密碼是防止個人敏感信息泄露的第一步。良許曾經分享過一篇文章,如何判斷你的密碼是否足夠安全,點擊以下鏈接查看: 信息泄漏時代,如何讓自己的密碼更安全? 在生活中,我們需要用到大量的密碼,這些密碼最好不要統一,否則萬一泄漏的話,所有賬號都暴露在風險之下。而在工作中,我們同 ...
  • 1、Keepalived軟體前期用來管理並監控LVS集群系統中各個服務節點的狀態;2、後期加入了實現高可用的VRRP功能。因此可以為lvs負載均衡提供高可用功能,也可以為其他服務提供高可用。。實驗鏡像:Centos 8.1.1911草圖:(待補)1、兩個real server 安裝配置在keepal... ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...