TI中文支持网
TI专业的中文技术问题搜集分享网站

cc2540 串口问题

  for (uint16 cnt = 0; cnt < len; cnt++)
  {
    dmaCfg.txBuf[dmaCfg.txTail] = *buf++;
    dmaCfg.txMT = 0;
    if (dmaCfg.txTail >= HAL_UART_DMA_TX_MAX-1)
    {
      dmaCfg.txTail = 0;
    }
    else
    {
      dmaCfg.txTail++;
    }
    // Keep re-enabling ISR as it might be keeping up with this loop due to other ints.
    IEN2 |= UTXxIE;
  }
上面的是在串口写数据的函数中,当执行到 IEN2 |= UTXxIE 时,如果UxDBUF = dmaCfg.txBuf[dmaCfg.txHead++];还没有发送完,中断标记没有置1.是不是数据就丢失了?还是说每次执行到 IEN2 |= UTXxIE 时,UxDBUF 中的数据一定是发送完并把中断标记置1?上面的代码会不会出现数据丢失?
UxDBUF = dmaCfg.txBuf[dmaCfg.txHead++]; 
#if (HAL_UART_DMA == 1)
HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR )
#else
HAL_ISR_FUNCTION( halUart1TxIsr, UTX1_VECTOR )
#endif
{
  HAL_ENTER_ISR();
  if (dmaCfg.txHead == dmaCfg.txTail)
  {
    IEN2 &= ~UTXxIE;
    dmaCfg.txMT = 1;
  }
  else
  {
    UTXxIF = 0;
    UxDBUF = dmaCfg.txBuf[dmaCfg.txHead++];
    if ((HAL_UART_DMA_TX_MAX != 256) && (dmaCfg.txHead >= HAL_UART_DMA_TX_MAX))
    {
      dmaCfg.txHead = 0;
    }
  }
  HAL_EXIT_ISR();
}
求回答。谢谢
Viki Shi:

这段代码,串口是用DMA来控制传输的。代码里怎么没有判断发送完成的标志呀?

一般做传输通讯,都要有传输完成标志的判断。你提到的中断使能标志实在传输完成后重新使能的

Viki Shi:

代码是不是漏了?从给出的来看,个人觉得逻辑不够严谨

sheng xu7:

回复 Viki Shi:

/****************************************************************************** * @fn      HalUARTWriteDMA * * @brief   Write a buffer to the UART, enforcing an all or none policy if the requested length *          exceeds the space available. * * @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 HalUARTWriteDMA(uint8 *buf, uint16 len){#if HAL_UART_TX_BY_ISR  // Enforce all or none.  if (HAL_UART_DMA_TX_AVAIL() < len)  {    count = 0;    return 0;  }  count = len;  for (uint16 cnt = 0; cnt < len; cnt++)  {    dmaCfg.txBuf[dmaCfg.txTail] = *buf++;    dmaCfg.txMT = 0;
    if (dmaCfg.txTail >= HAL_UART_DMA_TX_MAX-1)    {      dmaCfg.txTail = 0;    }    else    {      dmaCfg.txTail++;    }
    // Keep re-enabling ISR as it might be keeping up with this loop due to other ints.    IEN2 |= UTXxIE;  }#else  txIdx_t txIdx;  uint8 txSel;  halIntState_t his;
  HAL_ENTER_CRITICAL_SECTION(his);  txSel = dmaCfg.txSel;  txIdx = dmaCfg.txIdx[txSel];  HAL_EXIT_CRITICAL_SECTION(his);
  // Enforce all or none.  if ((len + txIdx) > HAL_UART_DMA_TX_MAX)  {    return 0;  }
  (void)memcpy(&(dmaCfg.txBuf[txSel][txIdx]), buf, len);
  HAL_ENTER_CRITICAL_SECTION(his);  /* If an ongoing DMA Tx finished while this buffer was being *appended*, then another DMA Tx   * will have already been started on this buffer, but it did not include the bytes just appended.   * Therefore these bytes have to be re-copied to the start of the new working buffer.   */  if (txSel != dmaCfg.txSel)  {    HAL_EXIT_CRITICAL_SECTION(his);    txSel ^= 1;
    (void)memcpy(&(dmaCfg.txBuf[txSel][0]), buf, len);    HAL_ENTER_CRITICAL_SECTION(his);    dmaCfg.txIdx[txSel] = len;  }  else  {    dmaCfg.txIdx[txSel] = txIdx + len;  }
  // If there is no ongoing DMA Tx, then the channel must be armed here.  if (dmaCfg.txIdx[(txSel ^ 1)] == 0)  {    HAL_EXIT_CRITICAL_SECTION(his);    HalUARTArmTxDMA();  }  else  {    dmaCfg.txMT = FALSE;    HAL_EXIT_CRITICAL_SECTION(his);  }#endif
  return len;}
