痞子衡嵌入式:記錄i.MXRT1060驅動LCD屏顯示橫向漸變色有亮點問題解決全過程(解答篇)

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

上一篇發出之後,大家在我的微信公號文章下麵留言很熱烈,大部分朋友都把懷疑點放在了HyperRAM時序配置上,覺得很大概率是HyperRAM的數據訪問出了問題導致了LCD顯示異常,這個懷疑是非常合情合理的,那麼從高效定位問題的角度,我們接下來應該怎麼做? ...



  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是i.MXRT1060上LCD橫向漸變色顯示出亮點問題的分析解決經驗

  接上篇《一個關於LCD屏顯示出異常亮點的故事(上)》咱們繼續聊,上一篇發出之後,大家在我的微信公號文章下麵留言很熱烈,大部分朋友都把懷疑點放在了HyperRAM時序配置上,覺得很大概率是HyperRAM的數據訪問出了問題導致了LCD顯示異常,這個懷疑是非常合情合理的,那麼從高效定位問題的角度,我們接下來應該怎麼做?

一、問題分析

  讓我們回到上一篇的最後,痞子衡列出了所有可能出問題的地方,我們現在需要將這些疑點逐一排除:

  1. 客戶LCD顯示測試代碼邏輯是否有問題?
  2. 客戶LCD屏與i.MXRT1060連接(線序)是否有問題?
  3. 客戶LCD屏的ST7701S驅動移植(從STM32到i.MXRT1060)是否有問題?
  4. 客戶選用的HyperRAM本身質量是否有問題?
  5. i.MXRT1060配置的客戶HyperRAM時序參數是否有問題?
  6. i.MXRT1060的LCD顯示模塊eLCDIF驅動是否有問題?
  7. i.MXRT1060系統的匯流排處理(如Cache、匯流排競爭)是否有問題?

  這些懷疑點總結下來就是兩類,一類是硬體問題(如2、4),另一類是軟體問題(如1、3、5、6、7)。痞子衡覺得應該從軟體疑點先下手。因為從現象上看,硬體上基本沒啥大問題,LCD是能夠按代碼設計那樣去顯示的,而且硬體問題檢查起來(可能涉及改板子或者焊接,萬一整壞了板子...)不如驗證軟體問題來得快,等軟體疑點初步排除了,再找硬體問題也不遲。
  確定了從軟體疑點下手,那麼從哪一個開始呢?當然是大家都認為最可疑的點 - HyperRAM時序配置問題這點先入手,不過直接去檢查HyperRAM時序配置較為繁瑣,我們有更好的選擇,uint32_t s_frameBuffer[480][480]總大小為900KB,這小於i.MXRT1060內部RAM總空間(1MB),所以我們完全可以將這個frameBuffer鏈接到內部RAM里來規避HyperRAM時序配置問題(疑點5)以及系統匯流排處理問題(疑點7),另外我們還可以直接用J-Link修改內部RAM里的frameBuffer數據來規避客戶測試代碼邏輯問題(疑點1)。為了方便地生成frameBuffer數據,我們還需要寫個簡單的Python腳本,那麼我們先嘗試用這一套方法在LCD上顯示一個真實風景照吧。

Note: 這套驗證方法的最大好處是高效且省時,不需要在App代碼工程里改frameBuffer相關代碼以及一次次地重新編譯下載。

二、開始測試

2.1 將frameBuffer鏈接到內部RAM里

2.1.1 重配FlexRAM

  首先是需要在App工程的startup_MIMXRT1062.s文件里修改Reset_Handler代碼,增加FlexRAM重配代碼,因為預設RAM配置是128KB ITCM, 128KB DTCM, 768KB OCRAM,我們要將其調整為1MB OCRAM。

__iomux_gpr16_adr     EQU  0x400AC040
__iomux_gpr17_adr     EQU  0x400AC044
__flexram_bank_cfg    EQU  0x55555555

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
        THUMB

        PUBWEAK Reset_Handler
        SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
        CPSID   I               ; Mask interrupts

        ;新增代碼(開始)
        LDR R0,=__iomux_gpr17_adr
        MOV32 R1,__flexram_bank_cfg
        STR R1,[R0]
        LDR R0,=__iomux_gpr16_adr
        LDR R1,[R0]
        ORR R1,R1,#4
        STR R1,[R0]
        ;新增代碼(結束)

        LDR     R0, =0xE000ED08
        LDR     R1, =__vector_table
        ; ...
