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