精读OSAL --中断方式串行通信(_hal_uart_isr.c)

来源:互联网 发布:java 发邮件带附件 编辑:程序博客网 时间:2024/06/10 16:44

当在HAL里读完 _hal_uart_isr.c 就明白了TI的工程师写的发送接收算法.

 

static void HalUARTInitISR(void) 
static void HalUARTOpenISR(halUARTCfg_t *config)


初始化和打开没什么好讲的,读文档就有了.

 

先在这里讲缓冲区算法

             |-------------------|

head-->|-------------------|

             |-------------------|

             |-------------------|

             |-------------------|

    tail-->|-------------------|

             |-------------------|

             |-------------------|

             |-------------------|

             |-------------------|

             |-------------------|

head和tail都是一个方向移动,当移到末位就回到开头位置.这个很重要..

读写函数不是真正的发送接改函数,他们只是负责将数填入上述的缓冲区,

或者从缓冲区中读出.

怎么操作呢? 读写函数只是将数填入或读出缓冲区,然后移动其中一个指针..

那么什么时候结束呢? 就是head==tail..

这里还有,另一个指针是在发送接收中断函数中移动.

这是这种你追我跑的方式发送接收.

 

这里开始读写函数

/***************************************************************************** * @fn      HalUARTReadISR * * @brief   Read a buffer from the UART * * @param   buf  - valid data buffer at least 'len' bytes in size *          len  - max length number of bytes to copy to 'buf' * * @return  length of buffer that was read *****************************************************************************/static uint16 HalUARTReadISR(uint8 *buf, uint16 len){  uint16 cnt = 0;  while ((isrCfg.rxHead != isrCfg.rxTail) && (cnt < len))   //这是读结束条件  {    *buf++ = isrCfg.rxBuf[isrCfg.rxHead++];    if (isrCfg.rxHead >= HAL_UART_ISR_RX_MAX)    {      isrCfg.rxHead = 0;    }    cnt++;  }  return cnt;}/****************************************************************************** * @fn      HalUARTWriteISR * * @brief   Write a buffer to the UART. * * @param   buf - pointer to the buffer that will be written, not freed *          len - length of * * @return  length of the buffer that was sent *****************************************************************************/static uint16 HalUARTWriteISR(uint8 *buf, uint16 len){  uint16 cnt;  // Enforce all or none.  if (HAL_UART_ISR_TX_AVAIL() < len)   //判断长度是否大于当前有效长度  {    return 0;  }  for (cnt = 0; cnt < len; cnt++)  {    isrCfg.txBuf[isrCfg.txTail] = *buf++;    isrCfg.txMT = 0;    if (isrCfg.txTail >= HAL_UART_ISR_TX_MAX-1)  //缓冲区循环    {      isrCfg.txTail = 0;    }    else    {      isrCfg.txTail++;    }    // Keep re-enabling ISR as it might be keeping up with this loop due to other ints.    IEN2 |= UTXxIE;  }  return cnt;}


 

 

这里是中断服务程序:

/*************************************************************************************************** * @fn      halUartRxIsr * * @brief   UART Receive Interrupt * * @param   None * * @return  None ***************************************************************************************************/#if (HAL_UART_ISR == 1)HAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )#elseHAL_ISR_FUNCTION( halUart1RxIsr, URX1_VECTOR )#endif{  HAL_ENTER_ISR();  uint8 tmp = UxDBUF;  isrCfg.rxBuf[isrCfg.rxTail] = tmp;  // Re-sync the shadow on any 1st byte received.  if (isrCfg.rxHead == isrCfg.rxTail)  {    isrCfg.rxShdw = ST0;  }  if (++isrCfg.rxTail >= HAL_UART_ISR_RX_MAX)  {    isrCfg.rxTail = 0;  }  isrCfg.rxTick = HAL_UART_ISR_IDLE;  HAL_EXIT_ISR();}/*************************************************************************************************** * @fn      halUartTxIsr * * @brief   UART Transmit Interrupt * * @param   None * * @return  None ***************************************************************************************************/#if (HAL_UART_ISR == 1)HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR )#elseHAL_ISR_FUNCTION( halUart1TxIsr, UTX1_VECTOR )#endif{  HAL_ENTER_ISR();  if (isrCfg.txHead == isrCfg.txTail)  {    IEN2 &= ~UTXxIE;    isrCfg.txMT = 1;  }  else  {    UTXxIF = 0;    UxDBUF = isrCfg.txBuf[isrCfg.txHead++];    if (isrCfg.txHead >= HAL_UART_ISR_TX_MAX)    {      isrCfg.txHead = 0;    }  }  HAL_EXIT_ISR();}


 都明白了吧?? 还有一个重要的东西:static void HalUARTPollISR(void)

这个函数是在OSAL每次循环中都调出一次,主要是设置事件,调用相应的回调函数.

 

static void HalUARTPollISR(void){  uint16 cnt = HAL_UART_ISR_RX_AVAIL();  uint8 evt = 0;  if (isrCfg.rxTick)  {    // Use the LSB of the sleep timer (ST0 must be read first anyway).    uint8 decr = ST0 - isrCfg.rxShdw;    if (isrCfg.rxTick > decr)    {      isrCfg.rxTick -= decr;    }    else    {      isrCfg.rxTick = 0;    }  }  isrCfg.rxShdw = ST0;  if (cnt >= HAL_UART_ISR_RX_MAX-1)  {    evt = HAL_UART_RX_FULL;  }  else if (cnt >= HAL_UART_ISR_HIGH)  {    evt = HAL_UART_RX_ABOUT_FULL;  }  else if (cnt && !isrCfg.rxTick)  {    evt = HAL_UART_RX_TIMEOUT;  }  if (isrCfg.txMT)  {    isrCfg.txMT = 0;    evt |= HAL_UART_TX_EMPTY;  }  if (evt && (isrCfg.uartCB != NULL))  {    isrCfg.uartCB(HAL_UART_ISR-1, evt);  }}


其它函数就不太重要了.

知道这些就很好理解了.

 

原创粉丝点击