这段时间断断续续在搞F1C100s的ADC音频采集,使用FIFO中断的方法采集数据没问题(这里有一个小坑,FIFO中断中读数据时,我用结构体地址指向的方式将Rx寄存器的值读出,发现不管读几次都只能读出FIFO最后一个值,按理说每读一次Rx应该就从FIFO中取下一个数据才对。后来实在没法子,用了Read32()函数,就可以了。。。。),但使用DMA传输就不行了,DMA缓冲区的数据一大部分压根不变化。啃了好几遍手册,各个Channel都试了,仍不行。一开始以为又进了读FIFO之类的坑,但最后排查来排查去,问题应该是Cache的问题。
我是在RTT BSP中开发,在board.c对MMU的初始化函数中可以看到,32M的DDR是全部Cacheble的,RTT内存管理当然也是Cacheble,目标缓存是rt_malloc出来的,在DMA结束后,CPU操作这些缓存数据时使用的还是Cache中的数据,导致一致性问题。尝试了一下,在rt_hw_mmu_init中直接将mmu_enable_dcache()屏蔽掉后,编译运行一切正常。。
当然关掉dcache是不实际的,但我不知道什么指令能使Cache和内存同步,mmu.c中的mmu_clean_invalidated_dcache()函数和mmu_clean_dcache()函数等好像也不起作用,于是换一种方式,在mmu_init函数的mem_desc表中,添加一部分DDR地址为“RW_NCNB”,把DMA传输的目标地址指向这个区域,就没问题了。
离线
对cache的使用知识,是裸机开发ARM9必备啊。你可以从我的rtx+emwin包里,找到mmu_c.c和mmu_a.s,我把所有mmu操作的api都放在里边了。你这个情况,只要调用我的MMU_InvalidateDCacheArray函数,使dma访问过的ram对应的cache无效就行了。注意,“无效”和“清理”是两个截然不同的概念。
谢谢指点,对arm9刚接触很多都还不熟悉,尤其是底层方面,还得向各位大牛学习!
离线
cpu把数据写到内存,然后交给外设或dma,要用clean;
cpu读取由外设或dma放在ram的数据之前,要invalid;
dcacheinvalid和dcacheclean指令,要么是针对mva的,要么是针对cache-line的,要么就整个dcache
所以MMU_InvalidateDCacheArray函数封装了mva的遍历。
对ram变量也有cache-line对齐的要求,即变量或数组的大小和地址必须32字节对齐,否则会破坏变量。
感谢您的热心指导,受益匪浅!实测使用mmu_invalidate_dcache是正确的,之前测试不起作用是粗心了没有设置对DMA的目的地址,犯了低级错误
离线