/****************************************************************************** * @fn HalUARTArmTxDMA * * @brief Arm the Tx DMA channel. * * @param None * * @return None *****************************************************************************/ static void HalUARTArmTxDMA(void) { halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX); HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]); HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]); dmaCfg.txSel ^= 1; dmaCfg.txTrig = 1; HAL_DMA_ARM_CH(HAL_DMA_CH_TX); HalUARTPollTxTrigDMA(); if (DMA_PM) { HAL_UART_DMA_SET_RDY_OUT(); } }
/****************************************************************************** * @fn HalUARTArmTxDMA * * @brief Arm the Tx DMA channel. * * @param None * * @return None *****************************************************************************/ static void HalUARTArmTxDMA(void) { halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX); HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]); HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]); dmaCfg.txSel ^= 1; dmaCfg.txTrig = 1; HAL_DMA_ARM_CH(HAL_DMA_CH_TX); /* Time to arm each DMA channel is 9 cycles as per the user's guide */ asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); HalUARTPollTxTrigDMA(); if (DMA_PM) { HAL_UART_DMA_SET_RDY_OUT(); } }
/****************************************************************************** * @fn HalUART_DMAIsrDMA * * @brief Handle the Tx done DMA ISR. * * @param none * * @return none *****************************************************************************/ void HalUART_DMAIsrDMA(void) { #if !HAL_UART_TX_BY_ISR if (dmaCfg.txIdx[dmaCfg.txSel]) { // If there is more Tx data ready to go, re-arm the DMA immediately on it. HalUARTArmTxDMA(); // Indicate that the Tx buffer just finished is now free (re-arming did a ^= toggle of txSel). dmaCfg.txIdx[dmaCfg.txSel] = 0; } else { dmaCfg.txIdx[(dmaCfg.txSel ^ 1)] = 0; // Indicate that the Tx buffer just finished is now free. // Clear the CSR_TX_BYTE flag & start the txTick to allow the possibility of an immediate // manual trigger from the next Write(), if it occurs more than one character time later. HalUARTPollTxTrigDMA(); } dmaCfg.txMT = TRUE; // Notify CB that at least one Tx buffer is now free to use. #endif }
/****************************************************************************** * @fn HalUARTPollDMA * * @brief Poll a USART module implemented by DMA, including the hybrid solution in which the Rx * is driven by DMA but the Tx is driven by ISR. * * @param none * * @return none *****************************************************************************/ static void HalUARTPollDMA(void) { uint8 evt = 0; uint16 cnt; #if DMA_PM PxIEN &= ~DMA_RDYIn_BIT; // Clear to not race with DMA_RDY_IN ISR. { if (dmaRdyIsr || HAL_UART_DMA_RDY_IN() || HalUARTBusyDMA()) { // Master may have timed-out the SRDY asserted state & may need a new edge. #if HAL_UART_TX_BY_ISR if (!HAL_UART_DMA_RDY_IN() && (dmaCfg.txHead != dmaCfg.txTail)) #else if (!HAL_UART_DMA_RDY_IN() && ((dmaCfg.txIdx[0] != 0) || (dmaCfg.txIdx[1] != 0))) #endif { HAL_UART_DMA_CLR_RDY_OUT(); } dmaRdyIsr = 0; if (dmaRdyDly == 0) { (void)osal_set_event(Hal_TaskID, HAL_PWRMGR_HOLD_EVENT); } if ((dmaRdyDly = ST0) == 0) // Reserve zero to signify that the delay expired. { dmaRdyDly = 0xFF; } HAL_UART_DMA_SET_RDY_OUT(); } else if ((dmaRdyDly != 0) && (!DMA_PM_DLY || ((uint8)(ST0 - dmaRdyDly) > DMA_PM_DLY))) { dmaRdyDly = 0; (void)osal_set_event(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT); } } PxIEN |= DMA_RDYIn_BIT; #endif #if !HAL_UART_TX_BY_ISR HalUARTPollTxTrigDMA(); #endif cnt = HalUARTRxAvailDMA(); // Wait to call until after the above DMA Rx bug work-around. #if HAL_UART_DMA_IDLE if (dmaCfg.rxTick) { // Use the LSB of the sleep timer (ST0 must be read first anyway) to measure the Rx timeout. if ((ST0 - dmaCfg.rxTick) > HAL_UART_DMA_IDLE) { dmaCfg.rxTick = 0; evt = HAL_UART_RX_TIMEOUT; } } else if (cnt != 0) { if ((dmaCfg.rxTick = ST0) == 0) // Zero signifies that the Rx timeout is not running. { dmaCfg.rxTick = 0xFF; } } #else if (cnt != 0) { evt = HAL_UART_RX_TIMEOUT; } #endif if (cnt >= HAL_UART_DMA_FULL) { evt |= HAL_UART_RX_FULL; } else if (cnt >= HAL_UART_DMA_HIGH) { evt |= HAL_UART_RX_ABOUT_FULL; if (!DMA_PM && (UxUCR & UCR_FLOW)) { HAL_UART_DMA_CLR_RDY_OUT(); // Disable Rx flow. } } if (dmaCfg.txMT) { dmaCfg.txMT = FALSE; evt |= HAL_UART_TX_EMPTY; } if ((evt != 0) && (dmaCfg.uartCB != NULL)) { dmaCfg.uartCB(HAL_UART_DMA-1, evt); } if (DMA_PM && (dmaRdyDly == 0) && !HalUARTBusyDMA()) { HAL_UART_DMA_CLR_RDY_OUT(); } }