默认使用了HAL_UART_TX_BY_ISR这个宏。这代码是官方的

sheng xu7:

回复 Viki Shi:

static uint16 HalUARTWriteDMA(uint8 *buf, uint16 len){#if HAL_UART_TX_BY_ISR  // Enforce all or none.  if (HAL_UART_DMA_TX_AVAIL() < len)  {    count = 0;    return 0;  }  count = len;  for (uint16 cnt = 0; cnt < len; cnt++)  {    dmaCfg.txBuf[dmaCfg.txTail] = *buf++;    dmaCfg.txMT = 0;
    if (dmaCfg.txTail >= HAL_UART_DMA_TX_MAX-1)    {      dmaCfg.txTail = 0;    }    else    {      dmaCfg.txTail++;    }
    // Keep re-enabling ISR as it might be keeping up with this loop due to other ints.    IEN2 |= UTXxIE;  }#else  txIdx_t txIdx;  uint8 txSel;  halIntState_t his;
  HAL_ENTER_CRITICAL_SECTION(his);  txSel = dmaCfg.txSel;  txIdx = dmaCfg.txIdx[txSel];  HAL_EXIT_CRITICAL_SECTION(his);
  // Enforce all or none.  if ((len + txIdx) > HAL_UART_DMA_TX_MAX)  {    return 0;  }
  (void)memcpy(&(dmaCfg.txBuf[txSel][txIdx]), buf, len);
  HAL_ENTER_CRITICAL_SECTION(his);  /* If an ongoing DMA Tx finished while this buffer was being *appended*, then another DMA Tx   * will have already been started on this buffer, but it did not include the bytes just appended.   * Therefore these bytes have to be re-copied to the start of the new working buffer.   */  if (txSel != dmaCfg.txSel)  {    HAL_EXIT_CRITICAL_SECTION(his);    txSel ^= 1;
    (void)memcpy(&(dmaCfg.txBuf[txSel][0]), buf, len);    HAL_ENTER_CRITICAL_SECTION(his);    dmaCfg.txIdx[txSel] = len;  }  else  {    dmaCfg.txIdx[txSel] = txIdx + len;  }
  // If there is no ongoing DMA Tx, then the channel must be armed here.  if (dmaCfg.txIdx[(txSel ^ 1)] == 0)  {    HAL_EXIT_CRITICAL_SECTION(his);    HalUARTArmTxDMA();  }  else  {    dmaCfg.txMT = FALSE;    HAL_EXIT_CRITICAL_SECTION(his);  }#endif
  return len;}

HAL_UART_TX_BY_ISR 这个宏已经定义,所以没有使用DMA来传输的。

Viki Shi:

回复 sheng xu7:

我看到了,这个用的发送缓存是FIFO形式,每次有给出已知的长度,当tail到达len的长度时,就说明发送完毕。

代码作为样例,肯定可以参考,不过具体应用的时候,我还是建议每次传输增加传输完成的判断

sheng xu7:

回复 Viki Shi:

是不是那段代码会出现丢数据现象?它是不是通过UTXxIF = 1 和 IEN2 |= UTXxIE;来决定 中断服务程序HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR ) 的调用?

#if (HAL_UART_DMA == 1)HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR )#elseHAL_ISR_FUNCTION( halUart1TxIsr, UTX1_VECTOR )#endif{  HAL_ENTER_ISR();
  if (dmaCfg.txHead == dmaCfg.txTail)  {    IEN2 &= ~UTXxIE;    dmaCfg.txMT = 1;  }  else  {    UTXxIF = 0;    UxDBUF = dmaCfg.txBuf[dmaCfg.txHead++];
    if ((HAL_UART_DMA_TX_MAX != 256) && (dmaCfg.txHead >= HAL_UART_DMA_TX_MAX))    {      dmaCfg.txHead = 0;    }  }
  HAL_EXIT_ISR();}#endif

Viki Shi:

回复 sheng xu7:

我觉得有丢失数据的可能。

比如说,上层调用该接口传输时的速率大于DMA的传输速率,就会导致缓存数据被后面传输的数据覆盖,从而引起丢失。

赞(0)
未经允许不得转载:TI中文支持网 » cc2540 串口问题
分享到: 更多 (0)