分享

BLE协议栈——UART DMA工作方式

 堆泄露栈溢出 2016-10-11
一、UART的轮询过程:
osal_run_system( void )
{
......
Hal_ProcessPoll();
......
}

Hal_ProcessPoll()
{
...
/* UART Poll */ 
#if (defined HAL_UART) && (HAL_UART == TRUE) 
 HalUARTPoll(); 
#endif
}

HalUARTPoll()
{
......
#if HAL_UART_DMA 
 HalUARTPollDMA(); 
#endif
......
}

HalUARTPollDMA()
{
......
if ((evt != 0) && (dmaCfg.uartCB != NULL)) 
 { 
 dmaCfg.uartCB(HAL_UART_DMA-1, evt); 
 }
......
}
其中,dmaCfg.uartCB为初始化uart时的回调函数,我们写一个串口读写函数,利用
NPI_InitTransport( npiCBack_t npiCBack )即可将串口读写函数付给dmaCfg.uartCB,从而实现串口的轮询。

二、UART与DMA初始化
1、DMA初始化(包含UART初始化的部分代码)
HalDriverInit (void)
{
......
#if (defined HAL_DMA) && (HAL_DMA == TRUE)
   // Must be called before the init call to any module that uses DMA.
   HalDmaInit();
#endif
......
#if (defined HAL_UART) && (HAL_UART == TRUE)
  HalUARTInit();
#endif
......
}

HalUARTInit()
{
......
#if HAL_UART_DMA
  HalUARTInitDMA();
#endif
......
}
初始化DMA,需要DMA通道描述符,BLE协议栈中定义的DMA通道描述符结构:
typedef struct
 {
  uint8 srcAddrH;
  uint8 srcAddrL;
  uint8 dstAddrH;
  uint8 dstAddrL;
  uint8 xferLenV;
  uint8 xferLenL;
  uint8 ctrlA;
  uint8 ctrlB;
} halDMADesc_t;
UART使用DMA方式时,函数HalUARTInitDMA()设置了UART工作方式以及配置了UART使用的DMA通道,默认开启DMA中断。

2、UART初始化
void NPI_InitTransport( npiCBack_t npiCBack )
{
  halUARTCfg_t uartConfig;

  // configure UART
  uartConfig.configured           = TRUE;
  uartConfig.baudRate             = NPI_UART_BR;
  uartConfig.flowControl          = NPI_UART_FC;
  uartConfig.flowControlThreshold = NPI_UART_FC_THRESHOLD;
  uartConfig.rx.maxBufSize        = NPI_UART_RX_BUF_SIZE;
  uartConfig.tx.maxBufSize        = NPI_UART_TX_BUF_SIZE;
  uartConfig.idleTimeout          = NPI_UART_IDLE_TIMEOUT;
  uartConfig.intEnable            = NPI_UART_INT_ENABLE;
  uartConfig.callBackFunc         = (halUARTCBack_t)npiCBack;

  // start UART
  // Note: Assumes no issue opening UART port.
  (void)HalUARTOpen( NPI_UART_PORT, &uartConfig );

  return;
}
uint8 HalUARTOpen(uint8 port, halUARTCfg_t *config)
{
......
#if (HAL_UART_DMA == 1)
  if (port == HAL_UART_PORT_0)  HalUARTOpenDMA(config);
#endif
......
}
在HalUARTOpenDMA(halUARTCfg_t *config)中完成主要的UART初始化,未打开RX中断,貌似初始化代码中也没有开启TX中断,TX中断应该是在写DMA函数中开启的:
static uint16 HalUARTWriteDMA(uint8 *buf, uint16 len)
{
#if HAL_UART_TX_BY_ISR
......
     // Keep re-enabling ISR as it might be keeping up with this loop due to other ints.
    IEN2 |= UTXxIE;
......
  }
#else

三、数据发送与接收
1、数据发送
使用了DMA通道4,单次发送,每次发送一个字节,发送一个字节后触发串口发送完成中断。协议栈默认定义了宏
HAL_UART_TX_BY_ISR,因此在DMA中断中不做任何处理。
2、数据接收
使用了DMA通道3,Repeated word模式,每次一个字,接收完成不触发DMA中断。注意DMA初始化时将rxBuf[]每个字节置为DMA_PAD取反。源地址为U0DBUF+U0BAUD,即每次传送的字包括两个字节,一个字节是接收缓冲U0DBUF,另一个是固定字节波特率,所以说rxBuf[]的高字节是波特率,低字节是接收的有效字节,这样如果高字节与波特率一致则说明是有效字(rxBuf[]全部字节初始化为DMA_PAD^0xff,如果串口没有接收到数据,则高字节是DMA_PAD取反,不相等)。
U0BAUD

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多