联博统计接口:痞子衡嵌入式:降低刷新率是定位LCD花屏显示问题的第一大法(i.MXRT1170, 1280x480 LVDS)

admin 2天前 科技 2 1

  人人好,我是痞子衡,是正经搞手艺的痞子。今天痞子衡给人人分享的是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花屏显示问题的第一大法(i.MXRT1170, 1280x480 LVDS) 第1张

三、引出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刷新率下,开机动画效果显示杠杠的。

联博统计接口:痞子衡嵌入式:降低刷新率是定位LCD花屏显示问题的第一大法(i.MXRT1170, 1280x480 LVDS) 第2张

  现在把代码下载进通俗SDR Flash的板子试试,可以看到LCD显示花屏了,完全没有图像的影子,这时候该怎么定位问题?

联博统计接口:痞子衡嵌入式:降低刷新率是定位LCD花屏显示问题的第一大法(i.MXRT1170, 1280x480 LVDS) 第3张

四、实验降低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主页、微信民众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

联博统计接口:痞子衡嵌入式:降低刷新率是定位LCD花屏显示问题的第一大法(i.MXRT1170, 1280x480 LVDS) 第4张

,

Allbet

www.ysmdfhk244.com欢迎进入欧博平台(Allbet Gaming),欧博平台开放欧博(Allbet)开户、欧博(Allbet)代理开户、欧博(Allbet)电脑客户端、欧博(Allbet)APP下载等业务。

网友评论

  • (*)

最新评论

  • 欧博APP下载 2020-07-02 00:02:26 回复

    欧博会员开户欢迎进入欧博会员开户(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。这个网站很全

    1

站点信息

  • 文章总数:548
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1031
  • 评论总数:156
  • 浏览总数:4014