DMA - aman396271/Flagchip_Study GitHub Wiki
概要
DMA(Direct Memory Access)
单次转换
使用DMA接收WSS数据
WSS(Wheel Speed Sensor,轮速传感器)
SDK版
单次转换
s_tDmaChannel0Cfg.pSrcBuffer = &FTU4->CONTROLS[1].CSCn;
s_tDmaChannel0Cfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B;
s_tDmaChannel0Cfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE;
s_tDmaChannel0Cfg.bSrcBlockOffsetEn = 0U;
s_tDmaChannel0Cfg.bSrcAddrLoopbackEn= 1U;
s_tDmaChannel0Cfg.pDestBuffer = &sWSS.ChannelReg[0];
s_tDmaChannel0Cfg.eDestDataSize = DMA_TRANSFER_SIZE_4B;
s_tDmaChannel0Cfg.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
s_tDmaChannel0Cfg.bDestAddrLoopbackEn = 0U;
s_tDmaChannel0Cfg.bDestAddrLoopbackEn = 1U;
s_tDmaChannel0Cfg.u32BlockSize = 8U;
s_tDmaChannel0Cfg.u16BlockCount = 1U;
s_tDmaChannel0Cfg.s32BlockOffset = 0U;
s_tDmaChannel0Cfg.bAutoStop = 0U;
s_tDmaChannel0Cfg.bSrcCircularBufferEn = 0U;
s_tDmaChannel0Cfg.u32SrcCircBufferSize = 0U;
s_tDmaChannel0Cfg.bDestCircularBufferEn = 0U;
s_tDmaChannel0Cfg.u32DestCircBufferSize = 0U;
s_tDmaChannel0Cfg.bInnerChannelChain = 0U;
s_tDmaChannel0Cfg.eTriggerSrc = DMA_REQ_FTU4_OR_CH0_CH7;
s_tDmaChannel0Cfg.bTransferCompleteIntEn = 1U;
s_tDmaChannel0Cfg.pTransferCompleteNotify = DMA_TransferCompleteCallback;
s_tDmaChannel0Cfg.bTransferErrorIntEn = 1U;
s_tDmaChannel0Cfg.pTransferErrorNotify = DMA_ErrorCallback;
DMA_InitChannel(&g_ch0tDmaHandle, &s_tDmaChannel0Cfg);
DMA->CFG[0].NBYTES.ILOFFYES = (1<<31) | (1<<30) | 4; s_tDmaChannel0Cfg.pSrcBuffer = &FTU4->CONTROLS[1].CSCn;
s_tDmaChannel0Cfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B;
s_tDmaChannel0Cfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE;
s_tDmaChannel0Cfg.bSrcBlockOffsetEn = 0U;
s_tDmaChannel0Cfg.bSrcAddrLoopbackEn= 1U;
s_tDmaChannel0Cfg.pDestBuffer = &sWSS.ChannelReg[0];
s_tDmaChannel0Cfg.eDestDataSize = DMA_TRANSFER_SIZE_4B;
s_tDmaChannel0Cfg.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
s_tDmaChannel0Cfg.bDestAddrLoopbackEn = 0U;
s_tDmaChannel0Cfg.bDestAddrLoopbackEn = 1U;
s_tDmaChannel0Cfg.u32BlockSize = 8U;
s_tDmaChannel0Cfg.u16BlockCount = 1U;
s_tDmaChannel0Cfg.s32BlockOffset = 0U;
s_tDmaChannel0Cfg.bAutoStop = 0U;
s_tDmaChannel0Cfg.bSrcCircularBufferEn = 0U;
s_tDmaChannel0Cfg.u32SrcCircBufferSize = 0U;
s_tDmaChannel0Cfg.bDestCircularBufferEn = 0U;
s_tDmaChannel0Cfg.u32DestCircBufferSize = 0U;
s_tDmaChannel0Cfg.bInnerChannelChain = 0U;
s_tDmaChannel0Cfg.eTriggerSrc = DMA_REQ_FTU4_OR_CH0_CH7;
s_tDmaChannel0Cfg.bTransferCompleteIntEn = 1U;
s_tDmaChannel0Cfg.pTransferCompleteNotify = DMA_TransferCompleteCallback;
s_tDmaChannel0Cfg.bTransferErrorIntEn = 1U;
s_tDmaChannel0Cfg.pTransferErrorNotify = DMA_ErrorCallback;
DMA_InitChannel(&g_ch0tDmaHandle, &s_tDmaChannel0Cfg);
DMA->CFG[0].NBYTES.ILOFFYES = (1<<31) | (1<<30) | 4;
关于单次传输
使用FTU的Reload/Match触发DMA
使用FTU来触发DMA有两种实现方式,一者是使用reload点,结合TRGSEL设置对应FTU的reload和DMA Channel,并在DMAMUX中使能通道,从而触发DMA 两者在FTU设置上的区别主要是MSB/MSA/ELSB/ELSA的设置,设置不同,则工作模式不同,reload是0000,compare是1011(match使用compare模式)
Reload FTU Code
void Bsp_Ftu3_Init(void)
{
FTU_Type* FTU = FTU3;
FTU->SC = FTU_SC_FLTPS(0)
| FTU_SC_CHNOUTEN(1<<0)
| FTU_SC_TOIE(0)
| FTU_SC_RIE(0)
| FTU_SC_CPWMS(0);
FTU->MOD = FTU_MOD_MOD(5000);
FTU->CNTIN = 0;
FTU->CONTROLS[0].CSCn = FTU_CSC_TRIGMODE(1)
| FTU_CSC_CHIE(1)
| FTU_CSC_MSB(1)
| FTU_CSC_MSA(0)
| FTU_CSC_ELSB(0)
| FTU_CSC_ELSA(0)
| FTU_CSC_ICRST(0) // Used only in IC Mode
| FTU_CSC_DMA(1);
FTU->CONTROLS[0].CVn = FTU_CV_VAL(5000);
FTU->TRIGCONF = FTU_TRIGCONF_RELOADTRIGEN(1)
| FTU_TRIGCONF_CH0TRIG(1);
FTU->POL = FTU_POL_POLN(0<<0);
FTU->CONF = FTU_CONF_RTRIGR(0)
| FTU_CONF_GTBEEN(0)
| FTU_CONF_DBG(0b11)
| FTU_CONF_LDFQ(0);
// Start FTU
FTU->SC |= FTU_SC_CLKS(3)
| FTU_SC_PS(FTU_DIV_8);
}
DMA配置,有几点需要注意: 1、u32BlockSize必须大于等于eSrcDataSize 2、eTriggerSrc的选择不同 Reload下的DMA配置
DMA_InitType s_tDmaInitCfg = {0};
DMA_ChannelCfgType s_tDmaCh0Cfg = {0};
DMA_ChannelCfgType s_tDmaCh1Cfg = {0};
DMA_ChannelCfgType s_tDmaCh2Cfg = {0};
s_tDmaInitCfg.eArbitrationAlgorithm = DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY;
s_tDmaInitCfg.bHaltOnError = false;
DMA_Init(&g_tDma0InstanceHandle, &s_tDmaInitCfg);
DMA->CR |= 1<<0; //Debug Mode
/* MUX0_Table[i] -> GPIOA->PCOR */
s_tDmaCh0Cfg.pSrcBuffer = MUX0_Table;
s_tDmaCh0Cfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B;
s_tDmaCh0Cfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE;
s_tDmaCh0Cfg.bSrcBlockOffsetEn = 0U;
s_tDmaCh0Cfg.bSrcAddrLoopbackEn = 1U;
s_tDmaCh0Cfg.pDestBuffer = &GPIOA->PTOR;
s_tDmaCh0Cfg.eDestDataSize = DMA_TRANSFER_SIZE_4B;
s_tDmaCh0Cfg.eDestIncMode = DMA_INCREMENT_DISABLE;
s_tDmaCh0Cfg.bDestBlockOffsetEn = 0U;
s_tDmaCh0Cfg.bDestAddrLoopbackEn= 0U;
s_tDmaCh0Cfg.u32BlockSize = 4U;
s_tDmaCh0Cfg.u16BlockCount = 16U;
s_tDmaCh0Cfg.s32BlockOffset = 0U;
s_tDmaCh0Cfg.bAutoStop = 0U;
s_tDmaCh0Cfg.bSrcCircularBufferEn = 0U;
s_tDmaCh0Cfg.u32SrcCircBufferSize = 0U;
s_tDmaCh0Cfg.bDestCircularBufferEn = 0U;
s_tDmaCh0Cfg.u32DestCircBufferSize = 0U;
s_tDmaCh0Cfg.bInnerChannelChain = 0U;
s_tDmaCh0Cfg.u8ChannelPriority = 0U;
s_tDmaCh0Cfg.eTriggerSrc = DMA_REQ_FTU3_OR_CH0_CH7;
s_tDmaCh0Cfg.bTransferCompleteIntEn = 1U;
s_tDmaCh0Cfg.pTransferCompleteNotify = DMA_Mux_GPIOSwitch_Callback;
s_tDmaCh0Cfg.bTransferErrorIntEn = 1U;
s_tDmaCh0Cfg.pTransferErrorNotify = DMA_ErrorCallback;
DMA_InitChannel(&g_ch0tDmaHandle, &s_tDmaCh0Cfg);
DMAMUX->CHCFG[0] |= 1<<6;
Match下s_tDmaCh0Cfg.eTriggerSrc = DMA_REQ_DMAMUX_ALWAYS_ENABLED0;,且DMAMUX->CHCFG[n] |= 1<<6;打开对应DMAMUX通道n
#End