DMA - aman396271/Flagchip_Study GitHub Wiki

概要

DMA(Direct Memory Access) image

单次转换

使用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