MODDMA GPDMA Controller New features: transfer pins to memory buffer under periodic timer control and send double buffers to DAC
Dependents: FirstTest WaveSim IO-dma-memmem DACDMAfuncgenlib ... more
MODDMA.cpp
00001 /* 00002 Copyright (c) 2010 Andy Kirkham 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 #include "iomacros.h" 00023 #include "MODDMA.h" 00024 00025 namespace AjK { 00026 00027 // Create a "hook" for our ISR to make callbacks. Set by init() 00028 class MODDMA *moddma_p = (class MODDMA *)NULL; 00029 00030 void 00031 MODDMA::Enable(CHANNELS ChannelNumber) 00032 { 00033 LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); 00034 pChannel->DMACCConfig |= _E ; 00035 } 00036 00037 bool 00038 MODDMA::Enabled(CHANNELS ChannelNumber) 00039 { 00040 LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); 00041 return (bool)(pChannel->DMACCConfig & _E ); 00042 } 00043 00044 void 00045 MODDMA::Disable(CHANNELS ChannelNumber) 00046 { 00047 LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); 00048 pChannel->DMACCConfig &= ~(_E ); 00049 } 00050 00051 bool 00052 MODDMA::isActive(CHANNELS ChannelNumber) 00053 { 00054 LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); 00055 return (bool)( pChannel->DMACCConfig & CxConfig_A() ) ; 00056 } 00057 00058 void 00059 MODDMA::haltChannel(CHANNELS ChannelNumber) 00060 { 00061 LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); 00062 pChannel->DMACCConfig |= CxConfig_H(); 00063 } 00064 00065 uint32_t 00066 MODDMA::getControl(CHANNELS ChannelNumber) 00067 { 00068 LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); 00069 return pChannel->DMACCControl; 00070 } 00071 00072 uint32_t oldDMAHandler = 0; 00073 typedef void (*MODDMA_FN)(void); 00074 00075 extern "C" void MODDMA_IRQHandler(void) { 00076 uint32_t channel_mask; 00077 00078 if (moddma_p == (class MODDMA *)NULL) { 00079 if (oldDMAHandler) { 00080 ((MODDMA_FN)oldDMAHandler)(); 00081 return; 00082 } 00083 else { 00084 error("Interrupt without instance"); 00085 } 00086 } 00087 00088 for (int channel_number = 0; channel_number < 8; channel_number++) { 00089 channel_mask = (1UL << channel_number); 00090 if (LPC_GPDMA->DMACIntStat & channel_mask) { 00091 if (LPC_GPDMA->DMACIntTCStat & channel_mask) { 00092 if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) { 00093 moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number); 00094 moddma_p->setIrqType(MODDMA::TcIrq ); 00095 moddma_p->setups[channel_number]->isrIntTCStat->call(); 00096 moddma_p->isrIntTCStat.call(); 00097 // The user callback should clear the IRQ. But if they forget 00098 // then the Mbed will lockup. So, check to see if the IRQ has 00099 // been dismissed, if not, we will dismiss it here. 00100 if (LPC_GPDMA->DMACIntTCStat & channel_mask) { 00101 LPC_GPDMA->DMACIntTCClear = channel_mask; 00102 } 00103 // If the user has left the channel enabled, disable it. 00104 // Note, we don't check Active here as it may block inside 00105 // an ISR, we just shut it down immediately. If the user 00106 // must wait for completion they should implement their 00107 // own ISR. But only disable if the LLI linked list register 00108 // is null otherwise we can crap out a series of transfers. 00109 if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) { 00110 if (moddma_p->lli( (MODDMA::CHANNELS)channel_number ) == 0 ) { 00111 moddma_p->Disable( (MODDMA::CHANNELS)channel_number ); 00112 } 00113 } 00114 } 00115 } 00116 00117 if (LPC_GPDMA->DMACIntErrStat & channel_mask) { 00118 if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) { 00119 moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number); 00120 moddma_p->setIrqType(MODDMA::ErrIrq ); 00121 moddma_p->setups[channel_number]->isrIntErrStat->call(); 00122 moddma_p->isrIntErrStat.call(); 00123 // The user callback should clear the IRQ. But if they forget 00124 // then the Mbed will lockup. So, check to see if the IRQ has 00125 // been dismissed, if not, we will dismiss it here. 00126 if (LPC_GPDMA->DMACIntErrStat & channel_mask) { 00127 LPC_GPDMA->DMACIntErrClr = channel_mask; 00128 } 00129 // If the user has left the channel enabled, disable it. 00130 // Not, we don't check Active here as it may block inside 00131 // an ISR, we just shut it down immediately. If the user 00132 // must wait for completion they should implement their 00133 // own ISR. But only disable if the LLI linked list register 00134 // is null otherwise we can crap out a series of transfers. 00135 if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) { 00136 if (moddma_p->lli( (MODDMA::CHANNELS)channel_number ) == 0 ) { 00137 moddma_p->Disable( (MODDMA::CHANNELS)channel_number ); 00138 } 00139 } 00140 } 00141 } 00142 } 00143 } 00144 00145 /* IRQ should be handled by now, check to make sure. */ 00146 if (LPC_GPDMA->DMACIntStat) { 00147 ((MODDMA_FN)oldDMAHandler)(); 00148 LPC_GPDMA->DMACIntTCClear = (uint32_t)0xFF; /* If not, clear anyway! */ 00149 } 00150 if (LPC_GPDMA->DMACIntErrStat) { 00151 ((MODDMA_FN)oldDMAHandler)(); 00152 LPC_GPDMA->DMACIntErrClr = (uint32_t)0xFF; /* If not, clear anyway! */ 00153 } 00154 } 00155 00156 }; // namespace AjK ends 00157
Generated on Tue Jul 12 2022 12:57:52 by 1.7.2