如何解决因CC2530重复触发串口回调函数导致程序卡死的问题
https://blog.youkuaiyun.com/zzz_xxj/article/details/80389531
原因:当使用CC2530的串口时,协议栈会生成一个串口发送事件,在执行该事件的时候也会触发相应的串口回调函数,导致回调函数被重复调用。
解决方法:在_hal_uart_dma.c文件中找到static void HalUARTPollDMA(void)函数,然后找到if (dmaCfg.txMT)语句,将这个判断语句注释掉,即可解决回调函数重复调用问题。
详细代码如下:
-
/******************************************************************************
-
* @fn HalUARTPollDMA
-
*
-
* @brief Poll a USART module implemented by DMA.
-
*
-
* @param none
-
*
-
* @return none
-
*****************************************************************************/
-
static void HalUARTPollDMA(void)
-
{
-
uint16 cnt = 0;
-
uint8 evt = 0;
-
if (HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
-
{
-
uint16 tail = findTail();
-
// If the DMA has transferred in more Rx bytes, reset the Rx idle timer.
-
if (dmaCfg.rxTail != tail)
-
{
-
dmaCfg.rxTail = tail;
-
// Re-sync the shadow on any 1st byte(s) received.
-
if (dmaCfg.rxTick == 0)
-
{
-
dmaCfg.rxShdw = ST0;
-
}
-
dmaCfg.rxTick = HAL_UART_DMA_IDLE;
-
}
-
else if (dmaCfg.rxTick)
-
{
-
// Use the LSB of the sleep timer (ST0 must be read first anyway).
-
uint8 decr = ST0 - dmaCfg.rxShdw;
-
if (dmaCfg.rxTick > decr)
-
{
-
dmaCfg.rxTick -= decr;
-
dmaCfg.rxShdw = ST0;
-
}
-
else
-
{
-
dmaCfg.rxTick = 0;
-
}
-
}
-
cnt = HalUARTRxAvailDMA();
-
}
-
else
-
{
-
dmaCfg.rxTick = 0;
-
}
-
if (cnt >= HAL_UART_DMA_FULL)
-
{
-
evt = HAL_UART_RX_FULL;
-
}
-
else if (cnt >= HAL_UART_DMA_HIGH)
-
{
-
evt = HAL_UART_RX_ABOUT_FULL;
-
PxOUT |= HAL_UART_Px_RTS;
-
}
-
else if (cnt && !dmaCfg.rxTick)
-
{
-
evt = HAL_UART_RX_TIMEOUT;
-
}
-
/****************以下代码会重复触发串口回调函数,所以注释掉*************************/
-
// if (dmaCfg.txMT)
-
// {
-
// dmaCfg.txMT = FALSE;
-
// evt |= HAL_UART_TX_EMPTY;
-
// }
-
/*********************************************************************************/
-
if (dmaCfg.txShdwValid)
-
{
-
uint8 decr = ST0;
-
decr -= dmaCfg.txShdw;
-
if (decr > dmaCfg.txTick)
-
{
-
// No protection for txShdwValid is required
-
// because while the shadow was valid, DMA ISR cannot be triggered
-
// to cause concurrent access to this variable.
-
dmaCfg.txShdwValid = FALSE;
-
}
-
}
-
if (dmaCfg.txDMAPending && !dmaCfg.txShdwValid)
-
{
-
// UART TX DMA is expected to be fired and enough time has lapsed since last DMA ISR
-
// to know that DBUF can be overwritten
-
halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX);
-
halIntState_t intState;
-
// Clear the DMA pending flag
-
dmaCfg.txDMAPending = FALSE;
-
HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]);
-
HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]);
-
dmaCfg.txSel ^= 1;
-
HAL_ENTER_CRITICAL_SECTION(intState);
-
HAL_DMA_ARM_CH(HAL_DMA_CH_TX);
-
do
-
{
-
asm("NOP");
-
} while (!HAL_DMA_CH_ARMED(HAL_DMA_CH_TX));
-
HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX);
-
HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX);
-
HAL_EXIT_CRITICAL_SECTION(intState);
-
}
-
else
-
{
-
halIntState_t his;
-
HAL_ENTER_CRITICAL_SECTION(his);
-
if ((dmaCfg.txIdx[dmaCfg.txSel] != 0) && !HAL_DMA_CH_ARMED(HAL_DMA_CH_TX)
-
&& !HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX))
-
{
-
HAL_EXIT_CRITICAL_SECTION(his);
-
HalUARTIsrDMA();
-
}
-
else
-
{
-
HAL_EXIT_CRITICAL_SECTION(his);
-
}
-
}
-
if (evt && (dmaCfg.uartCB != NULL))
-
{
-
dmaCfg.uartCB(HAL_UART_DMA-1, evt);
-
}
-
}