
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@40:6df4f63aa406, 2015-06-10 (annotated)
- Committer:
- alindvall
- Date:
- Wed Jun 10 09:54:15 2015 +0000
- Revision:
- 40:6df4f63aa406
- Parent:
- 38:420cdc281467
Updated USBDevice, mbed-src and mbed-rtos libraries to latest version. Fixed compiler errors related to us_ticker_read() that was introduced in latest mbed-src version.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
embeddedartists | 38:420cdc281467 | 1 | /* |
embeddedartists | 38:420cdc281467 | 2 | * Copyright 2015 Embedded Artists AB |
embeddedartists | 38:420cdc281467 | 3 | * |
embeddedartists | 38:420cdc281467 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
embeddedartists | 38:420cdc281467 | 5 | * you may not use this file except in compliance with the License. |
embeddedartists | 38:420cdc281467 | 6 | * You may obtain a copy of the License at |
embeddedartists | 38:420cdc281467 | 7 | * |
embeddedartists | 38:420cdc281467 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
embeddedartists | 38:420cdc281467 | 9 | * |
embeddedartists | 38:420cdc281467 | 10 | * Unless required by applicable law or agreed to in writing, software |
embeddedartists | 38:420cdc281467 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
embeddedartists | 38:420cdc281467 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
embeddedartists | 38:420cdc281467 | 13 | * See the License for the specific language governing permissions and |
embeddedartists | 38:420cdc281467 | 14 | * limitations under the License. |
embeddedartists | 38:420cdc281467 | 15 | */ |
embeddedartists | 38:420cdc281467 | 16 | |
embeddedartists | 38:420cdc281467 | 17 | #include "mbed.h" |
embeddedartists | 38:420cdc281467 | 18 | #include "DMBoard.h" |
embeddedartists | 38:420cdc281467 | 19 | #include "GPDMA.h" |
embeddedartists | 38:420cdc281467 | 20 | |
embeddedartists | 38:420cdc281467 | 21 | |
embeddedartists | 38:420cdc281467 | 22 | /****************************************************************************** |
embeddedartists | 38:420cdc281467 | 23 | * Defines and typedefs |
embeddedartists | 38:420cdc281467 | 24 | *****************************************************************************/ |
embeddedartists | 38:420cdc281467 | 25 | |
embeddedartists | 38:420cdc281467 | 26 | #define GPDMACH(__x) ((LPC_GPDMACH_TypeDef*)(LPC_GPDMACH0_BASE + (0x20 * (__x)))) |
embeddedartists | 38:420cdc281467 | 27 | |
embeddedartists | 38:420cdc281467 | 28 | #define CH_MASK(__ch) (((1UL << (__ch)) & 0xFF)) |
embeddedartists | 38:420cdc281467 | 29 | |
embeddedartists | 38:420cdc281467 | 30 | #define GPDMA_ALL_CH_MASK (0xff) |
embeddedartists | 38:420cdc281467 | 31 | |
embeddedartists | 38:420cdc281467 | 32 | /****************************************************************************** |
embeddedartists | 38:420cdc281467 | 33 | * Local variables |
embeddedartists | 38:420cdc281467 | 34 | *****************************************************************************/ |
embeddedartists | 38:420cdc281467 | 35 | |
embeddedartists | 38:420cdc281467 | 36 | /****************************************************************************** |
embeddedartists | 38:420cdc281467 | 37 | * Private Class |
embeddedartists | 38:420cdc281467 | 38 | *****************************************************************************/ |
embeddedartists | 38:420cdc281467 | 39 | |
embeddedartists | 38:420cdc281467 | 40 | /****************************************************************************** |
embeddedartists | 38:420cdc281467 | 41 | * DMA Interrupt Functon |
embeddedartists | 38:420cdc281467 | 42 | *****************************************************************************/ |
embeddedartists | 38:420cdc281467 | 43 | |
embeddedartists | 38:420cdc281467 | 44 | static void mydmairq() |
embeddedartists | 38:420cdc281467 | 45 | { |
embeddedartists | 38:420cdc281467 | 46 | GPDMA::instance().processInterrupt(); |
embeddedartists | 38:420cdc281467 | 47 | } |
embeddedartists | 38:420cdc281467 | 48 | |
embeddedartists | 38:420cdc281467 | 49 | /****************************************************************************** |
embeddedartists | 38:420cdc281467 | 50 | * Private Functions |
embeddedartists | 38:420cdc281467 | 51 | *****************************************************************************/ |
embeddedartists | 38:420cdc281467 | 52 | |
embeddedartists | 38:420cdc281467 | 53 | /****************************************************************************** |
embeddedartists | 38:420cdc281467 | 54 | * Public Functions |
embeddedartists | 38:420cdc281467 | 55 | *****************************************************************************/ |
embeddedartists | 38:420cdc281467 | 56 | |
embeddedartists | 38:420cdc281467 | 57 | GPDMA::GPDMA() : _usedChannels(0), _initialized(false) |
embeddedartists | 38:420cdc281467 | 58 | { |
embeddedartists | 38:420cdc281467 | 59 | for (int i = 0; i < NumDMAChannels; i++) { |
embeddedartists | 38:420cdc281467 | 60 | _chData[i].inUse = false; |
embeddedartists | 38:420cdc281467 | 61 | _chData[i].func = NULL; |
embeddedartists | 38:420cdc281467 | 62 | } |
embeddedartists | 38:420cdc281467 | 63 | |
embeddedartists | 38:420cdc281467 | 64 | /* Redirect all DMA IRQs to the local mydmairq() function */ |
embeddedartists | 38:420cdc281467 | 65 | NVIC_SetVector(DMA_IRQn, (uint32_t) mydmairq); |
embeddedartists | 38:420cdc281467 | 66 | } |
embeddedartists | 38:420cdc281467 | 67 | |
embeddedartists | 38:420cdc281467 | 68 | GPDMA::~GPDMA() |
embeddedartists | 38:420cdc281467 | 69 | { |
embeddedartists | 38:420cdc281467 | 70 | } |
embeddedartists | 38:420cdc281467 | 71 | |
embeddedartists | 38:420cdc281467 | 72 | void GPDMA::init() |
embeddedartists | 38:420cdc281467 | 73 | { |
embeddedartists | 38:420cdc281467 | 74 | _mutex.lock(); |
embeddedartists | 38:420cdc281467 | 75 | if (!_initialized) { |
embeddedartists | 38:420cdc281467 | 76 | /* Enable GPDMA master clock */ |
embeddedartists | 38:420cdc281467 | 77 | LPC_SC->PCONP |= (1<<29); |
embeddedartists | 38:420cdc281467 | 78 | |
embeddedartists | 38:420cdc281467 | 79 | /* Reset all channel configuration register */ |
embeddedartists | 38:420cdc281467 | 80 | for (int i = 0; i < NumDMAChannels; i++) { |
embeddedartists | 38:420cdc281467 | 81 | GPDMACH(i)->CConfig = 0; |
embeddedartists | 38:420cdc281467 | 82 | } |
embeddedartists | 38:420cdc281467 | 83 | |
embeddedartists | 38:420cdc281467 | 84 | /* Clear all DMA interrupt and error flag */ |
embeddedartists | 38:420cdc281467 | 85 | LPC_GPDMA->IntTCClear = 0xFF; |
embeddedartists | 38:420cdc281467 | 86 | LPC_GPDMA->IntErrClr = 0xFF; |
embeddedartists | 38:420cdc281467 | 87 | |
embeddedartists | 38:420cdc281467 | 88 | /* Reset all channel datas */ |
embeddedartists | 38:420cdc281467 | 89 | for (int i = 0; i < NumDMAChannels; i++) { |
embeddedartists | 38:420cdc281467 | 90 | _chData[i].inUse = false; |
embeddedartists | 38:420cdc281467 | 91 | _chData[i].func = NULL; |
embeddedartists | 38:420cdc281467 | 92 | } |
embeddedartists | 38:420cdc281467 | 93 | |
embeddedartists | 38:420cdc281467 | 94 | _initialized = true; |
embeddedartists | 38:420cdc281467 | 95 | } |
embeddedartists | 38:420cdc281467 | 96 | _mutex.unlock(); |
embeddedartists | 38:420cdc281467 | 97 | } |
embeddedartists | 38:420cdc281467 | 98 | |
embeddedartists | 38:420cdc281467 | 99 | void GPDMA::deinit() |
embeddedartists | 38:420cdc281467 | 100 | { |
embeddedartists | 38:420cdc281467 | 101 | _mutex.lock(); |
embeddedartists | 38:420cdc281467 | 102 | if (_usedChannels == 0) { |
embeddedartists | 38:420cdc281467 | 103 | /* Disable the real interrupt */ |
embeddedartists | 38:420cdc281467 | 104 | NVIC_DisableIRQ(DMA_IRQn); |
embeddedartists | 38:420cdc281467 | 105 | |
embeddedartists | 38:420cdc281467 | 106 | /* Clear all DMA interrupt and error flag */ |
embeddedartists | 38:420cdc281467 | 107 | LPC_GPDMA->IntTCClear = 0xFF; |
embeddedartists | 38:420cdc281467 | 108 | LPC_GPDMA->IntErrClr = 0xFF; |
embeddedartists | 38:420cdc281467 | 109 | |
embeddedartists | 38:420cdc281467 | 110 | /* Disable GPDMA master clock */ |
embeddedartists | 38:420cdc281467 | 111 | LPC_SC->PCONP &= ~(1<<29); |
embeddedartists | 38:420cdc281467 | 112 | |
embeddedartists | 38:420cdc281467 | 113 | _initialized = false; |
embeddedartists | 38:420cdc281467 | 114 | } |
embeddedartists | 38:420cdc281467 | 115 | _mutex.unlock(); |
embeddedartists | 38:420cdc281467 | 116 | } |
embeddedartists | 38:420cdc281467 | 117 | |
embeddedartists | 38:420cdc281467 | 118 | GPDMA::DMAChannels GPDMA::acquireChannel(void (*irqfunc)(void), DMAChannels suggested) |
embeddedartists | 38:420cdc281467 | 119 | { |
embeddedartists | 38:420cdc281467 | 120 | DMAChannels result = DMACh_Unavailable; |
embeddedartists | 38:420cdc281467 | 121 | _mutex.lock(); |
embeddedartists | 38:420cdc281467 | 122 | if (!_initialized) { |
embeddedartists | 38:420cdc281467 | 123 | init(); |
embeddedartists | 38:420cdc281467 | 124 | } |
embeddedartists | 38:420cdc281467 | 125 | for (int i = suggested; i < NumDMAChannels; i++) { |
embeddedartists | 38:420cdc281467 | 126 | if ((!_chData[i].inUse) && ((LPC_GPDMA->EnbldChns & CH_MASK(i)) == 0)) { |
embeddedartists | 38:420cdc281467 | 127 | _chData[i].inUse = true; |
embeddedartists | 38:420cdc281467 | 128 | _chData[i].func = irqfunc; |
embeddedartists | 38:420cdc281467 | 129 | result = (DMAChannels)i; |
embeddedartists | 38:420cdc281467 | 130 | _usedChannels++; |
embeddedartists | 38:420cdc281467 | 131 | break; |
embeddedartists | 38:420cdc281467 | 132 | } |
embeddedartists | 38:420cdc281467 | 133 | } |
embeddedartists | 38:420cdc281467 | 134 | |
embeddedartists | 38:420cdc281467 | 135 | _mutex.unlock(); |
embeddedartists | 38:420cdc281467 | 136 | return result; |
embeddedartists | 38:420cdc281467 | 137 | } |
embeddedartists | 38:420cdc281467 | 138 | |
embeddedartists | 38:420cdc281467 | 139 | void GPDMA::releaseChannel(DMAChannels ch) |
embeddedartists | 38:420cdc281467 | 140 | { |
embeddedartists | 38:420cdc281467 | 141 | _mutex.lock(); |
embeddedartists | 38:420cdc281467 | 142 | if (ch < NumDMAChannels) { |
embeddedartists | 38:420cdc281467 | 143 | stopTransfer(ch); |
embeddedartists | 38:420cdc281467 | 144 | if (_chData[ch].inUse) { |
embeddedartists | 38:420cdc281467 | 145 | _usedChannels--; |
embeddedartists | 38:420cdc281467 | 146 | } |
embeddedartists | 38:420cdc281467 | 147 | _chData[ch].inUse = false; |
embeddedartists | 38:420cdc281467 | 148 | _chData[ch].func = NULL; |
embeddedartists | 38:420cdc281467 | 149 | } |
embeddedartists | 38:420cdc281467 | 150 | _mutex.unlock(); |
embeddedartists | 38:420cdc281467 | 151 | } |
embeddedartists | 38:420cdc281467 | 152 | |
embeddedartists | 38:420cdc281467 | 153 | LPC_GPDMACH_TypeDef* GPDMA::getDirectRegisters(DMAChannels ch) |
embeddedartists | 38:420cdc281467 | 154 | { |
embeddedartists | 38:420cdc281467 | 155 | if (ch < NumDMAChannels) { |
embeddedartists | 38:420cdc281467 | 156 | return GPDMACH(ch); |
embeddedartists | 38:420cdc281467 | 157 | } else { |
embeddedartists | 38:420cdc281467 | 158 | return NULL; |
embeddedartists | 38:420cdc281467 | 159 | } |
embeddedartists | 38:420cdc281467 | 160 | } |
embeddedartists | 38:420cdc281467 | 161 | |
embeddedartists | 38:420cdc281467 | 162 | void GPDMA::processInterrupt() |
embeddedartists | 38:420cdc281467 | 163 | { |
embeddedartists | 38:420cdc281467 | 164 | /* check status of DMA channel interrupts */ |
embeddedartists | 38:420cdc281467 | 165 | uint32_t intstat = LPC_GPDMA->IntStat; |
embeddedartists | 38:420cdc281467 | 166 | |
embeddedartists | 38:420cdc281467 | 167 | for (int i = 0; i < NumDMAChannels; i++) { |
embeddedartists | 38:420cdc281467 | 168 | uint32_t mask = CH_MASK(i); |
embeddedartists | 38:420cdc281467 | 169 | if (intstat & mask) { |
embeddedartists | 38:420cdc281467 | 170 | if (_chData[i].func != NULL) { |
embeddedartists | 38:420cdc281467 | 171 | /* Notify registered subscriber */ |
embeddedartists | 38:420cdc281467 | 172 | _chData[i].func();//GPDMACH(i), (tcstat&mask)!=0, (errstat&mask)!=0); |
embeddedartists | 38:420cdc281467 | 173 | } |
embeddedartists | 38:420cdc281467 | 174 | } |
embeddedartists | 38:420cdc281467 | 175 | } |
embeddedartists | 38:420cdc281467 | 176 | |
embeddedartists | 38:420cdc281467 | 177 | if ((LPC_GPDMA->EnbldChns & GPDMA_ALL_CH_MASK) == 0) { |
embeddedartists | 38:420cdc281467 | 178 | /* No more enabled DMA channels, so turn of DMA IRQ */ |
embeddedartists | 38:420cdc281467 | 179 | //NVIC_DisableIRQ(DMA_IRQn); |
embeddedartists | 38:420cdc281467 | 180 | } |
embeddedartists | 38:420cdc281467 | 181 | } |
embeddedartists | 38:420cdc281467 | 182 | |
embeddedartists | 38:420cdc281467 | 183 | bool GPDMA::transfer(GPDMA_Channel_CFG_T* cfg, uint32_t CtrlWord, |
embeddedartists | 38:420cdc281467 | 184 | uint32_t LinkListItem, uint8_t SrcPeripheral, |
embeddedartists | 38:420cdc281467 | 185 | uint8_t DstPeripheral) |
embeddedartists | 38:420cdc281467 | 186 | { |
embeddedartists | 38:420cdc281467 | 187 | if (LPC_GPDMA->EnbldChns & CH_MASK(cfg->ChannelNum)) { |
embeddedartists | 38:420cdc281467 | 188 | /* This channel is enabled, return ERROR, need to release this channel first */ |
embeddedartists | 38:420cdc281467 | 189 | return false; |
embeddedartists | 38:420cdc281467 | 190 | } |
embeddedartists | 38:420cdc281467 | 191 | |
embeddedartists | 38:420cdc281467 | 192 | /* Get Channel pointer */ |
embeddedartists | 38:420cdc281467 | 193 | LPC_GPDMACH_TypeDef* pCh = GPDMACH(cfg->ChannelNum); |
embeddedartists | 38:420cdc281467 | 194 | |
embeddedartists | 38:420cdc281467 | 195 | /* Reset the Interrupt status */ |
embeddedartists | 38:420cdc281467 | 196 | LPC_GPDMA->IntTCClear = CH_MASK(cfg->ChannelNum); |
embeddedartists | 38:420cdc281467 | 197 | LPC_GPDMA->IntErrClr = CH_MASK(cfg->ChannelNum); |
embeddedartists | 38:420cdc281467 | 198 | |
embeddedartists | 38:420cdc281467 | 199 | /* Clear configuration */ |
embeddedartists | 38:420cdc281467 | 200 | pCh->CControl = 0x00; |
embeddedartists | 38:420cdc281467 | 201 | pCh->CConfig = 0x00; |
embeddedartists | 38:420cdc281467 | 202 | |
embeddedartists | 38:420cdc281467 | 203 | /* Assign Linker List Item value */ |
embeddedartists | 38:420cdc281467 | 204 | pCh->CLLI = LinkListItem; |
embeddedartists | 38:420cdc281467 | 205 | |
embeddedartists | 38:420cdc281467 | 206 | pCh->CSrcAddr = cfg->SrcAddr; |
embeddedartists | 38:420cdc281467 | 207 | pCh->CDestAddr = cfg->DstAddr; |
embeddedartists | 38:420cdc281467 | 208 | pCh->CControl = CtrlWord; |
embeddedartists | 38:420cdc281467 | 209 | |
embeddedartists | 38:420cdc281467 | 210 | /* Enable DMA channels, little endian */ |
embeddedartists | 38:420cdc281467 | 211 | LPC_GPDMA->Config = GPDMA_DMACConfig_E; |
embeddedartists | 38:420cdc281467 | 212 | while (!(LPC_GPDMA->Config & GPDMA_DMACConfig_E)) {} |
embeddedartists | 38:420cdc281467 | 213 | |
embeddedartists | 38:420cdc281467 | 214 | /* Configure DMA Channel, enable Error Counter and Terminate counter */ |
embeddedartists | 38:420cdc281467 | 215 | pCh->CConfig = GPDMA_DMACCxConfig_IE |
embeddedartists | 38:420cdc281467 | 216 | | GPDMA_DMACCxConfig_ITC |
embeddedartists | 38:420cdc281467 | 217 | | GPDMA_DMACCxConfig_TransferType((uint32_t) cfg->TransferType) |
embeddedartists | 38:420cdc281467 | 218 | | GPDMA_DMACCxConfig_SrcPeripheral(SrcPeripheral) |
embeddedartists | 38:420cdc281467 | 219 | | GPDMA_DMACCxConfig_DestPeripheral(DstPeripheral); |
embeddedartists | 38:420cdc281467 | 220 | |
embeddedartists | 38:420cdc281467 | 221 | /* Enable the interrupts */ |
embeddedartists | 38:420cdc281467 | 222 | NVIC_EnableIRQ(DMA_IRQn); |
embeddedartists | 38:420cdc281467 | 223 | |
embeddedartists | 38:420cdc281467 | 224 | /* Start the Channel */ |
embeddedartists | 38:420cdc281467 | 225 | pCh->CConfig |= GPDMA_DMACCxConfig_E; |
embeddedartists | 38:420cdc281467 | 226 | |
embeddedartists | 38:420cdc281467 | 227 | return true; |
embeddedartists | 38:420cdc281467 | 228 | } |
embeddedartists | 38:420cdc281467 | 229 | |
embeddedartists | 38:420cdc281467 | 230 | void GPDMA::stopTransfer(DMAChannels ch) |
embeddedartists | 38:420cdc281467 | 231 | { |
embeddedartists | 38:420cdc281467 | 232 | /* Disable channel */ |
embeddedartists | 38:420cdc281467 | 233 | GPDMACH(ch)->CConfig &= ~GPDMA_DMACCxConfig_E; |
embeddedartists | 38:420cdc281467 | 234 | |
embeddedartists | 38:420cdc281467 | 235 | /* Clear pending interrupts */ |
embeddedartists | 38:420cdc281467 | 236 | LPC_GPDMA->IntTCClear = CH_MASK(ch); |
embeddedartists | 38:420cdc281467 | 237 | LPC_GPDMA->IntErrClr = CH_MASK(ch); |
embeddedartists | 38:420cdc281467 | 238 | } |