搜索   Search
联系我们   Contact

精读OSAL --DMA方式串行通信(_hal_uart_dma.c) TI

发布:2015-05-19 23:38 点击:

跳过初始化的内容.

先讲接收操作:

DMA方式的具体操作可以查看DMA的相关内容.

这里有意思的是缓冲区算法的实现,和中断方式还是有些区别.

               |BAUD|DXBUF|

               |..........|............|

               |..........|............|

               |..........|............|

               |..........|............|

               |..........|............|

               |..........|............|

               |..........|............|

    Tail--> |..........|............|

               |..........|............|

               |..........|............|

               |..........|............|

               |..........|............|<--Head

               |..........|............|

 

读函数里只对Head操作,每读一字节就上移一字节,清BAUD,读到tail就停止了.

那么为啥要记录波特率呢?我想了好久也没明白.在DMA里会具体说.

代码不上了.

 

这里说Tail怎么变化,其实Tail指明的就是数据尾在哪里.

来自串口的数据通过DMA直接传到Tail所指的内容.不过因为

DMA所以Tail不能递增.那么Tail什么时候改呢?

是在每个OSAL的循环里:HalUARTPollDMA()里 ,调用HalUARTRxAvailDMA()里.

那么怎么知道数据写到哪呢?这就是为什么要存BAUD的原因.

算法里取反存起来作为没数据的标记,当DMA传输时,直接将BAUD和DxBUF一起

传过来存起来,于是BAUD就变成正常的BAUD值,而不是取反值.

然后POLL里就查找那个还是反的BAUD就是没数据.Tail就改到前一个..

都在HalUARTRxAvailDMA().

 

 

到这读操作完成了,下面是DMA的写..

里面有说写操作推荐 用 中断 方式,这和上篇没区别就不提了.

这里说DMA方式:

                     |SEL=0|SEL=1|

                     |IDX=n |IDX=m|

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

    (IDX=n)-->|...........|...........|

                     |...........|...........|

                     |...........|...........|<--(IDX=m)

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

                     |...........|...........|

算法理角了也很简单,IDX是记录侍发数据长度,发送完一列就清IDX,同时改SEL指向另一列..

不过看代码还是有点难..所以来注释:

[cpp] view plaincopy
 
  1. static void HalUARTArmTxDMA(void)  
  2. {  
  3.   halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX);  
  4.   HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]);  
  5.   HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]);  
  6.   
  7.   dmaCfg.txSel ^= 1; //注意这里取反了txSEL.  
  8.   dmaCfg.txTrig = 1;  
  9.   HAL_DMA_ARM_CH(HAL_DMA_CH_TX);  
  10.   
  11.   HalUARTPollTxTrigDMA();  
  12.   
  13.   if (DMA_PM)  
  14.   {  
  15.     HAL_UART_DMA_SET_RDY_OUT();  
  16.   }  
  17. }  

每次调用完,SEL都改成另一个.这是要注意.

[html] view plaincopy
 
  1. static void HalUARTPollTxTrigDMA(void)  //这个也是在POLL里调用.  
[html] view plaincopy
 
  1. {  
  2.   if ((UxCSR & CSR_TX_BYTE) == 0)  // If no TXBUF to shift register transfer, then TXBUF may be MT.  
  3.   {  
  4.     if ((dmaCfg.txTick == 0) || ((uint8)(ST0 - dmaCfg.txTick) > HAL_UART_TX_TICK_MIN))  
  5.     {  
  6.       dmaCfg.txTick = 0;  
  7.   
  8.       if (dmaCfg.txTrig && HAL_DMA_CH_ARMED(HAL_DMA_CH_TX)) //这里判断是否要人工触发DMA传输  
  9.       {  
  10.         HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX);  
  11.       }  
  12.       dmaCfg.txTrig = 0;  
  13.     }  
  14.   }  
  15.   else  
  16.   {  
  17.     UxCSR = (CSR_MODE | CSR_RE);  // Clear the CSR_TX_BYTE flag.  
  18.     dmaCfg.txTick = ST0;  
  19.   
  20.     if (dmaCfg.txTick == 0)  // Reserve zero to signify that the minimum delay has been met.  
  21.     {  
  22.       dmaCfg.txTick = 0xFF;  
  23.     }  
  24.   }  
  25. }  


 

