1 /** 2 ***************************************************************************** 3 * @file cmem7_dma.c 4 * 5 * @brief CMEM7 DMA source file 6 * 7 * 8 * @version V1.0 9 * @date 3. September 2013 10 * 11 * @note 12 * 13 ***************************************************************************** 14 * @attention 15 * 16 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 17 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 18 * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT, 19 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 20 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 21 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 22 * 23 * <h2><center>© COPYRIGHT 2013 Capital-micro </center></h2> 24 ***************************************************************************** 25 */ 26 27 #include "cmem7_dma.h" 28 29 typedef struct { 30 union { 31 uint32_t CTL_LOW; 32 33 struct { 34 uint32_t INT_EN : 1; 35 uint32_t DST_TR_WIDTH: 3; 36 uint32_t SRC_TR_WIDTH: 3; 37 uint32_t DINC : 2; 38 uint32_t SINC : 2; 39 uint32_t DEST_MSIZE : 3; 40 uint32_t SRC_MSIZE : 3; 41 uint32_t SRC_GATHER_EN: 1; 42 uint32_t DST_SCATTER_EN: 1; 43 uint32_t : 1; 44 uint32_t TT_FC : 3; 45 uint32_t DMS : 2; 46 uint32_t SMS : 2; 47 uint32_t LLP_DST_EN : 1; 48 uint32_t LLP_SRC_EN : 1; 49 } CTL_LOW_b; 50 } INNER; 51 } INNER_CTL_LOW; 52 53 typedef struct { 54 union { 55 uint32_t CTL_HI; 56 57 struct { 58 uint32_t BLOCK_TS : 12; 59 uint32_t DONE : 1; 60 } CTL_HI_b; 61 } INNER; 62 } INNER_CTL_HIGH; 63 64 typedef struct { 65 uint32_t srcAddr; 66 uint32_t dstAddr; 67 uint32_t nextBlock; 68 INNER_CTL_LOW low; 69 INNER_CTL_HIGH high; 70 } INNER_BLOCK_DESC; 71 72 73 #define DMA_MAX_CHANNEL_NUM 8 74 75 #define DMA_TR_WIDTH_8_BIT 0 76 #define DMA_TR_WIDTH_16_BIT 1 77 #define DMA_TR_WIDTH_32_BIT 2 78 #define DMA_TR_WIDTH_64_BIT 3 79 #define DMA_TR_WIDTH_128_BIT 4 80 #define DMA_TR_WIDTH_256_BIT 5 81 82 #define DMA_INC_INCREMENT 0 83 #define DMA_INC_DECREMENT 1 84 #define DMA_INC_NO_CHANGE 2 85 86 #define DMA_LOCK_DMA_TRANSFER 0 87 #define DMA_LOCK_DMA_BLOCK_TRANSFER 1 88 #define DMA_LOCK_DMA_BLOCK_TRANSACTION 2 89 90 DMA_Init()91void DMA_Init() { 92 DMA->DMA_EN_b.EN = TRUE; 93 94 // only open channel 0 95 DMA->CH_EN = (0xFF << DMA_MAX_CHANNEL_NUM) | 0x0; 96 97 DMA_ClearInt(DMA_Int_All); 98 DMA_EnableInt(DMA_Int_All, FALSE); 99 100 DMA->SAR0 = 0x0; 101 DMA->DAR0 = 0x0; 102 103 DMA->CTL_HI0_b.BLOCK_TS = 0; 104 DMA->CTL_LOW0_b.INT_EN = FALSE; 105 DMA->CTL_LOW0_b.DST_TR_WIDTH = DMA_TR_WIDTH_32_BIT; 106 DMA->CTL_LOW0_b.SRC_TR_WIDTH = DMA_TR_WIDTH_32_BIT; 107 DMA->CTL_LOW0_b.DINC = DMA_INC_INCREMENT; 108 DMA->CTL_LOW0_b.SINC = DMA_INC_INCREMENT; 109 DMA->CTL_LOW0_b.DEST_MSIZE = 0; 110 DMA->CTL_LOW0_b.SRC_MSIZE = 0; 111 DMA->CTL_LOW0_b.SRC_GATHER_EN = FALSE; 112 DMA->CTL_LOW0_b.DST_SCATTER_EN = FALSE; 113 DMA->CTL_LOW0_b.TT_FC = 0; 114 DMA->CTL_LOW0_b.DMS = 0; 115 DMA->CTL_LOW0_b.SMS = 0; 116 DMA->CTL_LOW0_b.LLP_DST_EN = FALSE; 117 DMA->CTL_LOW0_b.LLP_SRC_EN = FALSE; 118 119 DMA->LLP0_b.LOC = 0; 120 DMA->LLP0_b.LMS = 0; 121 122 DMA->SGR0_b.SGC = 0x1; 123 DMA->SGR0_b.SGI = 0x0; 124 125 DMA->DSR0_b.DSC = 0x0; 126 DMA->DSR0_b.DSI = 0x0; 127 128 DMA->SSTATAR0 = 0x0; 129 DMA->DSTATAR0 = 0x0; 130 131 DMA->CFG_HI0 = 0x0; 132 DMA->CFG_LOW0_b.CH_PRIOR = 0; 133 DMA->CFG_LOW0_b.CH_SUSP = 0; 134 DMA->CFG_LOW0_b.HS_SEL_DST = 0; 135 DMA->CFG_LOW0_b.LOCK_B_L = 0; 136 DMA->CFG_LOW0_b.HS_SEL_SRC = 0; 137 DMA->CFG_LOW0_b.LOCK_CH_L = DMA_LOCK_DMA_TRANSFER; 138 DMA->CFG_LOW0_b.LOCK_B_L = DMA_LOCK_DMA_TRANSFER; 139 DMA->CFG_LOW0_b.LOCK_CH = TRUE; 140 DMA->CFG_LOW0_b.LOCK_B = TRUE; 141 DMA->CFG_LOW0_b.DST_HS_POL = 0; 142 DMA->CFG_LOW0_b.SRC_HS_POL = 0; 143 DMA->CFG_LOW0_b.RELOAD_SRC = FALSE; 144 DMA->CFG_LOW0_b.RELOAD_DST = FALSE; 145 } 146 DMA_EnableInt(uint32_t Int,BOOL enable)147void DMA_EnableInt(uint32_t Int, BOOL enable) { 148 assert_param(IS_DMA_INT(Int)); 149 150 if (enable) { 151 if (Int & DMA_Int_TfrComplete) { 152 DMA->INT_EN_TFR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1; 153 } 154 155 if (Int & DMA_Int_Err) { 156 DMA->INT_EN_ERR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1; 157 } 158 } else { 159 if (Int & DMA_Int_TfrComplete) { 160 DMA->INT_EN_TFR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x0; 161 } 162 163 if (Int & DMA_Int_Err) { 164 DMA->INT_EN_ERR = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x0; 165 } 166 } 167 } 168 DMA_GetIntStatus(uint32_t Int)169BOOL DMA_GetIntStatus(uint32_t Int) { 170 assert_param(IS_DMA_INT(Int)); 171 172 if (Int & DMA_Int_TfrComplete) { 173 if (DMA->INT_TFR) { 174 return TRUE; 175 } 176 } 177 178 if (Int & DMA_Int_Err) { 179 if (DMA->INT_ERR) { 180 return TRUE; 181 } 182 } 183 184 return FALSE; 185 } 186 DMA_ClearInt(uint32_t Int)187void DMA_ClearInt(uint32_t Int) { 188 assert_param(IS_DMA_INT(Int)); 189 190 if (Int & DMA_Int_TfrComplete) { 191 DMA->INT_CLEAR_TFR = 0x1; 192 } 193 194 if (Int & DMA_Int_Err) { 195 DMA->INT_CLEAR_ERR = 0x1; 196 } 197 } 198 DMA_IsBusy()199BOOL DMA_IsBusy() { 200 return (DMA->CH_EN_b.EN) ? TRUE : FALSE; 201 } 202 DMA_Transfer(BLOCK_DESC * blockList)203BOOL DMA_Transfer(BLOCK_DESC *blockList) { 204 BLOCK_DESC *p; 205 if (!blockList) { 206 return FALSE; 207 } 208 209 if (DMA_IsBusy()) { 210 return FALSE; 211 } 212 213 p = blockList; 214 while (p) { 215 BOOL llp = FALSE; 216 INNER_BLOCK_DESC *inner = (INNER_BLOCK_DESC *)p; 217 if (p->nextBlock) { 218 llp = TRUE; 219 } 220 221 inner->high.INNER.CTL_HI = 0; 222 inner->high.INNER.CTL_HI_b.BLOCK_TS = (p->number >> DMA_TR_WIDTH_32_BIT); 223 inner->high.INNER.CTL_HI_b.DONE = 0; 224 225 inner->nextBlock = p->nextBlock; 226 227 inner->low.INNER.CTL_LOW = 0; 228 inner->low.INNER.CTL_LOW_b.INT_EN = TRUE; 229 inner->low.INNER.CTL_LOW_b.DST_TR_WIDTH = DMA_TR_WIDTH_32_BIT; 230 inner->low.INNER.CTL_LOW_b.SRC_TR_WIDTH = DMA_TR_WIDTH_32_BIT; 231 inner->low.INNER.CTL_LOW_b.DINC = DMA_INC_INCREMENT; 232 inner->low.INNER.CTL_LOW_b.SINC = DMA_INC_INCREMENT; 233 inner->low.INNER.CTL_LOW_b.DEST_MSIZE = 0; 234 inner->low.INNER.CTL_LOW_b.SRC_MSIZE = 0; 235 inner->low.INNER.CTL_LOW_b.SRC_GATHER_EN = FALSE; 236 inner->low.INNER.CTL_LOW_b.DST_SCATTER_EN = FALSE; 237 inner->low.INNER.CTL_LOW_b.TT_FC = 0; 238 inner->low.INNER.CTL_LOW_b.DMS = 0; 239 inner->low.INNER.CTL_LOW_b.SMS = 0; 240 inner->low.INNER.CTL_LOW_b.LLP_DST_EN = llp; 241 inner->low.INNER.CTL_LOW_b.LLP_SRC_EN = llp; 242 243 if ((uint32_t)inner == (uint32_t)blockList) { 244 // copy to DMA 245 DMA->SAR0 = llp ? 0x0 : inner->srcAddr ; 246 DMA->DAR0 = llp ? 0x0 : inner->dstAddr ; 247 248 DMA->CTL_HI0 = llp ? 0x0 : inner->high.INNER.CTL_HI; 249 DMA->CTL_LOW0 = inner->low.INNER.CTL_LOW; 250 251 DMA->LLP0 = llp ? (uint32_t)inner : 0x0; 252 } 253 254 p = (BLOCK_DESC *)inner->nextBlock; 255 } 256 257 // open channel 0 258 DMA->CH_EN = (0x1 << DMA_MAX_CHANNEL_NUM) | 0x1; 259 260 return TRUE; 261 } 262 263