2.1.2 調整MPU設置

  然後我們要在App工程的board.c文件里修改BOARD_ConfigMPU()函數,增加如下代碼,確保全部1MB OCRAM地址空間(0x20200000開始)都是non-cacheable屬性。

/* Region 6 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1MB);
2.1.3 修改鏈接文件

  最後我們要在App工程的main函數源文件里將s_frameBuffer放在一個自定義的.frameBuffer段里,以便在App鏈接文件里將其放到OCRAM地址空間里(0x20200000 - 0x202FFFFF)。
  main函數源文件中的修改:

__no_init   uint32_t s_frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH] @ ".frameBuffer";

  App工程鏈接文件中的修改:

define symbol m_data2_start  = 0x20200000;
define symbol m_data2_end    = 0x202FFFFF;

define region DATA2_region = mem:[from m_data2_start to m_data2_end];

place in DATA2_region        { section .frameBuffer };

2.2 編寫Python腳本生成frameBuffer數據

2.2.1 風景圖片數據

  我們可以從網上找一張.jpg格式圖片,將其尺寸裁剪到480x480,然後藉助Pillow里的Image庫將其轉成XRGB8888格式的binary文件,對應Python腳本(腳本名為convert_jpeg_to_xrgb8888.py)用法和源代碼如下:

import sys, os
import argparse
from PIL import Image

class ConvertJpegToXrgb8888(object):
    def __init__(self):
        pass

    def _read_options(self):
        parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument("-o", "--output", required=True, metavar="PATH", type=argparse.FileType('wb'), help="Specify the output file.")
        parser.add_argument("input", help="JPEG Image file."),
        return parser.parse_args()

    def run(self):
        args = self._read_options()
        imgObj = Image.open(args.input)
        pixelBuf = imgObj.getdata()
        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.write(chr(0))
        args.output.close()

if __name__ == "__main__":
    exit(ConvertJpegToXrgb8888().run())
2.2.2 RGB測試數據

  此外我們還需要一個腳本,能夠很容易地修改生成指定的RGB測試數據,用於定位亮點問題,對應Python腳本(腳本名為generate_xrgb8888.py)用法和源代碼如下:

import sys, os
import argparse

class GenerateXrgb8888(object):
    def __init__(self):
        pass

    def _read_options(self):
        parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument("-o", "--output", required=True, metavar="PATH", type=argparse.FileType('wb'), help="Specify the output file.")
        return parser.parse_args()

    def _make_xrgb8888(self, r, g, b):
        return chr(b) + chr(g) + chr(r) + chr(0)

    def run(self):
        args = self._read_options()
        for i in range(160):
            for j in range(480):
                args.output.write(self._make_xrgb8888(j%256, 0, 0))
        for i in range(160):
            for j in range(480):
                args.output.write(self._make_xrgb8888(0, j%256, 0))
        for i in range(160):
            for j in range(480):
                args.output.write(self._make_xrgb8888(0, 0, j%256))
        args.output.close()

if __name__ == "__main__":
    exit(GenerateXrgb8888().run())

2.3 使用J-Link將frameBuffer數據更新進OCRAM

2.3.1 顯示風景圖片

  我們從網上隨便找一張風景圖片scenery.jpg,使用convert_jpeg_to_xrgb8888.py腳本將其轉換為scenery.bin,然後將J-Link模擬器掛上晶元,成功連接之後,使用loadbin scenery.bin 0x20200000命令將圖片數據下載進內部RAM。

  這時候你可以看到LCD的顯示變成了圖片:

2.3.2 顯示RGB測試數據

  從上一節測試的真實圖片顯示效果上看,似乎看不出明顯的亮點問題,這說明亮點在特定RGB數據內容顯示的時候才會顯現出來,那麼我們現在的任務就是要找到這個顯現條件,這時候需要修改generate_xrgb8888.py腳本來反覆做實驗。
  所以痞子衡就不斷地修改腳本、生成數據、下載數據,功夫不負有心人,痞子衡找到了亮點復現規律。

三、原因分析

  痞子衡發現的亮點規律是當橫向某兩個連續漸變像素點RGB任一分量出現多bit由1向0跳變時(比如前一個像素點B分量是8'b01111111,後一個像素點B分量是8'b10000000),則後一個像素點必是亮點,這個亮點像素點最終顯示的B分量極可能變成了8'b11111111。

  所以分析下來應該是DCLK信號的極性設置在屏的驅動IC和i.MXRT1060的eLCDIF模塊里不匹配,RGB數據線採樣時機錯了,導致實際顯示的RGB數據發生了錯誤。
  在SDK的elcdif_rgb example里關於eLCDIF模塊信號輸出的極性設置如下,這裡需要註意的是kELCDIF_DriveDataOnRisingClkEdge是置1(即上沿數據輸出,下沿數據保持的意思)。

#define APP_POL_FLAGS (kELCDIF_DataEnableActiveHigh | kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DriveDataOnRisingClkEdge)

  這是i.MXRT1060 eLCDIF極性配置相關:

  這是OTA5180A晶元的預設極性配置時序圖:

  SDK里的極性設置與i.MXRT1060-EVK標配的LCD屏(RK043FN02H-CT)里的驅動晶元OTA5180A預設配置是相吻合的。
  我們現在再來看看SDK里的極性設置與客戶LCD屏的驅動晶元ST7701S的極性配置是否匹配,客戶設置了ST7701S的IM[3:0]狀態為4'b1010,即RGB模式輸出,且PCLK是下沿數據輸入,上沿數據保持(Latch),因此跟SDK里的極性設置是反相的。

  所以最終的解決方法就是要麼將ST7701S的IM[3:0]狀態設為4'b0010,要麼在App代碼里將APP_POL_FLAGS定義改用kELCDIF_DriveDataOnFallingClkEdge。

歡迎訂閱

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

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


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

-Advertisement-
Play Games
更多相關文章
  • [toc] 1.應用背景 底端設備有大量網路報文(位元組數組):心跳報文,數據採集報文,告警報文上報。需要有對應的報文結構去解析這些位元組流數據。 2.結構體解析 由此,我第一點就想到了用結構體去解析。原因有以下兩點: 2.1.結構體存在棧中 類屬於引用類型,存在堆中;結構體屬於值類型,存在棧中,在一個 ...
  • 前言 有一個東西叫做鴨子類型,所謂鴨子類型就是,只要一個東西表現得像鴨子那麼就能推出這玩意就是鴨子。 C 裡面其實也暗藏了很多類似鴨子類型的東西,但是很多開發者並不知道,因此也就沒法好好利用這些東西,那麼今天我細數一下這些藏在編譯器中的細節。 不是只有 和 才能 在 C 中編寫非同步代碼的時候,我們經 ...
  • 做下對文件複製操作相關的筆記: /// <summary> /// 文件幫助類 /// </summary> public class FileHelper { /// <summary> /// 複製一個目錄下所有文件到一個新目錄下 /// </summary> /// <param name=" ...
  • Xamarin.Forms讀取並展示Android和iOS通訊錄 TerminalMACS客戶端 本文同步更新地址: https://dotnet9.com/11520.html https://terminalmacs.com/861.html 閱讀導航: 一、功能說明 二、代碼實現 三、源碼獲取 ...
  • 對閉包的理解 1.對於成員變數和局部變數:成員變數就是方法外部,類的內部定義的變數;局部變數就是方法或語句塊內部定義的變數。局部變數必須初始化。 形式參數是局部變數,局部變數的數據存在於棧記憶體中。棧記憶體中的局部變數隨著方法的消失而消失。成員變數存儲在堆中的對象裡面,由垃圾回收器負責回收。 成員變數它 ...
  • 首先創建一個asp.net core web應用程式 第二步 目前官方預置了7種模板項目供我們選擇。從中我們可以看出,既有我們熟悉的MVC、WebAPI,又新添加了Razor Page,以及結合比較流行的Angular、React前端框架的模板項目。 空項目模板 Program.cs using S ...
  • 控制條控制項: progressBar 不能按照你程式的進程自動變化,需認為計算,調整變化量 private void progressBar1_Click(object sender, EventArgs e) { this.progressBar1.Maximum = 100;//設置進度條最大長 ...
  • 前幾天發佈了 "抄抄《CSS 故障藝術》的動畫" 這篇文章,在這篇文章里介紹瞭如何使用Win2D繪製文字然後配合BlendEffect製作故障藝術的動畫。本來打算就這樣收手不玩這個動畫了,但後來又發現性能不符合理想。明明只是做做Resize動畫和用BlendEffect混合,為什麼性能會這麼差呢? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...