The wait in mci_WaitForEvent will delay all card transactions.
Fork of EALib by
gpdma.cpp
00001 00002 /****************************************************************************** 00003 * Includes 00004 *****************************************************************************/ 00005 00006 #include "gpdma.h" 00007 00008 /****************************************************************************** 00009 * Defines and typedefs 00010 *****************************************************************************/ 00011 00012 #define NUM_GPDMA_CHANNELS 8 00013 00014 #define GPDMACH(__x) ((LPC_GPDMACH_TypeDef*)(LPC_GPDMACH0_BASE + (0x20 * (__x)))) 00015 00016 #define CH_MASK(__ch) (((1UL << (__ch)) & 0xFF)) 00017 00018 /** 00019 * @brief GPDMA request connections 00020 */ 00021 #define GPDMA_CONN_MEMORY ((0UL)) 00022 #define GPDMA_CONN_SDC ((1UL)) /*!< SD card */ 00023 00024 /** 00025 * @brief Macro defines for DMA channel control registers 00026 */ 00027 #define GPDMA_DMACCxControl_TransferSize(n) (((n & 0xFFF) << 0)) /*!< Transfer size*/ 00028 #define GPDMA_DMACCxControl_SBSize(n) (((n & 0x07) << 12)) /*!< Source burst size*/ 00029 #define GPDMA_DMACCxControl_DBSize(n) (((n & 0x07) << 15)) /*!< Destination burst size*/ 00030 #define GPDMA_DMACCxControl_SWidth(n) (((n & 0x07) << 18)) /*!< Source transfer width*/ 00031 #define GPDMA_DMACCxControl_DWidth(n) (((n & 0x07) << 21)) /*!< Destination transfer width*/ 00032 #define GPDMA_DMACCxControl_SI ((1UL << 26)) /*!< Source increment*/ 00033 #define GPDMA_DMACCxControl_DI ((1UL << 27)) /*!< Destination increment*/ 00034 #define GPDMA_DMACCxControl_SrcTransUseAHBMaster1 0 00035 #define GPDMA_DMACCxControl_DestTransUseAHBMaster1 0 00036 #define GPDMA_DMACCxControl_Prot1 ((1UL << 28)) /*!< Indicates that the access is in user mode or privileged mode*/ 00037 #define GPDMA_DMACCxControl_Prot2 ((1UL << 29)) /*!< Indicates that the access is bufferable or not bufferable*/ 00038 #define GPDMA_DMACCxControl_Prot3 ((1UL << 30)) /*!< Indicates that the access is cacheable or not cacheable*/ 00039 #define GPDMA_DMACCxControl_I ((1UL << 31)) /*!< Terminal count interrupt enable bit */ 00040 00041 /** 00042 * @brief GPDMA Burst size in Source and Destination definitions 00043 */ 00044 #define GPDMA_BSIZE_1 ((0UL)) /*!< Burst size = 1 */ 00045 #define GPDMA_BSIZE_4 ((1UL)) /*!< Burst size = 4 */ 00046 #define GPDMA_BSIZE_8 ((2UL)) /*!< Burst size = 8 */ 00047 #define GPDMA_BSIZE_16 ((3UL)) /*!< Burst size = 16 */ 00048 #define GPDMA_BSIZE_32 ((4UL)) /*!< Burst size = 32 */ 00049 #define GPDMA_BSIZE_64 ((5UL)) /*!< Burst size = 64 */ 00050 #define GPDMA_BSIZE_128 ((6UL)) /*!< Burst size = 128 */ 00051 #define GPDMA_BSIZE_256 ((7UL)) /*!< Burst size = 256 */ 00052 00053 /** 00054 * @brief Width in Source transfer width and Destination transfer width definitions 00055 */ 00056 #define GPDMA_WIDTH_BYTE ((0UL)) /*!< Width = 1 byte */ 00057 #define GPDMA_WIDTH_HALFWORD ((1UL)) /*!< Width = 2 bytes */ 00058 #define GPDMA_WIDTH_WORD ((2UL)) /*!< Width = 4 bytes */ 00059 00060 /** 00061 * @brief Macro defines for DMA Configuration register 00062 */ 00063 #define GPDMA_DMACConfig_E ((0x01)) /*!< DMA Controller enable*/ 00064 #define GPDMA_DMACConfig_M ((0x02)) /*!< AHB Master endianness configuration*/ 00065 #define GPDMA_DMACConfig_BITMASK ((0x03)) 00066 00067 /** 00068 * @brief Macro defines for DMA Channel Configuration registers 00069 */ 00070 #define GPDMA_DMACCxConfig_E ((1UL << 0)) /*!< DMA control enable*/ 00071 #define GPDMA_DMACCxConfig_SrcPeripheral(n) (((n & 0x1F) << 1)) /*!< Source peripheral*/ 00072 #define GPDMA_DMACCxConfig_DestPeripheral(n) (((n & 0x1F) << 6)) /*!< Destination peripheral*/ 00073 #define GPDMA_DMACCxConfig_TransferType(n) (((n & 0x7) << 11)) /*!< This value indicates the type of transfer*/ 00074 #define GPDMA_DMACCxConfig_IE ((1UL << 14)) /*!< Interrupt error mask*/ 00075 #define GPDMA_DMACCxConfig_ITC ((1UL << 15)) /*!< Terminal count interrupt mask*/ 00076 #define GPDMA_DMACCxConfig_L ((1UL << 16)) /*!< Lock*/ 00077 #define GPDMA_DMACCxConfig_A ((1UL << 17)) /*!< Active*/ 00078 #define GPDMA_DMACCxConfig_H ((1UL << 18)) /*!< Halt*/ 00079 00080 /** 00081 * @brief GPDMA structure using for DMA configuration 00082 */ 00083 typedef struct { 00084 uint32_t ChannelNum; /*!< DMA channel number, should be in 00085 * range from 0 to 7. 00086 * Note: DMA channel 0 has the highest priority 00087 * and DMA channel 7 the lowest priority. 00088 */ 00089 uint32_t TransferSize; /*!< Length/Size of transfer */ 00090 uint32_t TransferWidth; /*!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_M2M only */ 00091 uint32_t SrcAddr; /*!< Physical Source Address, used in case TransferType is chosen as 00092 * GPDMA_TRANSFERTYPE_M2M or GPDMA_TRANSFERTYPE_M2P */ 00093 uint32_t DstAddr; /*!< Physical Destination Address, used in case TransferType is chosen as 00094 * GPDMA_TRANSFERTYPE_M2M or GPDMA_TRANSFERTYPE_P2M */ 00095 uint32_t TransferType; /*!< Transfer Type, should be one of the following: 00096 * - GPDMA_TRANSFERTYPE_M2M: Memory to memory - DMA control 00097 * - GPDMA_TRANSFERTYPE_M2P: Memory to peripheral - DMA control 00098 * - GPDMA_TRANSFERTYPE_P2M: Peripheral to memory - DMA control 00099 * - GPDMA_TRANSFERTYPE_P2P: Source peripheral to destination peripheral - DMA control 00100 */ 00101 } GPDMA_Channel_CFG_T; 00102 00103 /****************************************************************************** 00104 * External global variables 00105 *****************************************************************************/ 00106 00107 /****************************************************************************** 00108 * Local variables 00109 *****************************************************************************/ 00110 00111 static bool used_channels[NUM_GPDMA_CHANNELS]; 00112 00113 /****************************************************************************** 00114 * Local Functions 00115 *****************************************************************************/ 00116 00117 static void gpdma_transfer(GPDMA_Channel_CFG_T* cfg, 00118 uint32_t CtrlWord, 00119 uint32_t LinkListItem, 00120 uint8_t SrcPeripheral, 00121 uint8_t DstPeripheral) 00122 { 00123 /* Get Channel pointer */ 00124 LPC_GPDMACH_TypeDef* pCh = GPDMACH(cfg->ChannelNum); 00125 00126 /* Reset the Interrupt status */ 00127 LPC_GPDMA->IntTCClear = CH_MASK(cfg->ChannelNum); 00128 LPC_GPDMA->IntErrClr = CH_MASK(cfg->ChannelNum); 00129 00130 /* Assign Linker List Item value */ 00131 pCh->CLLI = LinkListItem; 00132 00133 /* Enable DMA channels, little endian */ 00134 LPC_GPDMA->Config = GPDMA_DMACConfig_E; 00135 while (!(LPC_GPDMA->Config & GPDMA_DMACConfig_E)) {} 00136 00137 pCh->CSrcAddr = cfg->SrcAddr; 00138 pCh->CDestAddr = cfg->DstAddr; 00139 00140 /* Configure DMA Channel, enable Error Counter and Terminate counter */ 00141 pCh->CConfig = GPDMA_DMACCxConfig_IE 00142 | GPDMA_DMACCxConfig_ITC 00143 | GPDMA_DMACCxConfig_TransferType((uint32_t) cfg->TransferType) 00144 | GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral) 00145 | GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral); 00146 00147 pCh->CControl = CtrlWord; 00148 00149 /* Start the Channel */ 00150 pCh->CConfig |= GPDMA_DMACCxConfig_E; 00151 } 00152 00153 /****************************************************************************** 00154 * Public Functions 00155 *****************************************************************************/ 00156 00157 void gpdma_init() 00158 { 00159 uint8_t i; 00160 00161 /* Enable GPDMA master clock */ 00162 LPC_SC->PCONP |= (1<<29); 00163 00164 /* Reset all channel configuration register */ 00165 for (i = 0; i < NUM_GPDMA_CHANNELS; i++) { 00166 GPDMACH(i)->CConfig = 0; 00167 } 00168 00169 /* Clear all DMA interrupt and error flag */ 00170 LPC_GPDMA->IntTCClear = 0xFF; 00171 LPC_GPDMA->IntErrClr = 0xFF; 00172 00173 /* Reset all channels are free */ 00174 for (int i = 0; i < NUM_GPDMA_CHANNELS; i++) 00175 { 00176 used_channels[i] = false; 00177 } 00178 } 00179 00180 void gpdma_deinit() 00181 { 00182 /* Disable GPDMA master clock */ 00183 LPC_SC->PCONP &= ~(1<<29); 00184 } 00185 00186 void gpdma_stop(uint8_t ChannelNum) 00187 { 00188 if (ChannelNum >= NUM_GPDMA_CHANNELS) { 00189 return; 00190 } 00191 00192 /* Disable channel */ 00193 GPDMACH(ChannelNum)->CConfig &= ~GPDMA_DMACCxConfig_E; 00194 00195 /* check terminal count interrupt request status for DMA */ 00196 if (LPC_GPDMA->IntTCStat & CH_MASK(ChannelNum)) { 00197 /* Clear terminate counter Interrupt pending */ 00198 LPC_GPDMA->IntTCClear = CH_MASK(ChannelNum); 00199 } 00200 00201 /* check status of the error interrupt for DMA channels */ 00202 if (LPC_GPDMA->IntErrStat & CH_MASK(ChannelNum)) { 00203 /* clear the error interrupt request */ 00204 LPC_GPDMA->IntErrClr = CH_MASK(ChannelNum); 00205 } 00206 00207 used_channels[ChannelNum] = false; 00208 } 00209 00210 bool gpdma_interrupt(uint8_t ChannelNum) 00211 { 00212 /* check status of DMA channel interrupts */ 00213 if (LPC_GPDMA->IntStat & CH_MASK(ChannelNum)) { 00214 /* Check counter terminal status */ 00215 if (LPC_GPDMA->IntTCStat & CH_MASK(ChannelNum)) { 00216 /* Clear terminate counter Interrupt pending */ 00217 LPC_GPDMA->IntTCClear = CH_MASK(ChannelNum); 00218 return true; 00219 } 00220 /* Check error terminal status */ 00221 if (LPC_GPDMA->IntErrStat & CH_MASK(ChannelNum)) { 00222 /* Clear error counter Interrupt pending */ 00223 LPC_GPDMA->IntErrClr = CH_MASK(ChannelNum); 00224 return false; 00225 } 00226 } 00227 return false; 00228 } 00229 00230 bool gpdma_getFreeChannel(uint8_t* pCh) 00231 { 00232 for (int i = 0; i < NUM_GPDMA_CHANNELS; i++) 00233 { 00234 if ((!used_channels[i]) && ((LPC_GPDMA->EnbldChns & CH_MASK(i)) == 0)) 00235 { 00236 used_channels[i] = true; 00237 *pCh = i; 00238 return true; 00239 } 00240 } 00241 return false; 00242 } 00243 00244 bool gpdma_transfer_to_mci(uint8_t ChannelNum, 00245 uint32_t src, 00246 uint32_t Size) 00247 { 00248 GPDMA_Channel_CFG_T cfg; 00249 cfg.ChannelNum = ChannelNum; 00250 cfg.TransferType = GPDMA_TRANSFERTYPE_M2P_CONTROLLER_PERIPHERAL; 00251 cfg.TransferSize = Size; 00252 cfg.TransferWidth = 0; 00253 cfg.SrcAddr = src; 00254 cfg.DstAddr = (uint32_t) (&LPC_MCI->FIFO); 00255 00256 uint32_t ctrl_word = 00257 GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize) 00258 | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8) 00259 | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8) 00260 | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD) 00261 | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD) 00262 | GPDMA_DMACCxControl_DestTransUseAHBMaster1 00263 | GPDMA_DMACCxControl_SI 00264 | GPDMA_DMACCxControl_I; 00265 00266 if (LPC_GPDMA->EnbldChns & CH_MASK(ChannelNum)) { 00267 /* This channel is enabled, return ERROR, need to release this channel first */ 00268 return false; 00269 } 00270 00271 /* Select SD card interface in the DMA MUX*/ 00272 LPC_SC->DMAREQSEL &= ~(1 << 1); 00273 00274 gpdma_transfer(&cfg, ctrl_word, 0, GPDMA_CONN_MEMORY, GPDMA_CONN_SDC); 00275 return true; 00276 } 00277 00278 bool gpdma_transfer_from_mci(uint8_t ChannelNum, 00279 uint32_t dst, 00280 uint32_t Size) 00281 { 00282 GPDMA_Channel_CFG_T cfg; 00283 cfg.ChannelNum = ChannelNum; 00284 cfg.TransferType = GPDMA_TRANSFERTYPE_P2M_CONTROLLER_PERIPHERAL; 00285 cfg.TransferSize = Size; 00286 cfg.TransferWidth = 0; 00287 cfg.SrcAddr = (uint32_t) (&LPC_MCI->FIFO); 00288 cfg.DstAddr = dst; 00289 00290 uint32_t ctrl_word = 00291 GPDMA_DMACCxControl_TransferSize((uint32_t) cfg.TransferSize) 00292 | GPDMA_DMACCxControl_SBSize(GPDMA_BSIZE_8) 00293 | GPDMA_DMACCxControl_DBSize(GPDMA_BSIZE_8) 00294 | GPDMA_DMACCxControl_SWidth(GPDMA_WIDTH_WORD) 00295 | GPDMA_DMACCxControl_DWidth(GPDMA_WIDTH_WORD) 00296 | GPDMA_DMACCxControl_SrcTransUseAHBMaster1 00297 | GPDMA_DMACCxControl_DI 00298 | GPDMA_DMACCxControl_I; 00299 00300 if (LPC_GPDMA->EnbldChns & CH_MASK(ChannelNum)) { 00301 /* This channel is enabled, return ERROR, need to release this channel first */ 00302 return false; 00303 } 00304 00305 /* Select SD card interface in the DMA MUX*/ 00306 LPC_SC->DMAREQSEL &= ~(1 << 1); 00307 00308 gpdma_transfer(&cfg, ctrl_word, 0, GPDMA_CONN_SDC, GPDMA_CONN_MEMORY); 00309 return true; 00310 } 00311 00312
Generated on Tue Jul 12 2022 15:13:41 by 1.7.2