你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

请教STM32外挂SDRAM的读写冲突问题  

[复制链接]
tovax 提问时间:2018-2-28 11:53 /
主控为STM32F429BI,外挂32位SDRAM,请教一下:当移植了FreeRTOS和ucGUI后,在SDRAM中开辟一片存储区域作为显存,FreeRTOS的显示任务不断往SDRAM写入数据,而STM32的LTDC模块从SDRAM读出数据并传输到LCD上显示,这之间是不是有冲突呢?因为现在LCD屏幕有跳动现象,我是这么想的,显示任务不断的往SDRAM写入数据,必然触发SDRAM的写入时序,而LTDC在从SDRAM读取数据时必然触发读出时序,这两者之间如果没有互斥信号量处理的话,应该会导致时序异常。没有这方面的经验,不知道我的想法是否正确,还请过往的大侠指点迷津,从整体的概念上指点一下就行,谢谢了!
收藏 1 评论24 发布时间:2018-2-28 11:53

举报

24个回答
tovax 回答时间:2018-3-21 15:55:31
dsjsjf 发表于 2018-3-21 11:28
多个任务对同一个资源(SDRAM)的操作,需要用到互斥信号量

谢谢您的回复!
问题找到了:FMC读写数据这两个函数的问题
显示格式是RGB888的,于是在SDRAM里像素是24位的,与32位的AHB接口之间存在一个转换过程,来来回回的读写造成了“AHB总线冲突”,现在改成ARGB8888格式了,alpha填充0xFF就好了,这样读写像素的速度就提高了若干倍,目前显示"hello, world"和"毫秒表"都是没有问题的,目前是这样的状况,测试过程中发现问题的话我再回来补充。
再次感谢各位这些天的耐心交流!

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3 结贴奖励

查看全部评分

