STM32 UART的DMA模式,为何跟malloc函数相关

2019-12-12 18:20发布

各位好,感谢关注,直入主题:
产品有2个功能:
1,网络模块,接收指令和系统设置;其中有个parse_date_time函数,作用是把系统设置的时间,写入RTC中;
解析时,使用了两种方式将时间的字串保存;
void parse_date_time(char *str)
{
方式1:
        char point[100]={0};
        memcpy(point,str,datasize);
        /**************
        解析日期和时间
        **************/
方式2:
        char *point=NULL;
        point=malloc(100);
        memcpy(point,str,datasize);

        /**************
        解析日期和时间
        **************/
        free(point);
        point = NULL;
}

2,串口模块,使用DMA进行与另一板子的通信;

3,使用1中的方式2(malloc),串口DMA收发正常;
     使用1中的方式1(数组),串口DMA收发失败;

4,觉得可能是parse_date_time函数作妖,暂时将该函数屏蔽掉(整份代码中,没有malloc);串口DMA收发失败;
5,在其他不相干的函数,尝试先malloc,接着就free,不做任何操作,串口DMA收发正常;

表面现象:
        串口的DMA收发,一定要有malloc;

猜测:
        如果没有malloc,是否串口的DMA收发的内存空间,在编译的时候,就没有被分配?编译的时候优化掉了dma的内存空间?(哪怕优化级别为-O0)

很是困惑,希望得到大家的指点,谢谢。
   
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
41条回答
lingdianhao
1楼-- · 2019-12-14 19:37
cyzc2008 发表于 2019-3-10 01:32
谢谢回复,查看了两种方式下的内存地址,都是偶数。不知道从哪查了~  ...

你说的偶数是对齐还是我之前说的6内存块区域。你是用407还是103?4079有CCM才有可能有问题。
dukelec
2楼-- · 2019-12-14 20:49
本帖最后由 dukelec 于 2019-3-10 11:13 编辑

不要侷限在表像。

曾經,同事移植的 uboot 代碼,改一下 printf 和它相臨代碼的位置,系統就起不來了,從語言本身看不出任何問題,他當時帶着問題繼續推進,遇到越來越多的莫名奇妙的問題。
後來,我幫他找問題,首先回到最開始 printf 出問題的代碼,先調試找到表像問題的發生點,發現是一個內存變量不正常,不知道是誰修改的,然後再查本質,用對比方法追蹤到何時被修改,追蹤發現是該變量存放在一個 cache 行結尾,該 cache 行前部分數據用來做 DMA 交換,導致該變量在刷 cache 的時候被修改了。最後把所有 cache line 結尾對齊處理解決問題。

回到你的問題,你要去對比不同代碼對 DMA 和 UART 寄存器的操作的區別,以及內存數據的區別。
雖然 STM32 沒有 cache, 但隨便哪裏用錯指針、堆棧溢出或數組溢出都會影響無關模塊的代碼運行。

還有,DMA 的內存空間是你自己提前準備的,和編譯器優化沒有半點關係,你要惡補底層知識。
cyzc2008
3楼-- · 2019-12-14 23:01
 精彩回答 2  元偷偷看……
cyzc2008
4楼-- · 2019-12-15 04:41
dukelec 发表于 2019-3-10 11:02
不要侷限在表像。

曾經,同事移植的 uboot 代碼,改一下 printf 和它相臨代碼的位置,系統就起不來了,從 ...

感谢回复~
zchong
5楼-- · 2019-12-15 05:07
两个方面:1、dma所用的内存不能是局部变量,也就是说不能在栈空间中;2、dma使用的内存地址范围是有要求的,不是所有RAM都用来dma的。
cyzc2008
6楼-- · 2019-12-15 10:52
zchong 发表于 2019-3-10 11:25
两个方面:1、dma所用的内存不能是局部变量,也就是说不能在栈空间中;2、dma使用的内存地址范围是有要求的 ...

谢谢,感谢您的回复。

一周热门 更多>