/** ***************************************************************************** * @file cmem7_dma.c * * @brief CMEM7 DMA source file * * * @version V1.0 * @date 3. September 2013 * * @note * ***************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT, * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2013 Capital-micro

***************************************************************************** */ #include "cmem7_dma.h" typedef struct { union { uint32_t CTL_LOW; struct { uint32_t INT_EN : 1; uint32_t DST_TR_WIDTH: 3; uint32_t SRC_TR_WIDTH: 3; uint32_t DINC : 2; uint32_t SINC : 2; uint32_t DEST_MSIZE : 3; uint32_t SRC_MSIZE : 3; uint32_t SRC_GATHER_EN: 1; uint32_t DST_SCATTER_EN: 1; uint32_t : 1; uint32_t TT_FC : 3; uint32_t DMS : 2; uint32_t SMS : 2; uint32_t LLP_DST_EN : 1; uint32_t LLP_SRC_EN : 1; } CTL_LOW_b; } INNER; } INNER_CTL_LOW; typedef struct { union { uint32_t CTL_HI; struct { uint32_t BLOCK_TS : 12; uint32_t DONE : 1; } CTL_HI_b; } INNER; } INNER_CTL_HIGH; typedef struct { uint32_t srcAddr; uint32_t dstAddr; uint32_t nextBlock; INNER_CTL_LOW low; INNER_CTL_HIGH high; } INNER_BLOCK_DESC; #define DMA_MAX_CHANNEL_NUM 8 #define DMA_TR_WIDTH_8_BIT 0 #define DMA_TR_WIDTH_16_BIT 1 #define DMA_TR_WIDTH_32_BIT 2 #define DMA_TR_WIDTH_64_BIT 3 #define DMA_TR_WIDTH_128_BIT 4 #define DMA_TR_WIDTH_256_BIT 5 #define DMA_INC_INCREMENT 0 #define DMA_INC_DECREMENT 1 #define DMA_INC_NO_CHANGE 2 #define DMA_LOCK_DMA_TRANSFER 0 #define DMA_LOCK_DMA_BLOCK_TRANSFER 1 #define DMA_LOCK_DMA_BLOCK_TRANSACTION 2 void DMA_Init() { DMA->DMA_EN_b.EN = TRUE; // only open channel 0 DMA->CH_EN = (0xFF << DMA_MAX_CHANNEL_NUM) | 0x0; DMA_ClearInt(DMA_Int_All); DMA_EnableInt(DMA_Int_All, FALSE); DMA->SAR0 = 0x0; DMA->DAR0 = 0x0; DMA->CTL_HI0_b.BLOCK_TS = 0; DMA->CTL_LOW0_b.INT_EN = FALSE; DMA->CTL_LOW0_b.DST_TR_WIDTH = DMA_TR_WIDTH_32_BIT; DMA->CTL_LOW0_b.SRC_TR_WIDTH = DMA_TR_WIDTH_32_BIT; DMA->CTL_LOW0_b.DINC = DMA_INC_INCREMENT; DMA->CTL_LOW0_b.SINC = DMA_INC_INCREMENT; DMA->CTL_LOW0_b.DEST_MSIZE = 0; DMA->CTL_LOW0_b.SRC_MSIZE = 0; DMA->CTL_LOW0_b.SRC_GATHER_EN = FALSE; DMA->CTL_LOW0_b.DST_SCATTER_EN = FALSE; DMA->CTL_LOW0_b.TT_FC = 0; DMA->CTL_LOW0_b.DMS = 0; DMA->CTL_LOW0_b.SMS = 0; DMA->CTL_LOW0_b.LLP_DST_EN = FALSE; DMA->CTL_LOW0_b.LLP_SRC_EN = FALSE; DMA->LLP0_b.LOC = 0; DMA->LLP0_b.LMS = 0; DMA->SGR0_b.SGC = 0x1; DMA->SGR0_b.SGI = 0x0; DMA->DSR0_b.DSC = 0x0; DMA->DSR0_b.DSI = 0x0; DMA->SSTATAR0 = 0x0; DMA->DSTATAR0 = 0x0; DMA->CFG_HI0 = 0x0; DMA->CFG_LOW0_b.CH_PRIOR = 0; DMA->CFG_LOW0_b.CH_SUSP = 0; DMA->CFG_LOW0_b.HS_SEL_DST = 0; DMA->CFG_LOW0_b.LOCK_B_L = 0; DMA->CFG_LOW0_b.HS_SEL_SRC = 0; DMA->CFG_LOW0_b.LOCK_CH_L = DMA_LOCK_DMA_TRANSFER; DMA->CFG_LOW0_b.LOCK_B_L = DMA_LOCK_DMA_TRANSFER; DMA->CFG_LOW0_b.LOCK_CH = TRUE; DMA->CFG_LOW0_b.LOCK_B = TRUE; DMA->CFG_LOW0_b.DST_HS_POL = 0; DMA->CFG_LOW0_b.SRC_HS_POL = 0; DMA->CFG_LOW0_b.RELOAD_SRC = FALSE; DMA->CFG_LOW0_b.RELOAD_DST = FALSE; } void DMA_EnableInt(uint32_t Int, BOOL enable) { assert_param(IS_DMA_INT(Int)); if (enable) { if (Int & DMA_Int_TfrComplete) { DMA->INT_EN_TFR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1; } if (Int & DMA_Int_Err) { DMA->INT_EN_ERR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1; } } else { if (Int & DMA_Int_TfrComplete) { DMA->INT_EN_TFR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x0; } if (Int & DMA_Int_Err) { DMA->INT_EN_ERR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x0; } } } BOOL DMA_GetIntStatus(uint32_t Int) { assert_param(IS_DMA_INT(Int)); if (Int & DMA_Int_TfrComplete) { if (DMA->INT_TFR) { return TRUE; } } if (Int & DMA_Int_Err) { if (DMA->INT_ERR) { return TRUE; } } return FALSE; } void DMA_ClearInt(uint32_t Int) { assert_param(IS_DMA_INT(Int)); if (Int & DMA_Int_TfrComplete) { DMA->INT_CLEAR_TFR = 0x1; } if (Int & DMA_Int_Err) { DMA->INT_CLEAR_ERR = 0x1; } } BOOL DMA_IsBusy() { return (DMA->CH_EN_b.EN) ? TRUE : FALSE; } BOOL DMA_Transfer(BLOCK_DESC *blockList) { BLOCK_DESC *p; if (!blockList) { return FALSE; } if (DMA_IsBusy()) { return FALSE; } p = blockList; while (p) { BOOL llp = FALSE; INNER_BLOCK_DESC *inner = (INNER_BLOCK_DESC *)p; if (p->nextBlock) { llp = TRUE; } inner->high.INNER.CTL_HI = 0; inner->high.INNER.CTL_HI_b.BLOCK_TS = (p->number >> DMA_TR_WIDTH_32_BIT); inner->high.INNER.CTL_HI_b.DONE = 0; inner->nextBlock = p->nextBlock; inner->low.INNER.CTL_LOW = 0; inner->low.INNER.CTL_LOW_b.INT_EN = TRUE; inner->low.INNER.CTL_LOW_b.DST_TR_WIDTH = DMA_TR_WIDTH_32_BIT; inner->low.INNER.CTL_LOW_b.SRC_TR_WIDTH = DMA_TR_WIDTH_32_BIT; inner->low.INNER.CTL_LOW_b.DINC = DMA_INC_INCREMENT; inner->low.INNER.CTL_LOW_b.SINC = DMA_INC_INCREMENT; inner->low.INNER.CTL_LOW_b.DEST_MSIZE = 0; inner->low.INNER.CTL_LOW_b.SRC_MSIZE = 0; inner->low.INNER.CTL_LOW_b.SRC_GATHER_EN = FALSE; inner->low.INNER.CTL_LOW_b.DST_SCATTER_EN = FALSE; inner->low.INNER.CTL_LOW_b.TT_FC = 0; inner->low.INNER.CTL_LOW_b.DMS = 0; inner->low.INNER.CTL_LOW_b.SMS = 0; inner->low.INNER.CTL_LOW_b.LLP_DST_EN = llp; inner->low.INNER.CTL_LOW_b.LLP_SRC_EN = llp; if ((uint32_t)inner == (uint32_t)blockList) { // copy to DMA DMA->SAR0 = llp ? 0x0 : inner->srcAddr ; DMA->DAR0 = llp ? 0x0 : inner->dstAddr ; DMA->CTL_HI0 = llp ? 0x0 : inner->high.INNER.CTL_HI; DMA->CTL_LOW0 = inner->low.INNER.CTL_LOW; DMA->LLP0 = llp ? (uint32_t)inner : 0x0; } p = (BLOCK_DESC *)inner->nextBlock; } // open channel 0 DMA->CH_EN = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1; return TRUE; }