[cpp] view plaincopy
 
  1. void HalUART_DMAIsrDMA(void)  
  2. {  
  3.   if (dmaCfg.txIdx[dmaCfg.txSel]) //这里判断是否还有数据要传输  
  4. {  
  5.     // If there is more Tx data ready to go, re-arm the DMA immediately on it.  
  6.     HalUARTArmTxDMA();  
  7.   
  8.     // Indicate that the Tx buffer just finished is now free (re-arming did a ^= toggle of txSel).  
  9.     dmaCfg.txIdx[dmaCfg.txSel] = 0;//因为这前ARM的时候,SEL取反了,  
  10.                                    //刚刚完成DMA才进中断,在上面ARM中SEL又取反了,那么  
  11.    
  12.    
  13.                    //此列已发送所有数据,IDX清零.  
  14.  }  
  15.   else  
  16.   {  
  17.     dmaCfg.txIdx[(dmaCfg.txSel ^ 1)] = 0;  // Indicate that the Tx buffer just finished is now free.  
  18. // 当前没数据,因为没有再ARM,所以要取反清零.  
  19. // Clear the CSR_TX_BYTE flag & start the txTick to allow the possibility of an immediate  
  20. // manual trigger from the next Write(), if it occurs more than one character time later.  
  21.     HalUARTPollTxTrigDMA();  
  22.   }  
  23.   
  24.   dmaCfg.txMT = TRUE;  // Notify CB that at least one Tx buffer is now free to use.  
  25. }  


 

[html] view plaincopy
 
  1. static uint16 HalUARTWriteDMA(uint8 *buf, uint16 len)  
  2. {  
  3.   txIdx_t txIdx;  
  4.   uint8 txSel;  
  5.   halIntState_t his;  
  6.   
  7.   HAL_ENTER_CRITICAL_SECTION(his);  
  8.   txSel = dmaCfg.txSel;  
  9.   txIdx = dmaCfg.txIdx[txSel];  
  10.   HAL_EXIT_CRITICAL_SECTION(his);  
  11.   
  12.   // Enforce all or none.  
  13.   if ((len + txIdx) > HAL_UART_DMA_TX_MAX)  
  14.   {  
  15.     return 0;  
  16.   }  
  17.   
  18.   (void)memcpy(&(dmaCfg.txBuf[txSel][txIdx]), buf, len);  
  19.   
  20.   HAL_ENTER_CRITICAL_SECTION(his);  
  21.   /* If an ongoing DMA Tx finished while this buffer was being *appended*, then another DMA Tx  
  22.    * will have already been started on this buffer, but it did not include the bytes just appended.  
  23.    * Therefore these bytes have to be re-copied to the start of the new working buffer.  
  24.    */  
  25.   if (txSel != dmaCfg.txSel)//这里是判断这个过程是否有中断发生,如果有SEL不同,要重要整理过数据.  
  26.    {  
  27.     HAL_EXIT_CRITICAL_SECTION(his);  
  28.     txSel ^= 1;  
  29.   
  30.     (void)memcpy(&(dmaCfg.txBuf[txSel][0]), buf, len);  
  31.     HAL_ENTER_CRITICAL_SECTION(his);  
  32.     dmaCfg.txIdx[txSel] = len;  
  33.   }  
  34.   else  
  35.   {  
  36.     dmaCfg.txIdx[txSel] = txIdx + len;  
  37.   }  
  38.   
  39.   // If there is no ongoing DMA Tx, then the channel must be armed here.  
  40.   if (dmaCfg.txIdx[(txSel ^ 1)] == 0)  
  41.   {  
  42.     HAL_EXIT_CRITICAL_SECTION(his);  
  43.     HalUARTArmTxDMA();  
  44.   }  
  45.   else  
  46.   {  
  47.     dmaCfg.txMT = FALSE;  
  48.     HAL_EXIT_CRITICAL_SECTION(his);  
  49.   }  
  50.   return len;  
  51. }  


到此对DMA的UART就没什么疑问了.

 


关闭 大豪方案承接以下业务:

单片机开发
智能家居方案开发
ARM软件开发
手机APP软件开发
电子产品电路设计
电子产品开发
无线控制系统开发
产品老化测试系统定制
单片机工控系统定制
电子产品合作开发
动静态数据采集系统
应力应变测试开发
欢迎新老客户来电咨询! 13530382506