/*********************************************************************************************** 功能:设置DMA MINOR LOOP LENGTH 形参:DMAChl: DMA0_CH0 - DMA_CH15 DataNumber: 循环长度 返回:0 详解:0 ************************************************************************************************/ void DMA_SetCurrDataCounter(uint8_t DMAChl,uint16_t DataNumber) { //检测参数 assert_param(IS_DMA_CH(DMAChl)); assert_param(IS_DMA_MINOR_LOOP(DataNumber)); DMA0->TCD[DMAChl].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(DataNumber); }
/*********************************************************************************************** 功能:初始化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; }
/** * @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; }
/** * @brief 设置 DMA MajorLoopCount 计数值 * @param chl: DMA通道号 * @arg HW_DMA_CH0 * @arg HW_DMA_CH1 * @arg HW_DMA_CH2 * @arg HW_DMA_CH3 * @retval None * @note 数值不能超过 DMA_CITER_ELINKNO_CITER_MASK */ void DMA_SetMajorLoopCounter(uint8_t chl, uint32_t val) { DMA0->TCD[chl].CITER_ELINKNO &= ~DMA_CITER_ELINKNO_CITER_MASK; DMA0->TCD[chl].CITER_ELINKNO |= DMA_CITER_ELINKNO_CITER(val); }