大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是 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 。
importsys,os importargparse importImage 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="JPEGImagefolder.") args=parser.parse_args() imgFiles=[] #獲取指定文件夾中所有 jpg 圖片路徑 imgFolder=os.path.abspath(args.input) inputFiles=os.listdir(imgFolder) foridxinrange(len(inputFiles)): imgFiles.append(os.path.join(imgFolder,inputFiles[idx])) foridxinrange(len(imgFiles)): #使用 Image 庫打開 jpg 圖片 imgObj=Image.open(imgFiles[idx]) pixelBuf=imgObj.getdata() #抽取 rgb 裸數據寫入 bin 文件 foriinrange(len(pixelBuf)): forjinrange(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 解碼函數全部去掉):
#defineAPP_FB_HEIGHT480 #defineAPP_FB_WIDTH1280 /*LCDframebufferbyteperpixel,RGB888format,24-bit.*/ #defineAPP_FB_BPP3 constuint32_ts_imagePics=17; constuint32_ts_imageStartAddr=0x30100000; intmain(void) { uint8_t*imageAddr=(uint8_t*)s_imageStartAddr; uint32_timageBytes=APP_FB_HEIGHT*APP_FB_WIDTH*APP_FB_BPP; BOARD_ConfigMPU(); BOARD_InitBootPins(); BOARD_BootClockRUN(); BOARD_ResetDisplayMix(); APP_InitDisplay(); while(1) { /*Waitfortheprevioussetframebufferactive.*/ while(s_newFrameShown==false); /*Nownewframeisready,passittoLCDIF.*/ s_newFrameShown=false; g_dc.ops->setFrameBuffer(&g_dc,0,imageAddr); imageAddr+=imageBytes; if((uint32_t)imageAddr>=(s_imageStartAddr+imageBytes*s_imagePics)) { break; } } } staticvoidAPP_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 刷新率。
#defineDEMO_HSW(1U) #defineDEMO_HBP(48U) #defineDEMO_HFP(16U) #defineDEMO_VSW(1U) #defineDEMO_VBP(3U) #defineDEMO_VFP(5U) staticvoidBOARD_InitLcdifClock(void) { /* *Thepixelclockis(height+VSW+VFP+VBP)*(width+HSW+HFP+HBP)*framerate. * *For60Hzframerate,theTM103XDKP13pixelclockshouldbe40MHz. * */ constclock_root_config_tlcdifv2ClockConfig={ .clockOff=false, .mfn=0, .mfd=0, .mux=4,/*!
讓我們嘗試降低 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 花屏顯示問題的分析解決經驗痞子衡便介紹完畢了,掌聲在哪里~~~
審核編輯 黃昊宇
-
lcd
+關注
關注
34文章
4411瀏覽量
167101
發布評論請先 登錄
相關推薦
評論