【简介】
在之前的帖子中(【S32K3学习整理】DMA 配置使用)使用DMA来接收UART 的数据,我们基于此基础上来理解下DMA 接收数据的代码实现的流程。串口接收使用DMA模式时核心函数为Lpuart_Uart_Ip_StartReceiveDataUsingDma,对应函数的实现如下:
static Lpuart_Uart_Ip_StatusType Lpuart_Uart_Ip_StartReceiveDataUsingDma(const uint8 Instance, uint8 * RxBuff, const uint32 RxSize)
{
Lpuart_Uart_Ip_StateStructureType * UartState;
const Lpuart_Uart_Ip_UserConfigType *UartUserCfg;
LPUART_Type * Base;
Dma_Ip_LogicChannelTransferListType DmaTransferList[LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION];
Dma_Ip_ReturnType DmaReturnStatus;
Base = Lpuart_Uart_Ip_apBases[Instance];
UartState = (Lpuart_Uart_Ip_StateStructureType *)Lpuart_Uart_Ip_apStateStructuresArray[Instance];
UartUserCfg = Lpuart_Uart_Ip_apUserConfig[Instance];
/* Clear all the error flags */
Lpuart_Uart_Ip_ClearErrorFlags(Base);
/* Flush the Rx Buffer */
Lpuart_Uart_Ip_FlushRxBuffer(Base);
/* Set up parameters for Dma_Ip_LogicChannelTransferListType */
DmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS;
DmaTransferList[0].Value = LPUART_UART_IP_LSBW_ADDR(Base->DATA);
DmaTransferList[1].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS;
DmaTransferList[1].Value = (uint32)RxBuff;
DmaTransferList[2].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET;
DmaTransferList[2].Value = 0;
DmaTransferList[3].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET;
DmaTransferList[3].Value = 1;
DmaTransferList[4].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT;
DmaTransferList[4].Value = RxSize;
DmaTransferList[5].Param = DMA_IP_CH_SET_MINORLOOP_SIZE;
DmaTransferList[5].Value = 1;
DmaTransferList[6].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE;
DmaTransferList[6].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
DmaTransferList[7].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE;
DmaTransferList[7].Value = DMA_IP_TRANSFER_SIZE_1_BYTE;
DmaTransferList[8].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT;
DmaTransferList[8].Value = 1;
DmaTransferList[9].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST;
DmaTransferList[9].Value = 1;
/* Update the state structure */
UartState->RxBuff = RxBuff;
UartState->RxSize = 0U;
UartState->IsRxBusy = TRUE;
UartState->ReceiveStatus = LPUART_UART_IP_STATUS_BUSY;
/* Configure the transfer control descriptor for the DMA channel */
DmaReturnStatus = Dma_Ip_SetLogicChannelTransferList(UartUserCfg->RxDMAChannel, DmaTransferList, LPUART_UART_IP_DMA_CONFIG_LIST_DIMENSION);
LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
/* Start the DMA channel */
DmaReturnStatus = Dma_Ip_SetLogicChannelCommand(UartUserCfg->RxDMAChannel, DMA_IP_CH_SET_HARDWARE_REQUEST);
LPUART_UART_IP_DEV_ASSERT(DMA_IP_STATUS_SUCCESS == DmaReturnStatus);
/* Enable the receiver */
Lpuart_Uart_Ip_SetReceiverCmd(Base, TRUE);
/* Enable error interrupts and enable rx DMA requests for the current instance */
Lpuart_Uart_Ip_SetupIntDmaMode(Instance, TRUE);
return LPUART_UART_IP_STATUS_SUCCESS;
}上述函数的核心处理为通过 DmaTransferList 构造DMA传输的TCD 参数配置到DMA中。
/* Set up parameters for Dma_Ip_LogicChannelTransferListType */ DmaTransferList[0].Param = DMA_IP_CH_SET_SOURCE_ADDRESS; DmaTransferList[0].Value = LPUART_UART_IP_LSBW_ADDR(Base->DATA); DmaTransferList[1].Param = DMA_IP_CH_SET_DESTINATION_ADDRESS; DmaTransferList[1].Value = (uint32)RxBuff; DmaTransferList[2].Param = DMA_IP_CH_SET_SOURCE_SIGNED_OFFSET; DmaTransferList[2].Value = 0; DmaTransferList[3].Param = DMA_IP_CH_SET_DESTINATION_SIGNED_OFFSET; DmaTransferList[3].Value = 1; DmaTransferList[4].Param = DMA_IP_CH_SET_MAJORLOOP_COUNT; DmaTransferList[4].Value = RxSize; DmaTransferList[5].Param = DMA_IP_CH_SET_MINORLOOP_SIZE; DmaTransferList[5].Value = 1; DmaTransferList[6].Param = DMA_IP_CH_SET_DESTINATION_TRANSFER_SIZE; DmaTransferList[6].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; DmaTransferList[7].Param = DMA_IP_CH_SET_SOURCE_TRANSFER_SIZE; DmaTransferList[7].Value = DMA_IP_TRANSFER_SIZE_1_BYTE; DmaTransferList[8].Param = DMA_IP_CH_SET_CONTROL_EN_MAJOR_INTERRUPT; DmaTransferList[8].Value = 1; DmaTransferList[9].Param = DMA_IP_CH_SET_CONTROL_DIS_AUTO_REQUEST; DmaTransferList[9].Value = 1;
上述的配置信息会按照配置到DMA 指定channel 的TCD 地址中,完成DMA通道参数的配置。上述的TCD参数被抽象成了Param 和 Value 的结构以下处理将参数数据的内容写入到TCD结构中。

我要赚赏金
