t

Dependencies:   DM_FATFileSystem DM_HttpServer DM_USBHost EthernetInterface USBDevice mbed-rpc mbed-rtos

Fork of DMSupport by Embedded Artists

Committer:
JVI_1556
Date:
Fri Oct 26 11:19:35 2018 +0000
Revision:
41:096931c776eb
Parent:
38:420cdc281467
test

Who changed what in which revision?

UserRevisionLine numberNew 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 }