A board support package for the LPC4088 Display Module.
Dependencies: DM_HttpServer DM_USBHost
Dependents: lpc4088_displaymodule_emwin lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI ... more
Fork of DMSupport by
GPDMA.cpp
00001 /* 00002 * Copyright 2015 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 #include "mbed.h" 00018 #include "DMBoard.h" 00019 #include "GPDMA.h" 00020 00021 00022 /****************************************************************************** 00023 * Defines and typedefs 00024 *****************************************************************************/ 00025 00026 #define GPDMACH(__x) ((LPC_GPDMACH_TypeDef*)(LPC_GPDMACH0_BASE + (0x20 * (__x)))) 00027 00028 #define CH_MASK(__ch) (((1UL << (__ch)) & 0xFF)) 00029 00030 #define GPDMA_ALL_CH_MASK (0xff) 00031 00032 /****************************************************************************** 00033 * Local variables 00034 *****************************************************************************/ 00035 00036 /****************************************************************************** 00037 * Private Class 00038 *****************************************************************************/ 00039 00040 /****************************************************************************** 00041 * DMA Interrupt Functon 00042 *****************************************************************************/ 00043 00044 static void mydmairq() 00045 { 00046 GPDMA::instance().processInterrupt(); 00047 } 00048 00049 /****************************************************************************** 00050 * Private Functions 00051 *****************************************************************************/ 00052 00053 /****************************************************************************** 00054 * Public Functions 00055 *****************************************************************************/ 00056 00057 GPDMA::GPDMA() : _usedChannels(0), _initialized(false) 00058 { 00059 for (int i = 0; i < NumDMAChannels; i++) { 00060 _chData[i].inUse = false; 00061 _chData[i].func = NULL; 00062 } 00063 00064 /* Redirect all DMA IRQs to the local mydmairq() function */ 00065 NVIC_SetVector(DMA_IRQn, (uint32_t) mydmairq); 00066 } 00067 00068 GPDMA::~GPDMA() 00069 { 00070 } 00071 00072 void GPDMA::init() 00073 { 00074 _mutex.lock(); 00075 if (!_initialized) { 00076 /* Enable GPDMA master clock */ 00077 LPC_SC->PCONP |= (1<<29); 00078 00079 /* Reset all channel configuration register */ 00080 for (int i = 0; i < NumDMAChannels; i++) { 00081 GPDMACH(i)->CConfig = 0; 00082 } 00083 00084 /* Clear all DMA interrupt and error flag */ 00085 LPC_GPDMA->IntTCClear = 0xFF; 00086 LPC_GPDMA->IntErrClr = 0xFF; 00087 00088 /* Reset all channel datas */ 00089 for (int i = 0; i < NumDMAChannels; i++) { 00090 _chData[i].inUse = false; 00091 _chData[i].func = NULL; 00092 } 00093 00094 _initialized = true; 00095 } 00096 _mutex.unlock(); 00097 } 00098 00099 void GPDMA::deinit() 00100 { 00101 _mutex.lock(); 00102 if (_usedChannels == 0) { 00103 /* Disable the real interrupt */ 00104 NVIC_DisableIRQ(DMA_IRQn); 00105 00106 /* Clear all DMA interrupt and error flag */ 00107 LPC_GPDMA->IntTCClear = 0xFF; 00108 LPC_GPDMA->IntErrClr = 0xFF; 00109 00110 /* Disable GPDMA master clock */ 00111 LPC_SC->PCONP &= ~(1<<29); 00112 00113 _initialized = false; 00114 } 00115 _mutex.unlock(); 00116 } 00117 00118 GPDMA::DMAChannels GPDMA::acquireChannel(void (*irqfunc)(void), DMAChannels suggested) 00119 { 00120 DMAChannels result = DMACh_Unavailable; 00121 _mutex.lock(); 00122 if (!_initialized) { 00123 init(); 00124 } 00125 for (int i = suggested; i < NumDMAChannels; i++) { 00126 if ((!_chData[i].inUse) && ((LPC_GPDMA->EnbldChns & CH_MASK(i)) == 0)) { 00127 _chData[i].inUse = true; 00128 _chData[i].func = irqfunc; 00129 result = (DMAChannels)i; 00130 _usedChannels++; 00131 break; 00132 } 00133 } 00134 00135 _mutex.unlock(); 00136 return result; 00137 } 00138 00139 void GPDMA::releaseChannel(DMAChannels ch) 00140 { 00141 _mutex.lock(); 00142 if (ch < NumDMAChannels) { 00143 stopTransfer(ch); 00144 if (_chData[ch].inUse) { 00145 _usedChannels--; 00146 } 00147 _chData[ch].inUse = false; 00148 _chData[ch].func = NULL; 00149 } 00150 _mutex.unlock(); 00151 } 00152 00153 LPC_GPDMACH_TypeDef* GPDMA::getDirectRegisters(DMAChannels ch) 00154 { 00155 if (ch < NumDMAChannels) { 00156 return GPDMACH(ch); 00157 } else { 00158 return NULL; 00159 } 00160 } 00161 00162 void GPDMA::processInterrupt() 00163 { 00164 /* check status of DMA channel interrupts */ 00165 uint32_t intstat = LPC_GPDMA->IntStat; 00166 00167 for (int i = 0; i < NumDMAChannels; i++) { 00168 uint32_t mask = CH_MASK(i); 00169 if (intstat & mask) { 00170 if (_chData[i].func != NULL) { 00171 /* Notify registered subscriber */ 00172 _chData[i].func();//GPDMACH(i), (tcstat&mask)!=0, (errstat&mask)!=0); 00173 } 00174 } 00175 } 00176 00177 if ((LPC_GPDMA->EnbldChns & GPDMA_ALL_CH_MASK) == 0) { 00178 /* No more enabled DMA channels, so turn of DMA IRQ */ 00179 //NVIC_DisableIRQ(DMA_IRQn); 00180 } 00181 } 00182 00183 bool GPDMA::transfer(GPDMA_Channel_CFG_T* cfg, uint32_t CtrlWord, 00184 uint32_t LinkListItem, uint8_t SrcPeripheral, 00185 uint8_t DstPeripheral) 00186 { 00187 if (LPC_GPDMA->EnbldChns & CH_MASK(cfg->ChannelNum)) { 00188 /* This channel is enabled, return ERROR, need to release this channel first */ 00189 return false; 00190 } 00191 00192 /* Get Channel pointer */ 00193 LPC_GPDMACH_TypeDef* pCh = GPDMACH(cfg->ChannelNum); 00194 00195 /* Reset the Interrupt status */ 00196 LPC_GPDMA->IntTCClear = CH_MASK(cfg->ChannelNum); 00197 LPC_GPDMA->IntErrClr = CH_MASK(cfg->ChannelNum); 00198 00199 /* Clear configuration */ 00200 pCh->CControl = 0x00; 00201 pCh->CConfig = 0x00; 00202 00203 /* Assign Linker List Item value */ 00204 pCh->CLLI = LinkListItem; 00205 00206 pCh->CSrcAddr = cfg->SrcAddr; 00207 pCh->CDestAddr = cfg->DstAddr; 00208 pCh->CControl = CtrlWord; 00209 00210 /* Enable DMA channels, little endian */ 00211 LPC_GPDMA->Config = GPDMA_DMACConfig_E; 00212 while (!(LPC_GPDMA->Config & GPDMA_DMACConfig_E)) {} 00213 00214 /* Configure DMA Channel, enable Error Counter and Terminate counter */ 00215 pCh->CConfig = GPDMA_DMACCxConfig_IE 00216 | GPDMA_DMACCxConfig_ITC 00217 | GPDMA_DMACCxConfig_TransferType((uint32_t) cfg->TransferType) 00218 | GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral) 00219 | GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral); 00220 00221 /* Enable the interrupts */ 00222 NVIC_EnableIRQ(DMA_IRQn); 00223 00224 /* Start the Channel */ 00225 pCh->CConfig |= GPDMA_DMACCxConfig_E; 00226 00227 return true; 00228 } 00229 00230 void GPDMA::stopTransfer(DMAChannels ch) 00231 { 00232 /* Disable channel */ 00233 GPDMACH(ch)->CConfig &= ~GPDMA_DMACCxConfig_E; 00234 00235 /* Clear pending interrupts */ 00236 LPC_GPDMA->IntTCClear = CH_MASK(ch); 00237 LPC_GPDMA->IntErrClr = CH_MASK(ch); 00238 }
Generated on Tue Jul 12 2022 14:18:31 by 1.7.2