查看: 5847|回复: 1

[分享] 一个关于LCD屏显示出异常亮点的故事(下)

[复制链接]
  • TA的每日心情
    开心
    2025-7-11 08:53
  • 签到天数: 301 天

    连续签到: 2 天

    [LV.8]以坛为家I

    3868

    主题

    7472

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    39227
    最后登录
    2025-7-18
    发表于 2020-4-3 10:42:02 | 显示全部楼层 |阅读模式
    一个关于LCD屏显示出异常亮点的故事(下)


           今天痞子衡给大家分享的是i.MXRT1060上LCD横向渐变色显示出亮点问题的分析解决经验。


      接上篇《一个关于LCD屏显示出异常亮点的故事(上)》咱们继续聊,上一篇发出之后,大家在我的微信公号文章下面留言很热烈,大部分朋友都把怀疑点放在了HyperRAM时序配置上,觉得很大概率是HyperRAM的数据访问出了问题导致了LCD显示异常,这个怀疑是非常合情合理的,那么从高效定位问题的角度,我们接下来应该怎么做?


    一、问题分析
    1.png
    让我们回到上一篇的最后,痞子衡列出了所有可能出问题的地方,我们现在需要将这些疑点逐一排除:


    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.png
    二、开始测试
    2.1 将frameBuffer链接到内部RAM里
    2.1.1 重配FlexRAM
      首先是需要在App工程的startup_MIMXRT1062.s文件里修改Reset_Handler代码,增加FlexRAM重配代码,因为默认RAM配置是128KB ITCM, 128KB DTCM, 768KB OCRAM,我们要将其调整为1MB OCRAM。


    1. <font size="3" face="微软雅黑">__iomux_gpr16_adr     EQU  0x400AC040
    2. __iomux_gpr17_adr     EQU  0x400AC044
    3. __flexram_bank_cfg    EQU  0x55555555

    4. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    5. ;;
    6. ;; Default interrupt handlers.
    7. ;;
    8.         THUMB

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

    13.         ;新增代码(开始)
    14.         LDR R0,=__iomux_gpr17_adr
    15.         MOV32 R1,__flexram_bank_cfg
    16.         STR R1,[R0]
    17.         LDR R0,=__iomux_gpr16_adr
    18.         LDR R1,[R0]
    19.         ORR R1,R1,#4
    20.         STR R1,[R0]
    21.         ;新增代码(结束)

    22.         LDR     R0, =0xE000ED08
    23.         LDR     R1, =__vector_table
    24.         ; ...</font>
    复制代码
    2.1.2 调整MPU设置
      然后我们要在App工程的board.c文件里修改BOARD_ConfigMPU()函数,增加如下代码,确保全部1MB OCRAM地址空间(0x20200000开始)都是non-cacheable属性。
    1. <font size="3" face="微软雅黑">/* Region 6 setting: Memory with Normal type, not shareable, non-cacheable */
    2. MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U);
    3. MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1MB);</font>
    复制代码
    2.1.3 修改链接文件
      最后我们要在App工程的main函数源文件里将s_frameBuffer放在一个自定义的.frameBuffer段里,以便在App链接文件里将其放到OCRAM地址空间里(0x20200000 - 0x202FFFFF)。
      main函数源文件中的修改:
    1. <font size="3" face="微软雅黑">__no_init uint32_t s_frameBuffer[APP_IMG_HEIGHT][APP_IMG_WIDTH] @ ".frameBuffer";</font>
    复制代码
     App工程链接文件中的修改:
    1. <font size="3" face="微软雅黑">define symbol m_data2_start  = 0x20200000;
    2. define symbol m_data2_end    = 0x202FFFFF;

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

    4. place in DATA2_region        { section .frameBuffer };</font>
    复制代码
    2.2 编写Python脚本生成frameBuffer数据
    2.2.1 风景图片数据
      我们可以从网上找一张.jpg格式图片,将其尺寸裁剪到480x480,然后借助Pillow里的Image库将其转成XRGB8888格式的binary文件,对应Python脚本(脚本名为convert_jpeg_to_xrgb8888.py)用法和源代码如下:
    3.png
    1. <font size="3" face="微软雅黑">import sys, os
    2. import argparse
    3. from PIL import Image

    4. class ConvertJpegToXrgb8888(object):
    5.     def __init__(self):
    6.         pass

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

    12.     def run(self):
    13.         args = self._read_options()
    14.         imgObj = Image.open(args.input)
    15.         pixelBuf = imgObj.getdata()
    16.         for i in range(len(pixelBuf)):
    17.             for j in range(len(pixelBuf[i])):
    18.                 args.output.write(chr(pixelBuf[i][len(pixelBuf[i]) - j - 1]))
    19.             args.output.write(chr(0))
    20.         args.output.close()

    21. if __name__ == "__main__":
    22.     exit(ConvertJpegToXrgb8888().run())</font>
    复制代码
    2.2.2 RGB测试数据
      此外我们还需要一个脚本,能够很容易地修改生成指定的RGB测试数据,用于定位亮点问题,对应Python脚本(脚本名为generate_xrgb8888.py)用法和源代码如下:
    4.png
    1. <font size="3" face="微软雅黑">import sys, os
    2. import argparse

    3. class GenerateXrgb8888(object):
    4.     def __init__(self):
    5.         pass

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

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

    12.     def run(self):
    13.         args = self._read_options()
    14.         for i in range(160):
    15.             for j in range(480):
    16.                 args.output.write(self._make_xrgb8888(j%256, 0, 0))
    17.         for i in range(160):
    18.             for j in range(480):
    19.                 args.output.write(self._make_xrgb8888(0, j%256, 0))
    20.         for i in range(160):
    21.             for j in range(480):
    22.                 args.output.write(self._make_xrgb8888(0, 0, j%256))
    23.         args.output.close()

    24. if __name__ == "__main__":
    25.     exit(GenerateXrgb8888().run())</font>
    复制代码
    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。
    5.png
    这时候你可以看到LCD的显示变成了图片:
    6.png
    2.3.2 显示RGB测试数据
      从上一节测试的真实图片显示效果上看,似乎看不出明显的亮点问题,这说明亮点在特定RGB数据内容显示的时候才会显现出来,那么我们现在的任务就是要找到这个显现条件,这时候需要修改generate_xrgb8888.py脚本来反复做实验。
      所以痞子衡就不断地修改脚本、生成数据、下载数据,功夫不负有心人,痞子衡找到了亮点复现规律。
    7.png
    三、原因分析
      痞子衡发现的亮点规律是当横向某两个连续渐变像素点RGB任一分量出现多bit由1向0跳变时(比如前一个像素点B分量是8'b01111111,后一个像素点B分量是8'b10000000),则后一个像素点必是亮点,这个亮点像素点最终显示的B分量极可能变成了8'b11111111。
    8.png
     所以分析下来应该是DCLK信号的极性设置在屏的驱动IC和i.MXRT1060的eLCDIF模块里不匹配,RGB数据线采样时机错了,导致实际显示的RGB数据发生了错误。
      在SDK的elcdif_rgb example里关于eLCDIF模块信号输出的极性设置如下,这里需要注意的是kELCDIF_DriveDataOnRisingClkEdge是置1(即上沿数据输出,下沿数据保持的意思)。
    1. <font size="3" face="微软雅黑">#define APP_POL_FLAGS (kELCDIF_DataEnableActiveHigh | kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DriveDataOnRisingClkEdge)</font>
    复制代码
    这是i.MXRT1060 eLCDIF极性配置相关:
    9.png
    这是OTA5180A芯片的默认极性配置时序图:
    10.png
    SDK里的极性设置与i.MXRT1060-EVK标配的LCD屏(RK043FN02H-CT)里的驱动芯片OTA5180A默认配置是相吻合的。
      我们现在再来看看SDK里的极性设置与客户LCD屏的驱动芯片ST7701S的极性配置是否匹配,客户设置了ST7701S的IM[3:0]状态为4'b1010,即RGB模式输出,且PCLK是下沿数据输入,上沿数据保持(Latch),因此跟SDK里的极性设置是反相的。
    11.png
     所以最终的解决方法就是要么将ST7701S的IM[3:0]状态设为4'b0010,要么在App代码里将APP_POL_FLAGS定义改用kELCDIF_DriveDataOnFallingClkEdge。


    作者:痞子衡           文章出处:点击

    qiandao qiandao
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2025-6-10 23:03
  • 签到天数: 1502 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    97

    主题

    4688

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    10080
    最后登录
    2025-7-2
    发表于 2020-4-13 22:59:50 | 显示全部楼层
    学习了啊
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-19 04:56 , Processed in 0.085791 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表