/*********************************************************************************************** 功能:初始化DMA模块 形参:DMA_InitStruct: 初始化结构 返回:0 详解:0 ************************************************************************************************/ void DMA_Init(DMA_InitTypeDef *DMA_InitStruct) { //参数检查 assert_param(IS_DMA_REQ(DMA_InitStruct->PeripheralDMAReq)); assert_param(IS_DMA_ATTR_SSIZE(DMA_InitStruct->SourceDataSize)); assert_param(IS_DMA_ATTR_DSIZE(DMA_InitStruct->DestDataSize)); assert_param(IS_DMA_CH(DMA_InitStruct->Channelx)); assert_param(IS_DMA_MINOR_LOOP(DMA_InitStruct->MinorLoopLength)); //打开DMA0和DMAMUX时钟源 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK; SIM->SCGC7 |= SIM_SCGC7_DMA_MASK; //配置DMA触发源 DMAMUX->CHCFG[DMA_InitStruct->Channelx] = DMAMUX_CHCFG_SOURCE(DMA_InitStruct->PeripheralDMAReq); //设置源地址信息 DMA0->TCD[DMA_InitStruct->Channelx].SADDR = DMA_InitStruct->SourceBaseAddr; //执行完源地址操作后,是否在源地址基础上累加 DMA0->TCD[DMA_InitStruct->Channelx].SOFF = DMA_SOFF_SOFF(DMA_InitStruct->SourceMinorInc); //设置源地址传输宽度 DMA0->TCD[DMA_InitStruct->Channelx].ATTR = 0; DMA0->TCD[DMA_InitStruct->Channelx].ATTR |= DMA_ATTR_SSIZE(DMA_InitStruct->SourceDataSize); //主循环进行完后 是否更改源地址 DMA0->TCD[DMA_InitStruct->Channelx].SLAST = DMA_InitStruct->SourceMajorInc; //设置目的地址信息 DMA0->TCD[DMA_InitStruct->Channelx].DADDR = DMA_InitStruct->DestBaseAddr; //执行完源地址操作后,是否在源地址基础上累加 DMA0->TCD[DMA_InitStruct->Channelx].DOFF = DMA_DOFF_DOFF(DMA_InitStruct->DestMinorInc); //设置目的地址传输宽度 DMA0->TCD[DMA_InitStruct->Channelx].ATTR |= DMA_ATTR_DSIZE(DMA_InitStruct->DestDataSize); //主循环进行完后 是否更改源地址 DMA0->TCD[DMA_InitStruct->Channelx].DLAST_SGA = DMA_InitStruct->DestMajorInc; //设置计数器长度 循环次数 //设置数据长度 长度每次递减 也被称作当前主循环计数 current major loop count DMA0->TCD[DMA_InitStruct->Channelx].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(DMA_InitStruct->MinorLoopLength ); //起始循环计数器 当主循环计数器为0 时候 将装载起始循环计数器的值 DMA0->TCD[DMA_InitStruct->Channelx].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(DMA_InitStruct->MinorLoopLength); //设置每一次传输字节的个数 个数到达上限时 DMA便将数据存入RAM DMA0->TCD[DMA_InitStruct->Channelx].NBYTES_MLNO = DMA_NBYTES_MLNO_NBYTES(DMA_InitStruct->TransferBytes); //设置DMA TCD控制寄存器 DMA0->TCD[DMA_InitStruct->Channelx].CSR = 0; if(DMA_InitStruct->DMAAutoClose == ENABLE) { DMA0->TCD[DMA_InitStruct->Channelx].CSR |=DMA_CSR_DREQ_MASK; } else { DMA0->TCD[DMA_InitStruct->Channelx].CSR &=(~DMA_CSR_DREQ_MASK); } //使能此寄存器DMA开始工作 DMA_SetEnableReq(DMA_InitStruct->Channelx,DMA_InitStruct->EnableState); //DMA 通道使能 DMAMUX->CHCFG[DMA_InitStruct->Channelx] |= DMAMUX_CHCFG_ENBL_MASK; }
void DmaChannelInit(int channel, void *source_ptr, void *dest_ptr, int size, int source, int source_inc, int dest_inc) { // Configure mux. // Disable channel and clear everything. DMAMUX_CHCFG(channel) = 0x00; // Select source. DMAMUX_CHCFG(channel) |= DMAMUX_CHCFG_SOURCE(source); // Configure channel. // Set up source and dest addresses. DMA_SADDR(channel) = (int)source_ptr; DMA_DADDR(channel) = (int)dest_ptr; // Set soruce and dest address increment. DMA_SOFF(channel) = source_inc; DMA_DOFF(channel) = dest_inc; // Set size of transfer 0x00 = 1 byte. DMA_ATTR(channel) = DMA_ATTR_SSIZE(0) | DMA_ATTR_DSIZE(0); // Set bytes per minor loop. DMA_NBYTES_MLNO(channel) = 0x01; // Set number of minor loops. DMA_CITER_ELINKNO(channel) = DMA_CITER_ELINKNO_CITER(size); DMA_BITER_ELINKNO(channel) = DMA_BITER_ELINKNO_BITER(size); // Adjustment applied after major loop finishes DMA_SLAST(channel) = -(size * source_inc); // Source address adjustment. DMA_DLAST_SGA(channel) = -(size * dest_inc); // Destination address adjustment. // Set to disable on completion. DMA_CSR(0) |= DMA_CSR_DREQ_MASK; // Enable DMA request for channel. DMA_ERQ |= (1 << channel); // Enable mux. DMAMUX_CHCFG(channel) |= DMAMUX_CHCFG_ENBL_MASK; }
void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd) { assert(tcd != NULL); assert(((uint32_t)tcd & 0x1FU) == 0); assert(config != NULL); assert(((uint32_t)nextTcd & 0x1FU) == 0); /* source address */ tcd->SADDR = config->srcAddr; /* destination address */ tcd->DADDR = config->destAddr; /* Source data and destination data transfer size */ tcd->ATTR = DMA_ATTR_SSIZE(config->srcTransferSize) | DMA_ATTR_DSIZE(config->destTransferSize); /* Source address signed offset */ tcd->SOFF = config->srcOffset; /* Destination address signed offset */ tcd->DOFF = config->destOffset; /* Minor byte transfer count */ tcd->NBYTES = config->minorLoopBytes; /* Current major iteration count */ tcd->CITER = config->majorLoopCounts; /* Starting major iteration count */ tcd->BITER = config->majorLoopCounts; /* Enable scatter/gather processing */ if (nextTcd != NULL) { tcd->DLAST_SGA = (uint32_t)nextTcd; /* Before call EDMA_TcdSetTransferConfig or EDMA_SetTransferConfig, user must call EDMA_TcdReset or EDMA_ResetChannel which will set DREQ, so must use "|" or "&" rather than "=". Clear the DREQ bit because scatter gather has been enabled, so the previous transfer is not the last transfer, and channel request should be enabled at the next transfer(the next TCD). */ tcd->CSR = (tcd->CSR | DMA_CSR_ESG_MASK) & ~DMA_CSR_DREQ_MASK; } }
/** * @brief 初始化DMA模块 * @param DMA_InitStruct :DMA初始化配置结构体,详见dma.h * @retval 分配到的DMA 通道 */ uint32_t DMA_Init(DMA_InitTypeDef *DMA_InitStruct) { uint8_t chl; /* enable DMA and DMAMUX clock */ #if defined(DMAMUX0) SIM->SCGC6 |= SIM_SCGC6_DMAMUX0_MASK; #endif #if defined(DMAMUX1) SIM->SCGC6 |= SIM_SCGC6_DMAMUX1_MASK; #endif #if defined(DMAMUX) SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK; #endif SIM->SCGC7 |= SIM_SCGC7_DMA_MASK; chl = DMA_InitStruct->chl; /* disable chl first */ DMA0->ERQ &= ~(1<<(chl)); /* dma chl source config */ DMAMUX_InstanceTable[0]->CHCFG[chl] = DMAMUX_CHCFG_SOURCE(DMA_InitStruct->chlTriggerSource); /* trigger mode */ switch(DMA_InitStruct->triggerSourceMode) { case kDMA_TriggerSource_Normal: DMAMUX_InstanceTable[0]->CHCFG[chl] &= ~DMAMUX_CHCFG_TRIG_MASK; break; case kDMA_TriggerSource_Periodic: DMAMUX_InstanceTable[0]->CHCFG[chl] |= DMAMUX_CHCFG_TRIG_MASK; break; default: break; } /* clear some register */ DMA0->TCD[chl].ATTR = 0; DMA0->TCD[chl].CSR = 0; /* minor loop cnt */ DMA0->TCD[chl].NBYTES_MLNO = DMA_NBYTES_MLNO_NBYTES(DMA_InitStruct->minorLoopByteCnt); /* major loop cnt */ DMA0->TCD[chl].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(DMA_InitStruct->majorLoopCnt); DMA0->TCD[chl].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(DMA_InitStruct->majorLoopCnt); /* source config */ DMA0->TCD[chl].SADDR = DMA_InitStruct->sAddr; DMA0->TCD[chl].SOFF = DMA_InitStruct->sAddrOffset; DMA0->TCD[chl].ATTR |= DMA_ATTR_SSIZE(DMA_InitStruct->sDataWidth); DMA0->TCD[chl].ATTR |= DMA_ATTR_SMOD(DMA_InitStruct->sMod); DMA0->TCD[chl].SLAST = DMA_SLAST_SLAST(DMA_InitStruct->sLastAddrAdj); /* destation config */ DMA0->TCD[chl].DADDR = DMA_InitStruct->dAddr; DMA0->TCD[chl].DOFF = DMA_InitStruct->dAddrOffset; DMA0->TCD[chl].ATTR |= DMA_ATTR_DSIZE(DMA_InitStruct->dDataWidth); DMA0->TCD[chl].ATTR |= DMA_ATTR_DMOD(DMA_InitStruct->dMod); DMA0->TCD[chl].DLAST_SGA = DMA_DLAST_SGA_DLASTSGA(DMA_InitStruct->dLastAddrAdj); /* auto close enable(disable req on major loop complete)*/ DMA0->TCD[chl].CSR |= DMA_CSR_DREQ_MASK; /* enable DMAMUX */ DMAMUX_InstanceTable[0]->CHCFG[chl] |= DMAMUX_CHCFG_ENBL_MASK; return chl; }