tovax 回答时间:2018-3-8 21:05:10
        while (1) {
                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读取数据后显示,一旦有写入动作而没有互斥处理的话,势必会出现时序上的冲突。
不知道这样分析是否正确,还请大家帮忙,谢谢了!
hjj12 回答时间:2018-3-14 11:09:21
估计是SDRAM的ReadBurst配置不对导致的。我也碰到过该问题,显示屏是800*600分辨率的,只要对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,所以用信号量互斥是不实现的。

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

maxtch 回答时间:2018-2-28 17:09:52
如此操作冲突是必然的,而且同时存在两方面的冲突:内存带宽争夺和 SDRAM 页面访问争夺。

FMC 的每一个管脚都只有一定量的通信带宽。如果两个 DMA 都在访问同一块内存,这些访问就需要争抢通信带宽,发生冲突。

SDRAM 在读取的时候需要先打开页面,这个过程远远比 SDRAM 数据传输速率要慢得多,在 SDR SDRAM 上一般在 10-15 倍左右,DDR3 可以接近 20-30 倍,DDR4 直接 40 倍起跳。如果两个 DMA 所访问的内容不在同一页,那就需要不断地打开关闭页面,访问速度更慢。电脑显卡用的 GDDR SDRAM 最大的特点是支持同时打开两页,避免了这个瓶颈。

至于互斥信号量,bus matrix 是支持先来先服务排队和自动生成等待状态的,所以说一般用不到信号量,排队等数据即可。

你的这个使用场景之下,建议你考虑把程序数据放到 SDRAM 里面,使用片内 SRAM 来做 framebuffer。SRAM 本来就比 SDRAM 快,而且不会因为来回跳地址而大幅度减速。

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

tovax 回答时间:2018-3-2 11:48:41
maxtch 发表于 2018-2-28 17:09
如此操作冲突是必然的,而且同时存在两方面的冲突:内存带宽争夺和 SDRAM 页面访问争夺。

FMC 的每一个管 ...

STM32一般的内部SRAM只有几百KB,用来做显示缓存怕是不够哦,这款STM32F429BI只有256KB的SRAM,以800*480的8寸屏(RGB888)计算,800 * 480 * 4就超出了SRAM的范围。
xmshao 回答时间:2018-3-2 14:30:31
写SDRAM 和 LTDC从SDRAM读数据要考虑互斥错开操作。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

maxtch 回答时间:2018-3-2 18:45:01
tovax 发表于 2018-3-2 11:48
STM32一般的内部SRAM只有几百KB,用来做显示缓存怕是不够哦,这款STM32F429BI只有256KB的SRAM,以800*480 ...

如果处理得当,大量的显示数据可以直接从 Flash 里面 DMA 出去。这样的话依然可以支持 800x480 但 SRAM 占用就不多了。
tovax 回答时间:2018-3-5 09:15:27
maxtch 发表于 2018-3-2 18:45
如果处理得当,大量的显示数据可以直接从 Flash 里面 DMA 出去。这样的话依然可以支持 800x480 但 SRAM  ...

从flash读出,然后在LCD上显示,这个是没有问题的,但是不断对flash进行写入操作是不现实的吧。
tovax 回答时间:2018-3-5 09:18:37
xmshao 发表于 2018-3-2 14:30
写SDRAM 和 LTDC从SDRAM读数据要考虑互斥错开操作。

我也是这么考虑的,移植的freertos和ucgui,我是这么想的:在ucgui的最底层描点函数和ltdc的dma传输结束之间互斥操作,这两天有点其他事情,过两天我试试,到时候还请多多指教。
maxtch 回答时间:2018-3-5 12:29:28
tovax 发表于 2018-3-5 09:15
从flash读出,然后在LCD上显示,这个是没有问题的,但是不断对flash进行写入操作是不现实的吧。 ...

把窗口分块处理:整个生命周期里面不动的内容放在 Flash 里面,需要运行时填充的数据放在 RAM 里面。
tovax 回答时间:2018-3-5 14:28:31
maxtch 发表于 2018-3-5 12:29
把窗口分块处理:整个生命周期里面不动的内容放在 Flash 里面,需要运行时填充的数据放在 RAM 里面。 ...

我这个案子的图形数据变化比较大,数据放在内部flash的比较困难,最终方案是外挂SDRAM和nand flash,在nand flash上做文件系统,存储比如图片,图表这样的文件,根据操作显示在lcd上。内部flash只有2MB,24位的位图也存不了几张。
maxtch 回答时间:2018-3-5 16:58:47
tovax 发表于 2018-3-5 14:28
我这个案子的图形数据变化比较大,数据放在内部flash的比较困难,最终方案是外挂SDRAM和nand flash,在na ...

如果是这样的话,那必须拿外挂 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)

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

tovax 回答时间:2018-3-6 10:05:55
maxtch 发表于 2018-3-5 16:58
如果是这样的话,那必须拿外挂 SDRAM 当 VRAM,就要考虑 DMA 互锁了。两边都是顺序访问的话,只要调度得当 ...

好的,谢谢您的回复。我再排查一下,有结果后回来给你回复!
tovax 回答时间:2018-3-10 09:59:26
目前的测试结果是:在GUI_DispStringAt前把LTDC禁止掉,写入数据之后把LTDC使能,这样就没有了跳动,但是由于LTDC使能后重新加载显示数据,显示会有明显的闪动刷屏现象。
那么,我的问题可能是这样的,LTDC的使能和禁止应该不合理,不能用LTDC_Cmd(DISABLE);LTDC_Cmd(ENABLE);这样的语句来操作吧,只要能把DMA传输关掉,把FMC的接口干净的留给GUI来写入数据应该会有不错的效果。
现在还没找到合理的暂停LTDC数据传输的方法,还请各位多多交流。
tovax 回答时间:2018-3-10 13:08:32
跳动:红色背景色,但是间歇性的跳出部分绿色、蓝色
闪动:红色背景色,但是会像幕布那样刷屏,没有其他杂色
tovax 回答时间:2018-3-10 13:23:14
这样的情况是不是不该去禁止LTDC,而是禁止对应的显示层呢?
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版