这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 行业应用 » 汽车电子 » 【S32K3学习整理】S32K3 UART DMA 数据搬运代码解析

共1条 1/1 1 跳转至页

【S32K3学习整理】S32K3 UART DMA 数据搬运代码解析

高工
2026-10-07 09:57:54   被打赏 41 分(兑奖)     打赏

【简介】

在之前的帖子中(【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结构中。

image.png

/*==================================================================================================
 * DMA CHANNEL SET TRANSFER PARAMETER - FUNCTION POINTER
==================================================================================================*/
void HwAccDmaCh_SetTransferParam(const uint32 Parameter, const uint32 LocHwVers, Dma_Ip_TcdRegType * pxLocTcd, const uint32 LocValue)
{
static void (* const fpHwAcc_DmaCh_SetTransferParam[])(const uint32 LocHwVers, Dma_Ip_TcdRegType * pxLocTcd, const uint32 LocValue) =
{
&HwAccDmaCh_SetSource_Address,
&HwAccDmaCh_SetSource_SignedOffset,
&HwAccDmaCh_SetSource_LastAddrAdj,
&HwAccDmaCh_SetSource_TransferSize,
&HwAccDmaCh_SetSource_Modulo,
&HwAccDmaCh_SetDestination_Address,
&HwAccDmaCh_SetDestination_SignedOffset,
&HwAccDmaCh_SetDestination_LastAddrAdj,
&HwAccDmaCh_SetDestination_TransferSize,
&HwAccDmaCh_SetDestination_Modulo,
&HwAccDmaCh_SetMinorLoop_enSrcOffset,
&HwAccDmaCh_SetMinorLoop_enDstOffset,
&HwAccDmaCh_SetMinorLoop_Offset,
&HwAccDmaCh_SetMinorLoop_EnLink,
&HwAccDmaCh_SetMinorLoop_LogicLinkCh,
&HwAccDmaCh_SetMinorLoop_Size,
&HwAccDmaCh_SetMajorLoop_EnLink,
&HwAccDmaCh_SetMajorLoop_LogicLinkCh,
&HwAccDmaCh_SetMajorLoop_Count,
#if (STD_ON == DMA_IP_STORE_DST_ADDR_IS_AVAILABLE)
&HwAccDmaCh_SetControl_StoreDestinationAddress,
#else
&HwAccDmaCh_SetTransferDummyFunction,
#endif
&HwAccDmaCh_SetControl_EnStart,
&HwAccDmaCh_SetControl_EnMajor,
&HwAccDmaCh_SetControl_EnHalfMajor,
&HwAccDmaCh_SetControl_DisAutoHwRequest,
#if (STD_ON == DMA_IP_END_OF_PACKET_SIGNAL_IS_AVAILABLE)
&HwAccDmaCh_SetControl_EnEndOfPacketSignal,
#else
&HwAccDmaCh_SetTransferDummyFunction,
#endif
#if (STD_ON == DMA_IP_BANDWIDTH_CONTROL_IS_AVAILABLE)
&HwAccDmaCh_SetControl_BandwidthControl,
#else
&HwAccDmaCh_BandwithControlrDummyFunction,
#endif
#if (STD_ON == DMA_IP_TRANSFER_MODE_CONTROL_IS_AVAILABLE)
&HwAccDmaCh_SetControl_TransferModeControl,
#else
&HwAccDmaCh_SetTransferDummyFunction,
#endif
};
fpHwAcc_DmaCh_SetTransferParam[Parameter](LocHwVers, pxLocTcd, LocValue);
}

该函数根据配置的param 来调用对应的设置的函数指针完成DMA的参数配置。初始化配置好DMA参数配置后,在串口的接收完成的DMA中断中,如果重新更新了接收buffer,在中断完成函数中会重新配置DMA 参数重新开始下一次传输。

image.png


   


           


共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]