主控为STM32F429BI,外挂32位SDRAM,请教一下:当移植了FreeRTOS和ucGUI后,在SDRAM中开辟一片存储区域作为显存,FreeRTOS的显示任务不断往SDRAM写入数据,而STM32的LTDC模块从SDRAM读出数据并传输到LCD上显示,这之间是不是有冲突呢?因为现在LCD屏幕有跳动现象,我是这么想的,显示任务不断的往SDRAM写入数据,必然触发SDRAM的写入时序,而LTDC在从SDRAM读取数据时必然触发读出时序,这两者之间如果没有互斥信号量处理的话,应该会导致时序异常。没有这方面的经验,不知道我的想法是否正确,还请过往的大侠指点迷津,从整体的概念上指点一下就行,谢谢了! |
谢谢您的回复!
问题找到了:FMC读写数据这两个函数的问题
显示格式是RGB888的,于是在SDRAM里像素是24位的,与32位的AHB接口之间存在一个转换过程,来来回回的读写造成了“AHB总线冲突”,现在改成ARGB8888格式了,alpha填充0xFF就好了,这样读写像素的速度就提高了若干倍,目前显示"hello, world"和"毫秒表"都是没有问题的,目前是这样的状况,测试过程中发现问题的话我再回来补充。
再次感谢各位这些天的耐心交流!
评分
查看全部评分
vTaskDelay(1000);
// GUI_DispStringAt("Hello, World!", 200, 200);
lcdisplay_red();
LTDC_LayerAddress(LTDC_Layer1, SDRAM_BANK1_ADDR + AT800480_WIDTH * AT800480_HEIGHT * 0);
LTDC_LayerPosition(LTDC_Layer1, 0, 0);
LTDC_ReloadConfig(LTDC_IMReload);
}
以上是LCD任务的代码:
GUI_DispStringAt("Hello, World!", 200, 200); ===> ucgui往SDRAM写入字符串
lcdisplay_red(); ===> 往SDRAM写入半屏红色
两个写入函数任选其一,LCD显示就会跳动;
如果没有这两个写入函数的话,显示正常。
我猜想是,LTDC周期性的通过DMA从SDRAM读取数据后显示,一旦有写入动作而没有互斥处理的话,势必会出现时序上的冲突。
不知道这样分析是否正确,还请大家帮忙,谢谢了!
把ReadBurst配置为FMC_SDRAM_RBURST_ENABLE就解决了。(以下是我用的是ST32Cube生成的代码)
hsdram1.Init.SDBank = FMC_SDRAM_BANK2;
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_3;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
别外,LTDC需要实时的从SDRAM读取显存数据发送到RGB接口,以800*600的16位色屏为例,每秒读取的数据量高达28MB,读取间隔远小于1us,所以用信号量互斥是不实现的。
评分
查看全部评分
FMC 的每一个管脚都只有一定量的通信带宽。如果两个 DMA 都在访问同一块内存,这些访问就需要争抢通信带宽,发生冲突。
SDRAM 在读取的时候需要先打开页面,这个过程远远比 SDRAM 数据传输速率要慢得多,在 SDR SDRAM 上一般在 10-15 倍左右,DDR3 可以接近 20-30 倍,DDR4 直接 40 倍起跳。如果两个 DMA 所访问的内容不在同一页,那就需要不断地打开关闭页面,访问速度更慢。电脑显卡用的 GDDR SDRAM 最大的特点是支持同时打开两页,避免了这个瓶颈。
至于互斥信号量,bus matrix 是支持先来先服务排队和自动生成等待状态的,所以说一般用不到信号量,排队等数据即可。
你的这个使用场景之下,建议你考虑把程序数据放到 SDRAM 里面,使用片内 SRAM 来做 framebuffer。SRAM 本来就比 SDRAM 快,而且不会因为来回跳地址而大幅度减速。
评分
查看全部评分
STM32一般的内部SRAM只有几百KB,用来做显示缓存怕是不够哦,这款STM32F429BI只有256KB的SRAM,以800*480的8寸屏(RGB888)计算,800 * 480 * 4就超出了SRAM的范围。
评分
查看全部评分
如果处理得当,大量的显示数据可以直接从 Flash 里面 DMA 出去。这样的话依然可以支持 800x480 但 SRAM 占用就不多了。
从flash读出,然后在LCD上显示,这个是没有问题的,但是不断对flash进行写入操作是不现实的吧。
我也是这么考虑的,移植的freertos和ucgui,我是这么想的:在ucgui的最底层描点函数和ltdc的dma传输结束之间互斥操作,这两天有点其他事情,过两天我试试,到时候还请多多指教。
把窗口分块处理:整个生命周期里面不动的内容放在 Flash 里面,需要运行时填充的数据放在 RAM 里面。
我这个案子的图形数据变化比较大,数据放在内部flash的比较困难,最终方案是外挂SDRAM和nand flash,在nand flash上做文件系统,存储比如图片,图表这样的文件,根据操作显示在lcd上。内部flash只有2MB,24位的位图也存不了几张。
如果是这样的话,那必须拿外挂 SDRAM 当 VRAM,就要考虑 DMA 互锁了。两边都是顺序访问的话,只要调度得当,一般不会卡顿的。另外可以考虑用一个定时器来控制帧速率,定时器设定成 60Hz,每次定时器触发先启动 LTDC 把画面更新了,然后跑业务逻辑更新界面内容,渲染到内存,把 LTDC 的内存打开,准备下一帧。
还有一种方法:换主控,譬如全志 V3s,譬如 NXP i.MX233。这些主控用的 DRAM 要比 STM32 的快一些(前者是片内自带 64MB LPDDR2,后者是外挂 DDR)而且有都专门的 2D 图形加速单元。V3s 的主频足有 1.2GHz 而 i.MX233 也能上至少 500MHz。这两个芯片都是设计拿来跑 Linux 的,图形体系可能还好开发一点,有现成的 Qt 和 Cairo 体系可以用,甚至可以用 Chrome OS 的体系设计来偷懒(系统启动直接就是全屏的网页浏览器打开 localhost,实际界面和功能完全用 HTML5 + CSS + JS 做,至于和硬件的交互就靠 CGI)
评分
查看全部评分
好的,谢谢您的回复。我再排查一下,有结果后回来给你回复!
那么,我的问题可能是这样的,LTDC的使能和禁止应该不合理,不能用LTDC_Cmd(DISABLE);LTDC_Cmd(ENABLE);这样的语句来操作吧,只要能把DMA传输关掉,把FMC的接口干净的留给GUI来写入数据应该会有不错的效果。
现在还没找到合理的暂停LTDC数据传输的方法,还请各位多多交流。
闪动:红色背景色,但是会像幕布那样刷屏,没有其他杂色