查看: 9832|回复: 4

zstack-2530-dma-uart-两线串口-大量数据的一个伪bug

[复制链接]
lhdzwkk 发表于 2011-11-7 16:18:34 | 显示全部楼层 |阅读模式
又来说一个比较偏的问题..
//---------------------------------
我认为你已经基本了解了dma传输,和协议栈下uart利用dma传输的机制
然后我们来谈谈这个伪bug:
//---------------------------------
先来看看这个结构体:
  1. typedef struct
  2. {
  3.   uint16 rxBuf[HAL_UART_DMA_RX_MAX];
  4.   rxIdx_t rxHead;
  5.   rxIdx_t rxTail;
  6.   uint8 rxTick;
  7.   uint8 rxShdw;

  8.   uint8 txBuf[2][HAL_UART_DMA_TX_MAX];
  9.   txIdx_t txIdx[2];
  10.   volatile uint8 txSel;
  11.   uint8 txMT;
  12.   uint8 txTick;
  13.   volatile uint8 txShdw;  // Sleep Timer LSB shadow.
  14.   volatile uint8 txShdwValid; // TX shadow value is valid
  15.   uint8 txDMAPending;     // UART TX DMA is pending

  16.   halUARTCBack_t uartCB;
  17. } uartDMACfg_t;
复制代码
rxBuf[HAL_UART_DMA_RX_MAX]就是缓存,数组大小是256
只关注rxHead,rxTail只是为了判断超时用的,有了rxHead数组就变成链表了
然后简单说下,
设备上电,rxHead=0,DMA传输指针dmhead=0;

rxHead在rxBuf被读取时++
dmhead在串口有数据时++
情况1:
接收一个字节,rxHead=0,dmhead=1;读走这个字节rxHead=1,dmhead=1;
再接收一个字节,rxHead=1,dmhead=2;读走这个字节rxHead=2,dmhead=2;
再接收254个字节,rxHead=2,dmhead=0;再读走着254个字节,rxHead=0,dmhead=0;

情况2:
然而如果一下子接收了257个字节!!rxHead=0,dmhead=1;读取这257个字节,实际只能读到256个,rxHead=0,dmhead=1;而且读取的第一个字节rxBuf[0]会被第257个字节覆盖
然后再接收1个字节,rxHead=0,dmhead=2;这时候无法读走这个字节,因为读取函数中判断rxBuf[0]无效,而实际接收位置是rxBuf[1]

产生这种情况的根本原因是:
  1.   else if (cnt >= HAL_UART_DMA_HIGH)
  2.   {
  3.     evt = HAL_UART_RX_ABOUT_FULL;
  4.     PxOUT |= HAL_UART_Px_RTS;  // Disable Rx flow.
  5.   }
复制代码
在串口缓存快满的时候,会Disable Rx flow,然后
  1. PxOUT &= ~HAL_UART_Px_RTS;  // Re-enable the flow on any read.//keke
复制代码
读取函数后重新使能
在两线串口下这个功能是没有的
所以需要注意,不然就用额外的代码来解决,比如关dma中断

即使是4线串口也存在这个问题,因为
  1. PxOUT |= HAL_UART_Px_RTS;  // Disable Rx flow.
复制代码
这个是在主osal循环里面,不可能及时执行到
所以一切都是浮云

有人说我缓冲256个字节不会满,那当然没问题,
也注意这种情况,你在处理一个任务id的某事件的时候,耗时比较长,同时有串口数据过来,大量的短的串口数据可能使串口缓冲溢出!

有人说开串口中断吧不要dma了,ok很好,没有这个问题,因为dma传输是覆盖链表数据,而串口isr是不会覆盖的(没时间验证,个人推测)

自己mark
关于协议栈下的串口和dma,可以看看我写的日志:
http://user.qzone.qq.com/744721131/infocenter#!

欢迎大家测试和指正
kennan 发表于 2011-11-7 23:45:22 | 显示全部楼层
这个事情是的,不只是2530,所有的处理器都有这个问题啊。缓存满了就会出问题。实际上Zigbee的出发点就是小量偶发数据,你要真让串口疯狂发,不只是串口处理不过来,无线也处理不过来,那时候崩溃的不只是串口,是统统挂。
hygrand 发表于 2011-11-17 09:54:45 | 显示全部楼层
楼主能不能详细整理下DMA串口传输啊 协议栈下uart利用dma传输的机制呢 最近在这个地方卡住了 想同时运用两个串口工作
lizheng86312 发表于 2012-8-29 13:23:47 | 显示全部楼层
学到东西了。顶。。。
一月的萧邦 发表于 2013-4-15 17:46:03 | 显示全部楼层
顶一个,楼主分析的很好,我现在实际应用中就碰到了这个问题,最终只能自己增加代码来判断防止这个缓存溢出
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表