打印
[STM32F4]

外扩SRAM通过DMA刷新TFT而导致DMA时序错误!

[复制链接]
3361|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
KC_CEC|  楼主 | 2014-2-27 11:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
现在我的目的是在SRAM中给TFT做一个二级缓存,这样可以提高TFT的局部刷新速度,并且目前这样的效果实现了还很不错。
不过仍然有两个疑问没有解决,先给大家说说我的实现步骤:
1、总体步骤
stm32f4----(通过FSMC)-------->更新SRAM中缓存内容----------(通过DMA)--------->刷新TFT屏
2、程序准备
要将SRAM想像成一个TFT,根据地址偏移算出对应的X,Y轴即可,所以之前在TFT画图的程序得对应修改为在SRAM画图的程序
,并且DMA使用M2M模式就可以了。
3、代码
DMA初始化:

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
        DMA_Cmd(DMA2_Stream2, DISABLE);
        DMA_DeInit(DMA2_Stream2);
        DMA_InitStructure.DMA_Channel = DMA_Channel_0;
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0;
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Bank1_LCD_D;
        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory;
        DMA_InitStructure.DMA_BufferSize = (uint32_t)30000;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//DMA_Priority_High;
                DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4;  
        DMA_Init(DMA2_Stream2, &DMA_InitStructure);  
在以后使用仅仅更改设备地址及设备大小就行了:
void LCD_DMA_TX(u32 Addr,u32 Size)
{
        DMA_Cmd(DMA2_Stream2, DISABLE);
         DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)Addr;
         DMA_InitStructure.DMA_BufferSize=(uint32_t)Size;
         DMA_Init(DMA2_Stream2,&DMA_InitStructure);
         DMA_Cmd(DMA2_Stream2,ENABLE);
}

4、问题
一、在使用void LCD_DMA_TX()这个函数后,必须在后面加入至少SysTick_DelayMS(10);的延时才能正常使用。
A、刚开始我以为是DMA初始化需要等待,于是我将SysTick_DelayMS(10)替换为:while(DMA_GetCmdStatus(DMA2_Stream2)!=ENABLE&&u32_i--);
这样子理论上来说,DMA已经完全稳定,但是还是显示不正常。
B、然后为了不堵塞CPU,我就100MS启动一次刷屏,理论上这样比SysTick_DelayMS(10)延时还多:
if(++count==10)
{
    count=0;
   void LCD_DMA_TX();
}
郁闷的是,这样还是不行。
C、最后我屏蔽掉了其他程序,排除其他部分的干扰。但问题依旧,唯有SysTick_DelayMS(10);这种方法坚挺!
二、ADC转换速度与带宽速度冲突
实际上,我刷新的SRAM中的内容是ADC采样的数据。之前一直保持的是1M的采样率多通道转换。
现在只要DMA刷屏一开启,就会使能ADC报警:overrun
后面想了想,有可能是DMA占用的总线带宽,使得剩下带宽读取ADC的速度已经跟不上ADC本身的采样率而导致ADC挂掉。
试了试果然是这样,但是这样ADC速度就下来了。
5、解答
请教各位大神,如何把那个该死的10MS延迟消掉?还有就是如何配置DMA才和ADC尽量不冲突?


沙发
ilovezeno| | 2014-2-27 12:51 | 只看该作者
是f1的双主访问fsmc的硬件bug导致的么?一般f1早期版本的的fsmc不能cpu和dma同时访问的,要死机。。。。似乎最新的芯片版本已经修复此bug。。。

使用特权

评论回复
板凳
KC_CEC|  楼主 | 2014-2-27 13:25 | 只看该作者
ilovezeno 发表于 2014-2-27 12:51
是f1的双主访问fsmc的硬件bug导致的么?一般f1早期版本的的fsmc不能cpu和dma同时访问的,要死机。。。。似 ...

是f4,应该还是我调用的问题

使用特权

评论回复
地板
KC_CEC|  楼主 | 2014-2-27 14:06 | 只看该作者
再次屏蔽与TFT有关的函数,只要在DMA中的数据没有被完全输出时使用了FSMC总线就会造成干涉。以至于屏幕上到处打点

使用特权

评论回复
5
KC_CEC|  楼主 | 2014-2-27 14:41 | 只看该作者
看来想通过DMA刷新屏幕的一部分,剩下部分直接用FSMC直接刷的方法虽然减轻了CPU的负荷。但是需要等待DMA传输完成才能使用FSMC

使用特权

评论回复
6
KC_CEC|  楼主 | 2014-2-27 15:10 | 只看该作者
然后把ADC恢复为1M,也可以正常运行了。看来还得仔细研究M4的总线结构啊。  
那么,结贴了

使用特权

评论回复
7
ilovezeno| | 2014-2-27 21:06 | 只看该作者
我感觉还是你程序的细节问题
因为f2上我也试过这样的操作,绝不会造成屏幕乱打点的事情的。如果cpu和DMA都要访问fsmc的话,两者会各自分享总线一半的时间,如果各个信号量设置无误,那么绝对不应该相互干扰的。如果干扰,那么就是硬件bug了,但是硬件勘误里没有这条啊

使用特权

评论回复
8
KC_CEC|  楼主 | 2014-2-28 09:32 | 只看该作者
ilovezeno 发表于 2014-2-27 21:06
我感觉还是你程序的细节问题
因为f2上我也试过这样的操作,绝不会造成屏幕乱打点的事情的。如果cpu和DMA都 ...

谢谢提醒,我再看看fsmc和dma的设置

使用特权

评论回复
9
KC_CEC|  楼主 | 2014-3-27 10:53 | 只看该作者
再次验证,在dma刷屏的同时再用fsmc刷屏会出现矛盾的。
现在取消dma,依然还是让fsmc做搬运工,速度反而比dma快得多了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

169

帖子

1

粉丝