Hi, Daniel,
I have to admit the software architecture is complex.
But I think this is the a clue to understand the code.
#define DEMO_USART Driver_USART0
1)calling DEMO_USART.PowerControl(ARM_POWER_FULL); in main() is the same as calling
DEMO_USART.USART0_NonBlockingPowerControl(ARM_POWER_FULL);
ARM_DRIVER_USART Driver_USART0 = {
USARTx_GetVersion, USARTx_GetCapabilities,
#if RTE_USART0_DMA_EN
USART0_DmaInitialize, USART0_DmaUninitialize, USART0_DmaPowerControl, USART0_DmaSend, USART0_DmaReceive,
USART0_DmaTransfer, USART0_DmaGetTxCount, USART0_DmaGetRxCount, USART0_DmaControl, USART0_DmaGetStatus,
#else
USART0_NonBlockingInitialize,
USART0_NonBlockingUninitialize,
USART0_NonBlockingPowerControl,
USART0_NonBlockingSend,
USART0_NonBlockingReceive,
USART0_NonBlockingTransfer,
USART0_NonBlockingGetTxCount,
USART0_NonBlockingGetRxCount,
USART0_NonBlockingControl,
USART0_NonBlockingGetStatus,
#endif
USARTx_SetModemControl, USARTx_GetModemStatus};
2)In the USART_NonBlockingPowerControl(), the USART_TransferCreateHandle(usart->resource->base, usart->handle, KSDK_USART_NonBlockingCallback,
(void *)usart->cb_event); is called.
static int32_t USART_NonBlockingPowerControl(ARM_POWER_STATE state, cmsis_usart_non_blocking_driver_state_t *usart)
{
usart_config_t config;
switch (state)
{
case ARM_POWER_OFF:
if (usart->flags & USART_FLAG_POWER)
{
USART_Deinit(usart->resource->base);
usart->flags = USART_FLAG_INIT;
}
break;
case ARM_POWER_LOW:
return ARM_DRIVER_ERROR_UNSUPPORTED;
case ARM_POWER_FULL:
/* Must be initialized first. */
if (usart->flags == USART_FLAG_UNINIT)
{
return ARM_DRIVER_ERROR;
}
if (usart->flags & USART_FLAG_POWER)
{
/* Driver already powered */
break;
}
USART_GetDefaultConfig(&config);
config.enableTx = true;
config.enableRx = true;
USART_Init(usart->resource->base, &config, usart->resource->GetFreq());
USART_TransferCreateHandle(usart->resource->base, usart->handle, KSDK_USART_NonBlockingCallback,
(void *)usart->cb_event);
usart->flags |= (USART_FLAG_POWER | USART_FLAG_CONFIGURED);
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}
3)In the USART_TransferCreateHandle(), the FLEXCOMM_SetIRQHandler() is called
status_t USART_TransferCreateHandle(USART_Type *base,
usart_handle_t *handle,
usart_transfer_callback_t callback,
void *userData)
{
/* Check 'base' */
assert(!((NULL == base) || (NULL == handle)));
uint32_t instance = 0;
usart_to_flexcomm_t handler;
handler.usart_master_handler = USART_TransferHandleIRQ;
if ((NULL == base) || (NULL == handle))
{
return kStatus_InvalidArgument;
}
instance = USART_GetInstance(base);
(void)memset(handle, 0, sizeof(*handle));
/* Set the TX/RX state. */
handle->rxState = (uint8_t)kUSART_RxIdle;
handle->txState = (uint8_t)kUSART_TxIdle;
/* Set the callback and user data. */
handle->callback = callback;
handle->userData = userData;
handle->rxWatermark = (uint8_t)USART_FIFOTRIG_RXLVL_GET(base);
handle->txWatermark = (uint8_t)USART_FIFOTRIG_TXLVL_GET(base);
FLEXCOMM_SetIRQHandler(base, handler.flexcomm_handler, handle);
/* Enable interrupt in NVIC. */
(void)EnableIRQ(s_usartIRQ[instance]);
return kStatus_Success;
}
typedef union usart_to_flexcomm
{
flexcomm_usart_irq_handler_t usart_master_handler;
flexcomm_irq_handler_t flexcomm_handler;
} usart_to_flexcomm_t;
4)In the FLEXCOMM_SetIRQHandler(), the s_flexcommIrqHandler[instance] is initialized by handler;, the s_flexcommIrqHandler[instance] is called by USART ISR.
void FLEXCOMM_SetIRQHandler(void *base, flexcomm_irq_handler_t handler, void *handle)
{
uint32_t instance;
/* Look up instance number */
instance = FLEXCOMM_GetInstance(base);
/* Clear handler first to avoid execution of the handler with wrong handle */
s_flexcommIrqHandler[instance] = NULL;
s_flexcommHandle[instance] = handle;
s_flexcommIrqHandler[instance] = handler;
SDK_ISR_EXIT_BARRIER;
}
5) in the end, the USART_TransferHandleIRQ() is called by ISR
void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
{
/* Check arguments */
assert((NULL != base) && (NULL != handle));
bool receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));
bool sendEnabled = (handle->txDataSize != 0U);
uint8_t rxdata;
size_t tmpsize;
/* If RX overrun. */
if ((base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK) != 0U)
{
/* Clear rx error state. */
base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
/* clear rxFIFO */
base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
/* Trigger callback. */
if (handle->callback != NULL)
{
handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
}
}
while ((receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U)) ||
(sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U)))
{
/* Receive data */
if (receiveEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK) != 0U))
{
/* Receive to app bufffer if app buffer is present */
if (handle->rxDataSize != 0U)
{
rxdata = (uint8_t)base->FIFORD;
*handle->rxData = rxdata;
handle->rxDataSize--;
handle->rxData++;
receiveEnabled = ((handle->rxDataSize != 0U) || (handle->rxRingBuffer != NULL));
if (0U == handle->rxDataSize)
{
if (NULL == handle->rxRingBuffer)
{
base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
}
handle->rxState = (uint8_t)kUSART_RxIdle;
if (handle->callback != NULL)
{
handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
}
}
}
/* Otherwise receive to ring buffer if ring buffer is present */
else
{
if (handle->rxRingBuffer != NULL)
{
/* If RX ring buffer is full, trigger callback to notify over run. */
if (USART_TransferIsRxRingBufferFull(handle))
{
if (handle->callback != NULL)
{
handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
}
}
/* If ring buffer is still full after callback function, the oldest data is overridden. */
if (USART_TransferIsRxRingBufferFull(handle))
{
/* Increase handle->rxRingBufferTail to make room for new data. */
if ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
/* Read data. */
rxdata = (uint8_t)base->FIFORD;
handle->rxRingBuffer[handle->rxRingBufferHead] = rxdata;
/* Increase handle->rxRingBufferHead. */
if ((size_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
{
handle->rxRingBufferHead = 0U;
}
else
{
handle->rxRingBufferHead++;
}
}
}
}
/* Send data */
if (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U))
{
base->FIFOWR = *handle->txData;
handle->txDataSize--;
handle->txData++;
sendEnabled = handle->txDataSize != 0U;
if (!sendEnabled)
{
base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
base->INTENSET = USART_INTENSET_TXIDLEEN_MASK;
}
}
}
/* Tx idle and the interrupt is enabled. */
if ((0U != (base->INTENSET & USART_INTENSET_TXIDLEEN_MASK)) && (0U != (base->INTSTAT & USART_INTSTAT_TXIDLE_MASK)))
{
/* Set txState to idle only when all data has been sent out to bus. */
handle->txState = (uint8_t)kUSART_TxIdle;
/* Disable tx idle interrupt */
base->INTENCLR = USART_INTENCLR_TXIDLECLR_MASK;
/* Trigger callback. */
if (handle->callback != NULL)
{
handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
}
}
/* ring buffer is not used */
if (NULL == handle->rxRingBuffer)
{
tmpsize = handle->rxDataSize;
/* restore if rx transfer ends and rxLevel is different from default value */
if ((tmpsize == 0U) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))
{
base->FIFOTRIG =
(base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);
}
/* decrease level if rx transfer is bellow */
if ((tmpsize != 0U) && (tmpsize < (USART_FIFOTRIG_RXLVL_GET(base) + 1U)))
{
base->FIFOTRIG = (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(tmpsize - 1U));
}
}
}
Hope it can help you
BR
XiangJun Rong