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
Revision 8:cb4d323ce6fd, committed 2011-02-05
- Comitter:
- AjK
- Date:
- Sat Feb 05 08:53:26 2011 +0000
- Parent:
- 7:347110c7aefc
- Child:
- 9:e7ecf909e834
- Commit message:
- 1.5 See ChangeLog.c
Changed in this revision
--- a/CONFIG.h Wed Nov 24 00:32:49 2010 +0000 +++ b/CONFIG.h Sat Feb 05 08:53:26 2011 +0000 @@ -1,96 +1,95 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifdef NOCOMPILE - -#ifndef MODDMA_CONFIG_H -#define MODDMA_CONFIG_H - -#include "mbed.h" - -namespace AjK { - -// Forward reference. -class MODDMA; - -class MODDMA_Channel_CFG_t { -public: - - // ***************************************** - // From GPDMA by NXP MCU SW Application Team - // ***************************************** - - uint32_t ChannelNum; //!< DMA channel number, should be in range from 0 to 7. - uint32_t TransferSize; //!< Length/Size of transfer - uint32_t TransferWidth; //!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_m2m only - uint32_t SrcMemAddr; //!< Physical Src Addr, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::m2p - uint32_t DstMemAddr; //!< Physical Destination Address, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::p2m - uint32_t TransferType; //!< Transfer Type - uint32_t SrcConn; ///!< Peripheral Source Connection type, used in case TransferType is chosen as - uint32_t DstConn; //!< Peripheral Destination Connection type, used in case TransferType is chosen as - uint32_t DMALLI; //!< Linker List Item structure data address if there's no Linker List, set as '0' - - // Mbed specifics. - - MODDMA_Channel_CFG_t() { - isrIntTCStat = new FunctionPointer; - isrIntErrStat = new FunctionPointer; - } - - ~MODDMA_Channel_CFG_t() { - delete(isrIntTCStat); - delete(isrIntErrStat); - } - - class MODDMA_Channel_CFG_t * channelNum(uint32_t n) { ChannelNum = n; return this; } - class MODDMA_Channel_CFG_t * transferSize(uint32_t n) { TransferSize = n; return this; } - class MODDMA_Channel_CFG_t * transferWidth(uint32_t n) { TransferWidth = n; return this; } - class MODDMA_Channel_CFG_t * srcMemAddr(uint32_t n) { SrcMemAddr = n; return this; } - class MODDMA_Channel_CFG_t * dstMemAddr(uint32_t n) { DstMemAddr = n; return this; } - class MODDMA_Channel_CFG_t * transferType(uint32_t n) { TransferType = n; return this; } - class MODDMA_Channel_CFG_t * srcConn(uint32_t n) { SrcConn = n; return this; } - class MODDMA_Channel_CFG_t * dstConn(uint32_t n) { DstConn = n; return this; } - class MODDMA_Channel_CFG_t * dmaLLI(uint32_t n) { DMALLI = n; return this; } - - uint32_t channelNum(void) { return ChannelNum; } - - FunctionPointer *isrIntTCStat; - FunctionPointer *isrIntErrStat; -}; - -/** - * @brief GPDMA Linker List Item structure type definition - */ - /* -typedef struct { - uint32_t SrcAddr; //!< Source Address - uint32_t DstAddr; //!< Destination address - uint32_t NextLLI; //!< Next LLI address, otherwise set to '0' - uint32_t Control; //!< GPDMA Control of this LLI -} GPDMA_LLI_t; -*/ - - -}; // namespace AjK ends. - -#endif -#endif +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifdef NOCOMPILE + +#ifndef MODDMA_CONFIG_H +#define MODDMA_CONFIG_H + +#include "mbed.h" + +namespace AjK { + +// Forward reference. +class MODDMA; + +class MODDMA_Channel_CFG_t { +public: + + // ***************************************** + // From GPDMA by NXP MCU SW Application Team + // ***************************************** + + uint32_t ChannelNum; //!< DMA channel number, should be in range from 0 to 7. + uint32_t TransferSize; //!< Length/Size of transfer + uint32_t TransferWidth; //!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_m2m only + uint32_t SrcMemAddr; //!< Physical Src Addr, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::m2p + uint32_t DstMemAddr; //!< Physical Destination Address, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::p2m + uint32_t TransferType; //!< Transfer Type + uint32_t SrcConn; ///!< Peripheral Source Connection type, used in case TransferType is chosen as + uint32_t DstConn; //!< Peripheral Destination Connection type, used in case TransferType is chosen as + uint32_t DMALLI; //!< Linker List Item structure data address if there's no Linker List, set as '0' + + // Mbed specifics. + + MODDMA_Channel_CFG_t() { + isrIntTCStat = new FunctionPointer; + isrIntErrStat = new FunctionPointer; + } + + ~MODDMA_Channel_CFG_t() { + delete(isrIntTCStat); + delete(isrIntErrStat); + } + + class MODDMA_Channel_CFG_t * channelNum(uint32_t n) { ChannelNum = n; return this; } + class MODDMA_Channel_CFG_t * transferSize(uint32_t n) { TransferSize = n; return this; } + class MODDMA_Channel_CFG_t * transferWidth(uint32_t n) { TransferWidth = n; return this; } + class MODDMA_Channel_CFG_t * srcMemAddr(uint32_t n) { SrcMemAddr = n; return this; } + class MODDMA_Channel_CFG_t * dstMemAddr(uint32_t n) { DstMemAddr = n; return this; } + class MODDMA_Channel_CFG_t * transferType(uint32_t n) { TransferType = n; return this; } + class MODDMA_Channel_CFG_t * srcConn(uint32_t n) { SrcConn = n; return this; } + class MODDMA_Channel_CFG_t * dstConn(uint32_t n) { DstConn = n; return this; } + class MODDMA_Channel_CFG_t * dmaLLI(uint32_t n) { DMALLI = n; return this; } + + uint32_t channelNum(void) { return ChannelNum; } + + FunctionPointer *isrIntTCStat; + FunctionPointer *isrIntErrStat; +}; + +/** + * @brief GPDMA Linker List Item structure type definition + */ +class GPDMA_LLI_t +{ +public: + uint32_t SrcAddr; //!< Source Address + uint32_t DstAddr; //!< Destination address + uint32_t NextLLI; //!< Next LLI address, otherwise set to '0' + uint32_t Control; //!< GPDMA Control of this LLI +}; + +}; // namespace AjK ends. + +#endif +#endif
--- a/ChangeLog.c Wed Nov 24 00:32:49 2010 +0000 +++ b/ChangeLog.c Sat Feb 05 08:53:26 2011 +0000 @@ -1,5 +1,11 @@ /* $Id:$ +1.5 - 5 Feb 2011 + + * Found a bug in the NXP library that I had copied over. + http://mbed.org/forum/mbed/topic/1798 + * Added example2.cpp to support that forum thread. + 1.4 - 23/11/2010 * Added some extra overloaded methods to make calling certain
--- a/DATALUTS.cpp Wed Nov 24 00:32:49 2010 +0000 +++ b/DATALUTS.cpp Sat Feb 05 08:53:26 2011 +0000 @@ -1,147 +1,147 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODDMA.h" - -#ifndef MBED_H -#include "mbed.h" -#endif - -#ifndef MODDMA_CONFIG_H -#include "CONFIG.h" -#endif - -namespace AjK { - -uint32_t -MODDMA::LUTPerAddr(int n) -{ - const uint32_t lut[] = { - (uint32_t)&LPC_SSP0->DR // SSP0 Tx - , (uint32_t)&LPC_SSP0->DR // SSP0 Rx - , (uint32_t)&LPC_SSP1->DR // SSP1 Tx - , (uint32_t)&LPC_SSP1->DR // SSP1 Rx - , (uint32_t)&LPC_ADC->ADGDR // ADC - , (uint32_t)&LPC_I2S->I2STXFIFO // I2S Tx - , (uint32_t)&LPC_I2S->I2SRXFIFO // I2S Rx - , (uint32_t)&LPC_DAC->DACR // DAC - , (uint32_t)&LPC_UART0->THR // UART0 Tx - , (uint32_t)&LPC_UART0->RBR // UART0 Rx - , (uint32_t)&LPC_UART1->THR // UART1 Tx - , (uint32_t)&LPC_UART1->RBR // UART1 Rx - , (uint32_t)&LPC_UART2->THR // UART2 Tx - , (uint32_t)&LPC_UART2->RBR // UART2 Rx - , (uint32_t)&LPC_UART3->THR // UART3 Tx - , (uint32_t)&LPC_UART3->RBR // UART3 Rx - , (uint32_t)&LPC_TIM0->MR0 // MAT0.0 - , (uint32_t)&LPC_TIM0->MR1 // MAT0.1 - , (uint32_t)&LPC_TIM1->MR0 // MAT1.0 - , (uint32_t)&LPC_TIM1->MR1 // MAT1.1 - , (uint32_t)&LPC_TIM2->MR0 // MAT2.0 - , (uint32_t)&LPC_TIM2->MR1 // MAT2.1 - , (uint32_t)&LPC_TIM3->MR0 // MAT3.0 - , (uint32_t)&LPC_TIM3->MR1 // MAT3.1 - }; - return lut[n & 0xFF]; -} - -uint32_t -MODDMA::Channel_p(int channel) -{ - const uint32_t lut[] = { - (uint32_t)LPC_GPDMACH0 - , (uint32_t)LPC_GPDMACH1 - , (uint32_t)LPC_GPDMACH2 - , (uint32_t)LPC_GPDMACH3 - , (uint32_t)LPC_GPDMACH4 - , (uint32_t)LPC_GPDMACH5 - , (uint32_t)LPC_GPDMACH6 - , (uint32_t)LPC_GPDMACH7 - }; - return lut[channel & 0xFF]; -} - -uint8_t -MODDMA::LUTPerBurst(int n) -{ - const uint8_t lut[] = { - (uint8_t)_4 // SSP0 Tx - , (uint8_t)_4 // SSP0 Rx - , (uint8_t)_4 // SSP1 Tx - , (uint8_t)_4 // SSP1 Rx - , (uint8_t)_4 // ADC - , (uint8_t)_32 // I2S channel 0 - , (uint8_t)_32 // I2S channel 1 - , (uint8_t)_1 // DAC - , (uint8_t)_1 // UART0 Tx - , (uint8_t)_1 // UART0 Rx - , (uint8_t)_1 // UART1 Tx - , (uint8_t)_1 // UART1 Rx - , (uint8_t)_1 // UART2 Tx - , (uint8_t)_1 // UART2 Rx - , (uint8_t)_1 // UART3 Tx - , (uint8_t)_1 // UART3 Rx - , (uint8_t)_1 // MAT0.0 - , (uint8_t)_1 // MAT0.1 - , (uint8_t)_1 // MAT1.0 - , (uint8_t)_1 // MAT1.1 - , (uint8_t)_1 // MAT2.0 - , (uint8_t)_1 // MAT2.1 - , (uint8_t)_1 // MAT3.0 - , (uint8_t)_1 // MAT3.1 - }; - return lut[n & 0xFFF]; -} - -uint8_t -MODDMA::LUTPerWid(int n) -{ - const uint8_t lut[] = { - (uint8_t)byte // SSP0 Tx - , (uint8_t)byte // SSP0 Rx - , (uint8_t)byte // SSP1 Tx - , (uint8_t)byte // SSP1 Rx - , (uint8_t)word // ADC - , (uint8_t)word // I2S channel 0 - , (uint8_t)word // I2S channel 1 - , (uint8_t)byte // DAC - , (uint8_t)byte // UART0 Tx - , (uint8_t)byte // UART0 Rx - , (uint8_t)byte // UART1 Tx - , (uint8_t)byte // UART1 Rx - , (uint8_t)byte // UART2 Tx - , (uint8_t)byte // UART2 Rx - , (uint8_t)byte // UART3 Tx - , (uint8_t)byte // UART3 Rx - , (uint8_t)word // MAT0.0 - , (uint8_t)word // MAT0.1 - , (uint8_t)word // MAT1.0 - , (uint8_t)word // MAT1.1 - , (uint8_t)word // MAT2.0 - , (uint8_t)word // MAT2.1 - , (uint8_t)word // MAT3.0 - , (uint8_t)word // MAT3.1 - }; - return lut[n & 0xFFF]; -} - -}; // namespace AjK ends +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "MODDMA.h" + +#ifndef MBED_H +#include "mbed.h" +#endif + +#ifndef MODDMA_CONFIG_H +#include "CONFIG.h" +#endif + +namespace AjK { + +uint32_t +MODDMA::LUTPerAddr(int n) +{ + const uint32_t lut[] = { + (uint32_t)&LPC_SSP0->DR // SSP0 Tx + , (uint32_t)&LPC_SSP0->DR // SSP0 Rx + , (uint32_t)&LPC_SSP1->DR // SSP1 Tx + , (uint32_t)&LPC_SSP1->DR // SSP1 Rx + , (uint32_t)&LPC_ADC->ADGDR // ADC + , (uint32_t)&LPC_I2S->I2STXFIFO // I2S Tx + , (uint32_t)&LPC_I2S->I2SRXFIFO // I2S Rx + , (uint32_t)&LPC_DAC->DACR // DAC + , (uint32_t)&LPC_UART0->THR // UART0 Tx + , (uint32_t)&LPC_UART0->RBR // UART0 Rx + , (uint32_t)&LPC_UART1->THR // UART1 Tx + , (uint32_t)&LPC_UART1->RBR // UART1 Rx + , (uint32_t)&LPC_UART2->THR // UART2 Tx + , (uint32_t)&LPC_UART2->RBR // UART2 Rx + , (uint32_t)&LPC_UART3->THR // UART3 Tx + , (uint32_t)&LPC_UART3->RBR // UART3 Rx + , (uint32_t)&LPC_TIM0->MR0 // MAT0.0 + , (uint32_t)&LPC_TIM0->MR1 // MAT0.1 + , (uint32_t)&LPC_TIM1->MR0 // MAT1.0 + , (uint32_t)&LPC_TIM1->MR1 // MAT1.1 + , (uint32_t)&LPC_TIM2->MR0 // MAT2.0 + , (uint32_t)&LPC_TIM2->MR1 // MAT2.1 + , (uint32_t)&LPC_TIM3->MR0 // MAT3.0 + , (uint32_t)&LPC_TIM3->MR1 // MAT3.1 + }; + return lut[n & 0xFF]; +} + +uint32_t +MODDMA::Channel_p(int channel) +{ + const uint32_t lut[] = { + (uint32_t)LPC_GPDMACH0 + , (uint32_t)LPC_GPDMACH1 + , (uint32_t)LPC_GPDMACH2 + , (uint32_t)LPC_GPDMACH3 + , (uint32_t)LPC_GPDMACH4 + , (uint32_t)LPC_GPDMACH5 + , (uint32_t)LPC_GPDMACH6 + , (uint32_t)LPC_GPDMACH7 + }; + return lut[channel & 0xFF]; +} + +uint8_t +MODDMA::LUTPerBurst(int n) +{ + const uint8_t lut[] = { + (uint8_t)_4 // SSP0 Tx + , (uint8_t)_4 // SSP0 Rx + , (uint8_t)_4 // SSP1 Tx + , (uint8_t)_4 // SSP1 Rx + , (uint8_t)_1 // ADC + , (uint8_t)_32 // I2S channel 0 + , (uint8_t)_32 // I2S channel 1 + , (uint8_t)_1 // DAC + , (uint8_t)_1 // UART0 Tx + , (uint8_t)_1 // UART0 Rx + , (uint8_t)_1 // UART1 Tx + , (uint8_t)_1 // UART1 Rx + , (uint8_t)_1 // UART2 Tx + , (uint8_t)_1 // UART2 Rx + , (uint8_t)_1 // UART3 Tx + , (uint8_t)_1 // UART3 Rx + , (uint8_t)_1 // MAT0.0 + , (uint8_t)_1 // MAT0.1 + , (uint8_t)_1 // MAT1.0 + , (uint8_t)_1 // MAT1.1 + , (uint8_t)_1 // MAT2.0 + , (uint8_t)_1 // MAT2.1 + , (uint8_t)_1 // MAT3.0 + , (uint8_t)_1 // MAT3.1 + }; + return lut[n & 0xFFF]; +} + +uint8_t +MODDMA::LUTPerWid(int n) +{ + const uint8_t lut[] = { + (uint8_t)byte // SSP0 Tx + , (uint8_t)byte // SSP0 Rx + , (uint8_t)byte // SSP1 Tx + , (uint8_t)byte // SSP1 Rx + , (uint8_t)word // ADC + , (uint8_t)word // I2S channel 0 + , (uint8_t)word // I2S channel 1 + , (uint8_t)byte // DAC + , (uint8_t)byte // UART0 Tx + , (uint8_t)byte // UART0 Rx + , (uint8_t)byte // UART1 Tx + , (uint8_t)byte // UART1 Rx + , (uint8_t)byte // UART2 Tx + , (uint8_t)byte // UART2 Rx + , (uint8_t)byte // UART3 Tx + , (uint8_t)byte // UART3 Rx + , (uint8_t)word // MAT0.0 + , (uint8_t)word // MAT0.1 + , (uint8_t)word // MAT1.0 + , (uint8_t)word // MAT1.1 + , (uint8_t)word // MAT2.0 + , (uint8_t)word // MAT2.1 + , (uint8_t)word // MAT3.0 + , (uint8_t)word // MAT3.1 + }; + return lut[n & 0xFFF]; +} + +}; // namespace AjK ends
--- a/INIT.cpp Wed Nov 24 00:32:49 2010 +0000 +++ b/INIT.cpp Sat Feb 05 08:53:26 2011 +0000 @@ -1,69 +1,69 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODDMA.h" - -namespace AjK { - -extern uint32_t oldDMAHandler; -extern "C" void MODDMA_IRQHandler(void); -extern class MODDMA *moddma_p; - -void -MODDMA::init(bool isConstructorCalling, int Channels, int Tc, int Err) -{ - if (isConstructorCalling) { - if (LPC_SC->PCONP & (1UL << 29)) { - if (LPC_GPDMA->DMACConfig & 1) { - error("Only one instance of MODDMA can exist."); - } - } - LPC_SC->PCONP |= (1UL << 29); - LPC_GPDMA->DMACConfig = 1; - moddma_p = this; - for (int i = 0; i < 8; i++) { - setups[i] = (MODDMA_Config *)NULL; - } - } - - // Reset channel configuration register(s) - if (Channels & 0x01) LPC_GPDMACH0->DMACCConfig = 0; - if (Channels & 0x02) LPC_GPDMACH1->DMACCConfig = 0; - if (Channels & 0x04) LPC_GPDMACH2->DMACCConfig = 0; - if (Channels & 0x08) LPC_GPDMACH3->DMACCConfig = 0; - if (Channels & 0x10) LPC_GPDMACH4->DMACCConfig = 0; - if (Channels & 0x20) LPC_GPDMACH5->DMACCConfig = 0; - if (Channels & 0x40) LPC_GPDMACH6->DMACCConfig = 0; - if (Channels & 0x80) LPC_GPDMACH7->DMACCConfig = 0; - - /* Clear DMA interrupt and error flag */ - LPC_GPDMA->DMACIntTCClear = Tc; - LPC_GPDMA->DMACIntErrClr = Err; - - if (isConstructorCalling) { - oldDMAHandler = NVIC_GetVector(DMA_IRQn); - NVIC_SetVector(DMA_IRQn, (uint32_t)MODDMA_IRQHandler); - NVIC_EnableIRQ(DMA_IRQn); - } -} - -}; // namespace AjK ends +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "MODDMA.h" + +namespace AjK { + +extern uint32_t oldDMAHandler; +extern "C" void MODDMA_IRQHandler(void); +extern class MODDMA *moddma_p; + +void +MODDMA::init(bool isConstructorCalling, int Channels, int Tc, int Err) +{ + if (isConstructorCalling) { + if (LPC_SC->PCONP & (1UL << 29)) { + if (LPC_GPDMA->DMACConfig & 1) { + error("Only one instance of MODDMA can exist."); + } + } + LPC_SC->PCONP |= (1UL << 29); + LPC_GPDMA->DMACConfig = 1; + moddma_p = this; + for (int i = 0; i < 8; i++) { + setups[i] = (MODDMA_Config *)NULL; + } + } + + // Reset channel configuration register(s) + if (Channels & 0x01) LPC_GPDMACH0->DMACCConfig = 0; + if (Channels & 0x02) LPC_GPDMACH1->DMACCConfig = 0; + if (Channels & 0x04) LPC_GPDMACH2->DMACCConfig = 0; + if (Channels & 0x08) LPC_GPDMACH3->DMACCConfig = 0; + if (Channels & 0x10) LPC_GPDMACH4->DMACCConfig = 0; + if (Channels & 0x20) LPC_GPDMACH5->DMACCConfig = 0; + if (Channels & 0x40) LPC_GPDMACH6->DMACCConfig = 0; + if (Channels & 0x80) LPC_GPDMACH7->DMACCConfig = 0; + + /* Clear DMA interrupt and error flag */ + LPC_GPDMA->DMACIntTCClear = Tc; + LPC_GPDMA->DMACIntErrClr = Err; + + if (isConstructorCalling) { + oldDMAHandler = NVIC_GetVector(DMA_IRQn); + NVIC_SetVector(DMA_IRQn, (uint32_t)MODDMA_IRQHandler); + NVIC_EnableIRQ(DMA_IRQn); + } +} + +}; // namespace AjK ends
--- a/MODDMA.cpp Wed Nov 24 00:32:49 2010 +0000 +++ b/MODDMA.cpp Sat Feb 05 08:53:26 2011 +0000 @@ -1,150 +1,157 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODDMA.h" - -namespace AjK { - -// Create a "hook" for our ISR to make callbacks. Set by init() -class MODDMA *moddma_p = (class MODDMA *)NULL; - -void -MODDMA::Enable(CHANNELS ChannelNumber) -{ - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); - pChannel->DMACCConfig |= _E; -} - -bool -MODDMA::Enabled(CHANNELS ChannelNumber) -{ - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); - return (bool)(pChannel->DMACCConfig & _E); -} - -void -MODDMA::Disable(CHANNELS ChannelNumber) -{ - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); - pChannel->DMACCConfig &= ~(_E); -} - -bool -MODDMA::isActive(CHANNELS ChannelNumber) -{ - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); - return (bool)( pChannel->DMACCConfig & CxConfig_A() ) ; -} - -void -MODDMA::haltChannel(CHANNELS ChannelNumber) -{ - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); - pChannel->DMACCConfig |= CxConfig_H(); -} - -uint32_t oldDMAHandler = 0; -typedef void (*MODDMA_FN)(void); - -extern "C" void MODDMA_IRQHandler(void) { - uint32_t channel_mask; - - if (moddma_p == (class MODDMA *)NULL) { - if (oldDMAHandler) { - ((MODDMA_FN)oldDMAHandler)(); - return; - } - else { - error("Interrupt without instance"); - } - } - - for (int channel_number = 0; channel_number < 8; channel_number++) { - channel_mask = (1UL << channel_number); - if (LPC_GPDMA->DMACIntStat & channel_mask) { - if (LPC_GPDMA->DMACIntTCStat & channel_mask) { - if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) { - moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number); - moddma_p->setIrqType(MODDMA::TcIrq); - moddma_p->setups[channel_number]->isrIntTCStat->call(); - moddma_p->isrIntTCStat.call(); - // The user callback should clear the IRQ. But if they forget - // then the Mbed will lockup. So, check to see if the IRQ has - // been dismissed, if not, we will dismiss it here. - if (LPC_GPDMA->DMACIntTCStat & channel_mask) { - LPC_GPDMA->DMACIntTCClear = channel_mask; - } - // If the user has left the channel enabled, disable it. - // Not, we don't check Active here as it may block inside - // an ISR, we just shut it down immediately. If the user - // must wait for completion they should implement their - // own ISR. But only disable if the LLI linked list register - // is null otherwise we can crap out a series of transfers. - if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) { - if (moddma_p->lli(channel_number) == 0 ) { - moddma_p->Disable( (MODDMA::CHANNELS)channel_number ); - } - } - } - } - - if (LPC_GPDMA->DMACIntErrStat & channel_mask) { - if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) { - moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number); - moddma_p->setIrqType(MODDMA::ErrIrq); - moddma_p->setups[channel_number]->isrIntErrStat->call(); - moddma_p->isrIntErrStat.call(); - // The user callback should clear the IRQ. But if they forget - // then the Mbed will lockup. So, check to see if the IRQ has - // been dismissed, if not, we will dismiss it here. - if (LPC_GPDMA->DMACIntErrStat & channel_mask) { - LPC_GPDMA->DMACIntErrClr = channel_mask; - } - // If the user has left the channel enabled, disable it. - // Not, we don't check Active here as it may block inside - // an ISR, we just shut it down immediately. If the user - // must wait for completion they should implement their - // own ISR. But only disable if the LLI linked list register - // is null otherwise we can crap out a series of transfers. - if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) { - if (moddma_p->lli(channel_number) == 0 ) { - moddma_p->Disable( (MODDMA::CHANNELS)channel_number ); - } - } - } - } - } - } - - /* IRQ should be handled by now, check to make sure. */ - if (LPC_GPDMA->DMACIntStat) { - ((MODDMA_FN)oldDMAHandler)(); - LPC_GPDMA->DMACIntTCClear = (uint32_t)0xFF; /* If not, clear anyway! */ - } - if (LPC_GPDMA->DMACIntErrStat) { - ((MODDMA_FN)oldDMAHandler)(); - LPC_GPDMA->DMACIntErrClr = (uint32_t)0xFF; /* If not, clear anyway! */ - } -} - -}; // namespace AjK ends - +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +#include "iomacros.h" +#include "MODDMA.h" + +namespace AjK { + +// Create a "hook" for our ISR to make callbacks. Set by init() +class MODDMA *moddma_p = (class MODDMA *)NULL; + +void +MODDMA::Enable(CHANNELS ChannelNumber) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + pChannel->DMACCConfig |= _E; +} + +bool +MODDMA::Enabled(CHANNELS ChannelNumber) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + return (bool)(pChannel->DMACCConfig & _E); +} + +void +MODDMA::Disable(CHANNELS ChannelNumber) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + pChannel->DMACCConfig &= ~(_E); +} + +bool +MODDMA::isActive(CHANNELS ChannelNumber) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + return (bool)( pChannel->DMACCConfig & CxConfig_A() ) ; +} + +void +MODDMA::haltChannel(CHANNELS ChannelNumber) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + pChannel->DMACCConfig |= CxConfig_H(); +} + +uint32_t +MODDMA::getControl(CHANNELS ChannelNumber) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber ); + return pChannel->DMACCControl; +} + +uint32_t oldDMAHandler = 0; +typedef void (*MODDMA_FN)(void); + +extern "C" void MODDMA_IRQHandler(void) { + uint32_t channel_mask; + + if (moddma_p == (class MODDMA *)NULL) { + if (oldDMAHandler) { + ((MODDMA_FN)oldDMAHandler)(); + return; + } + else { + error("Interrupt without instance"); + } + } + + for (int channel_number = 0; channel_number < 8; channel_number++) { + channel_mask = (1UL << channel_number); + if (LPC_GPDMA->DMACIntStat & channel_mask) { + if (LPC_GPDMA->DMACIntTCStat & channel_mask) { + if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) { + moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number); + moddma_p->setIrqType(MODDMA::TcIrq); + moddma_p->setups[channel_number]->isrIntTCStat->call(); + moddma_p->isrIntTCStat.call(); + // The user callback should clear the IRQ. But if they forget + // then the Mbed will lockup. So, check to see if the IRQ has + // been dismissed, if not, we will dismiss it here. + if (LPC_GPDMA->DMACIntTCStat & channel_mask) { + LPC_GPDMA->DMACIntTCClear = channel_mask; + } + // If the user has left the channel enabled, disable it. + // Note, we don't check Active here as it may block inside + // an ISR, we just shut it down immediately. If the user + // must wait for completion they should implement their + // own ISR. But only disable if the LLI linked list register + // is null otherwise we can crap out a series of transfers. + if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) { + if (moddma_p->lli( (MODDMA::CHANNELS)channel_number ) == 0 ) { + moddma_p->Disable( (MODDMA::CHANNELS)channel_number ); + } + } + } + } + + if (LPC_GPDMA->DMACIntErrStat & channel_mask) { + if (moddma_p->setups[channel_number] != (MODDMA_Config *)NULL) { + moddma_p->setIrqProcessingChannel((MODDMA::CHANNELS)channel_number); + moddma_p->setIrqType(MODDMA::ErrIrq); + moddma_p->setups[channel_number]->isrIntErrStat->call(); + moddma_p->isrIntErrStat.call(); + // The user callback should clear the IRQ. But if they forget + // then the Mbed will lockup. So, check to see if the IRQ has + // been dismissed, if not, we will dismiss it here. + if (LPC_GPDMA->DMACIntErrStat & channel_mask) { + LPC_GPDMA->DMACIntErrClr = channel_mask; + } + // If the user has left the channel enabled, disable it. + // Not, we don't check Active here as it may block inside + // an ISR, we just shut it down immediately. If the user + // must wait for completion they should implement their + // own ISR. But only disable if the LLI linked list register + // is null otherwise we can crap out a series of transfers. + if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) { + if (moddma_p->lli( (MODDMA::CHANNELS)channel_number ) == 0 ) { + moddma_p->Disable( (MODDMA::CHANNELS)channel_number ); + } + } + } + } + } + } + + /* IRQ should be handled by now, check to make sure. */ + if (LPC_GPDMA->DMACIntStat) { + ((MODDMA_FN)oldDMAHandler)(); + LPC_GPDMA->DMACIntTCClear = (uint32_t)0xFF; /* If not, clear anyway! */ + } + if (LPC_GPDMA->DMACIntErrStat) { + ((MODDMA_FN)oldDMAHandler)(); + LPC_GPDMA->DMACIntErrClr = (uint32_t)0xFF; /* If not, clear anyway! */ + } +} + +}; // namespace AjK ends +
--- a/MODDMA.h Wed Nov 24 00:32:49 2010 +0000 +++ b/MODDMA.h Sat Feb 05 08:53:26 2011 +0000 @@ -1,661 +1,671 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - @file MODDMA.h - @purpose Adds DMA controller and multiple transfer configurations - @version see ChangeLog.c - @date Nov 2010 - @author Andy Kirkham -*/ - -#ifndef MODDMA_H -#define MODDMA_H - -/** @defgroup API The MODDMA API */ -/** @defgroup MISC Misc MODSERIAL functions */ -/** @defgroup INTERNALS MODSERIAL Internals */ - -#include "mbed.h" - -namespace AjK { - -/** - * @brief The MODDMA configuration system - * @author Andy Kirkham - * @see http://mbed.org/cookbook/MODDMA_Config - * @see MODDMA - * @see API - * - * <b>MODDMA_Config</b> defines a configuration that can be passed to the MODDMA controller - * instance to perform a GPDMA data transfer. - */ -class MODDMA_Config { -protected: - - // ***************************************** - // From GPDMA by NXP MCU SW Application Team - // ***************************************** - - uint32_t ChannelNum; //!< DMA channel number, should be in range from 0 to 7. - uint32_t TransferSize; //!< Length/Size of transfer - uint32_t TransferWidth; //!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_m2m only - uint32_t SrcMemAddr; //!< Physical Src Addr, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::m2p - uint32_t DstMemAddr; //!< Physical Destination Address, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::p2m - uint32_t TransferType; //!< Transfer Type - uint32_t SrcConn; //!< Peripheral Source Connection type, used in case TransferType is chosen as - uint32_t DstConn; //!< Peripheral Destination Connection type, used in case TransferType is chosen as - uint32_t DMALLI; //!< Linker List Item structure data address if there's no Linker List, set as '0' - - // Mbed specifics. - -public: - - MODDMA_Config() { - isrIntTCStat = new FunctionPointer; - isrIntErrStat = new FunctionPointer; - ChannelNum = 0xFFFF; - TransferSize = 0; - TransferWidth = 0; - SrcMemAddr = 0; - DstMemAddr = 0; - TransferType = 0; - SrcConn = 0; - DstConn = 0; - DMALLI = 0; - } - - ~MODDMA_Config() { - delete(isrIntTCStat); - delete(isrIntErrStat); - } - - class MODDMA_Config * channelNum(uint32_t n) { ChannelNum = n & 0x7; return this; } - class MODDMA_Config * transferSize(uint32_t n) { TransferSize = n; return this; } - class MODDMA_Config * transferWidth(uint32_t n) { TransferWidth = n; return this; } - class MODDMA_Config * srcMemAddr(uint32_t n) { SrcMemAddr = n; return this; } - class MODDMA_Config * dstMemAddr(uint32_t n) { DstMemAddr = n; return this; } - class MODDMA_Config * transferType(uint32_t n) { TransferType = n; return this; } - class MODDMA_Config * srcConn(uint32_t n) { SrcConn = n; return this; } - class MODDMA_Config * dstConn(uint32_t n) { DstConn = n; return this; } - class MODDMA_Config * dmaLLI(uint32_t n) { DMALLI = n; return this; } - - uint32_t channelNum(void) { return ChannelNum; } - uint32_t transferSize(void) { return TransferSize; } - uint32_t transferWidth(void) { return TransferWidth; } - uint32_t srcMemAddr(void) { return SrcMemAddr; } - uint32_t dstMemAddr(void) { return DstMemAddr; } - uint32_t transferType(void) { return TransferType; } - uint32_t srcConn(void) { return SrcConn; } - uint32_t dstConn(void) { return DstConn; } - uint32_t dmaLLI(void) { return DMALLI; } - - /** - * Attach a callback to the TC IRQ configuration. - * - * @param fptr A function pointer to call - * @return this - */ - class MODDMA_Config * attach_tc(void (*fptr)(void)) { - isrIntTCStat->attach(fptr); - return this; - } - - /** - * Attach a callback to the ERR IRQ configuration. - * - * @param fptr A function pointer to call - * @return this - */ - class MODDMA_Config * attach_err(void (*fptr)(void)) { - isrIntErrStat->attach(fptr); - return this; - } - - /** - * Attach a callback to the TC IRQ configuration. - * - * @param tptr A template pointer to the calling object - * @param mptr A method pointer within the object to call. - * @return this - */ - template<typename T> - class MODDMA_Config * attach_tc(T* tptr, void (T::*mptr)(void)) { - if((mptr != NULL) && (tptr != NULL)) { - isrIntTCStat->attach(tptr, mptr); - } - return this; - } - - /** - * Attach a callback to the ERR IRQ configuration. - * - * @param tptr A template pointer to the calling object - * @param mptr A method pointer within the object to call. - * @return this - */ - template<typename T> - class MODDMA_Config * attach_err(T* tptr, void (T::*mptr)(void)) { - if((mptr != NULL) && (tptr != NULL)) { - isrIntErrStat->attach(tptr, mptr); - } - return this; - } - FunctionPointer *isrIntTCStat; - FunctionPointer *isrIntErrStat; -}; - -/** - * @brief The MODDMA configuration system (linked list items) - * @author Andy Kirkham - * @see http://mbed.org/cookbook/MODDMA_Config - * @see MODDMA - * @see MODDMA_Config - * @see API - */ -class MODDMA_LLI { -public: - class MODDMA_LLI *srcAddr(uint32_t n) { SrcAddr = n; return this; } - class MODDMA_LLI *dstAddr(uint32_t n) { DstAddr = n; return this; } - class MODDMA_LLI *nextLLI(uint32_t n) { NextLLI = n; return this; } - class MODDMA_LLI *control(uint32_t n) { Control = n; return this; } - uint32_t srcAddr(void) { return SrcAddr; } - uint32_t dstAddr(void) { return DstAddr; } - uint32_t nextLLI(void) { return NextLLI; } - uint32_t control(void) { return Control; } -protected: - uint32_t SrcAddr; //!< Source Address - uint32_t DstAddr; //!< Destination address - uint32_t NextLLI; //!< Next LLI address, otherwise set to '0' - uint32_t Control; //!< GPDMA Control of this LLI -}; - - - - /** - * @brief MODDMA GPDMA Controller - * @author Andy Kirkham - * @see http://mbed.org/cookbook/MODDMA - * @see example1.cpp - * @see API - * - * <b>MODDMA</b> defines a GPDMA controller and multiple DMA configurations that allow for DMA - * transfers from memory to memory, memory to peripheral or peripheral to memory. - * - * At the heart of the library is the MODDMA class that defines a single instance controller that - * manages all the GPDMA hardware registers and interrupts. The controller can accept multiple - * configurations that define the channel transfers. Each configuration specifies the source and - * destination information and other associated parts to maintain the transfer process. - * - * Standard example: - * @code - * #include "mbed.h" - * #include "MODDMA.h" - * - * DigitalOut led1(LED1); - * Serial pc(USBTX, USBRX); // tx, rx - * MODDMA dma; - * - * int main() { - * - * // Create a string buffer to send directly to a Uart/Serial - * char s[] = "***DMA*** ABCDEFGHIJKLMNOPQRSTUVWXYZ ***DMA***"; - * - * // Create a transfer configuarion - * MODDMA_Config *config = new MODDMA_Config; - * - * // Provide a "minimal" setup for demo purposes. - * config - * ->channelNum ( MODDMA::Channel_0 ) // The DMA channel to use. - * ->srcMemAddr ( (uint32_t) &s ) // A pointer to the buffer to send. - * ->transferSize ( sizeof(s) ) // The size of that buffer. - * ->transferType ( MODDMA::m2p ) // Source is memory, destination is peripheral - * ->dstConn ( MODDMA::UART0_Tx ) // Specifically, peripheral is Uart0 TX (USBTX, USBRX) - * ; // config end. - * - * // Pass the configuration to the MODDMA controller. - * dma.Setup( config ); - * - * // Enable the channel and begin transfer. - * dma.Enable( config->channelNum() ); - * - * while(1) { - * led1 = !led1; - * wait(0.25); - * } - * } - * @endcode - */ -class MODDMA -{ -public: - - //! Channel definitions. - enum CHANNELS { - Channel_0 = 0 /*!< Channel 0 */ - , Channel_1 /*!< Channel 1 */ - , Channel_2 /*!< Channel 2 */ - , Channel_3 /*!< Channel 3 */ - , Channel_4 /*!< Channel 4 */ - , Channel_5 /*!< Channel 5 */ - , Channel_6 /*!< Channel 6 */ - , Channel_7 /*!< Channel 7 */ - }; - - //! Interrupt callback types. - enum IrqType_t { - TcIrq = 0 /*!< Terminal Count interrupt */ - , ErrIrq /*!< Error interrupt */ - }; - - //! Return status codes. - enum Status { - Ok = 0 /*!< Ok, suceeded */ - , Error = -1 /*!< General error */ - , ErrChInUse = -2 /*!< Specific error, channel in use */ - }; - - //! DMA Connection number definitions - enum GPDMA_CONNECTION { - SSP0_Tx = 0UL /*!< SSP0 Tx */ - , SSP0_Rx = 1UL /*!< SSP0 Rx */ - , SSP1_Tx = 2UL /*!< SSP1 Tx */ - , SSP1_Rx = 3UL /*!< SSP1 Rx */ - , ADC = 4UL /*!< ADC */ - , I2S_Channel_0 = 5UL /*!< I2S channel 0 */ - , I2S_Channel_1 = 6UL /*!< I2S channel 1 */ - , DAC = 7UL /*!< DAC */ - , UART0_Tx = 8UL /*!< UART0 Tx */ - , UART0_Rx = 9UL /*!< UART0 Rx */ - , UART1_Tx = 10UL /*!< UART1 Tx */ - , UART1_Rx = 11UL /*!< UART1 Rx */ - , UART2_Tx = 12UL /*!< UART2 Tx */ - , UART2_Rx = 13UL /*!< UART2 Rx */ - , UART3_Tx = 14UL /*!< UART3 Tx */ - , UART3_Rx = 15UL /*!< UART3 Rx */ - , MAT0_0 = 16UL /*!< MAT0.0 */ - , MAT0_1 = 17UL /*!< MAT0.1 */ - , MAT1_0 = 18UL /*!< MAT1.0 */ - , MAT1_1 = 19UL /*!< MAT1.1 */ - , MAT2_0 = 20UL /**< MAT2.0 */ - , MAT2_1 = 21UL /*!< MAT2.1 */ - , MAT3_0 = 22UL /*!< MAT3.0 */ - , MAT3_1 = 23UL /*!< MAT3.1 */ - }; - - //! GPDMA Transfer type definitions - enum GPDMA_TRANSFERTYPE { - m2m = 0UL /*!< Memory to memory - DMA control */ - , m2p = 1UL /*!< Memory to peripheral - DMA control */ - , p2m = 2UL /*!< Peripheral to memory - DMA control */ - , p2p = 3UL /*!< Src peripheral to dest peripheral - DMA control */ - }; - - //! Burst size in Source and Destination definitions */ - enum GPDMA_BSIZE { - _1 = 0UL /*!< Burst size = 1 */ - , _4 = 1UL /*!< Burst size = 4 */ - , _8 = 2UL /*!< Burst size = 8 */ - , _16 = 3UL /*!< Burst size = 16 */ - , _32 = 4UL /*!< Burst size = 32 */ - , _64 = 5UL /*!< Burst size = 64 */ - , _128 = 6UL /*!< Burst size = 128 */ - , _256 = 7UL /*!< Burst size = 256 */ - }; - - //! Width in Src transfer width and Dest transfer width definitions */ - enum GPDMA_WIDTH { - byte = 0UL /*!< Width = 1 byte */ - , halfword = 1UL /*!< Width = 2 bytes */ - , word = 2UL /*!< Width = 4 bytes */ - }; - - //! DMA Request Select Mode definitions. */ - enum GPDMA_REQSEL { - uart = 0UL /*!< UART TX/RX is selected */ - , timer = 1UL /*!< Timer match is selected */ - }; - - //! GPDMA Control register bits. - enum Config { - _E = 1 /*!< DMA Controller enable */ - , _M = 2 /*!< AHB Master endianness configuration */ - }; - - //! GPDMA Channel config register bits. - enum CConfig { - _CE = (1UL << 0) /*!< Channel enable */ - , _IE = (1UL << 14) /*!< Interrupt error mask */ - , _ITC = (1UL << 15) /*!< Terminal count interrupt mask */ - , _L = (1UL << 16) /*!< Lock */ - , _A = (1UL << 17) /*!< Active */ - , _H = (1UL << 18) /*!< Halt */ - }; - - /** - * The MODDMA constructor is used to initialise the DMA controller object. - */ - MODDMA() { init(true); } - - /** - * The MODDMA destructor. - */ - ~MODDMA() {} - - /** - * Used to setup the DMA controller to prepare for a data transfer. - * - * @ingroup API - * @param isConstructorCalling Set true when called from teh constructor - * @param - */ - void init(bool isConstructorCalling, int Channels = 0xFF, int Tc = 0xFF, int Err = 0xFF); - - /** - * Used to setup the DMA controller to prepare for a data transfer. - * - * @ingroup API - * @param c A pointer to an instance of MODDMA_Config to setup. - */ - Status Setup(MODDMA_Config *c); - - /** - * Enable and begin data transfer. - * - * @ingroup API - * @param ChannelNumber Type CHANNELS, the channel number to enable - */ - void Enable(CHANNELS ChannelNumber); - - /** - * Enable and begin data transfer (overloaded function) - * - * @ingroup API - * @param ChannelNumber Type uin32_t, the channel number to enable - */ - void Enable(uint32_t ChannelNumber) { Enable((CHANNELS)(ChannelNumber & 0x7)); } - - /** - * Enable and begin data transfer (overloaded function) - * - * @ingroup API - * @param config A pointer to teh configuration - */ - void Enable(MODDMA_Config *config) { Enable( config->channelNum() ); } - - - /** - * Disable a channel and end data transfer. - * - * @ingroup API - * @param ChannelNumber Type CHANNELS, the channel number to enable - */ - void Disable(CHANNELS ChannelNumber); - - /** - * Disable a channel and end data transfer (overloaded function) - * - * @ingroup API - * @param ChannelNumber Type uin32_t, the channel number to disable - */ - void Disable(uint32_t ChannelNumber) { Disable((CHANNELS)(ChannelNumber & 0x7)); } - - /** - * Is the specified channel enabled? - * - * @ingroup API - * @param ChannelNumber Type CHANNELS, the channel number to test - * @return bool true if enabled, false otherwise. - */ - bool Enabled(CHANNELS ChannelNumber); - - /** - * Is the specified channel enabled? (overloaded function) - * - * @ingroup API - * @param ChannelNumber Type uin32_t, the channel number to test - * @return bool true if enabled, false otherwise. - */ - bool Enabled(uint32_t ChannelNumber) { return Enabled((CHANNELS)(ChannelNumber & 0x7)); } - - __INLINE uint32_t IntStat(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t IntTCStat_Ch(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t IntTCClear_Ch(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t IntErrStat_Ch(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t IntErrClr_Ch(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t RawIntErrStat_Ch(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t EnbldChns_Ch(uint32_t n) { return (1UL << n) & 0xFF; } - __INLINE uint32_t SoftBReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } - __INLINE uint32_t SoftSReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } - __INLINE uint32_t SoftLBReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } - __INLINE uint32_t SoftLSReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } - __INLINE uint32_t Sync_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } - __INLINE uint32_t ReqSel_Input(uint32_t n) { return (1UL << (n - 8)) & 0xFF; } - - - __INLINE uint32_t CxControl_TransferSize(uint32_t n) { return (n & 0xFFF) << 0; } - __INLINE uint32_t CxControl_SBSize(uint32_t n) { return (n & 0x7) << 12; } - __INLINE uint32_t CxControl_DBSize(uint32_t n) { return (n & 0x7) << 15; } - __INLINE uint32_t CxControl_SWidth(uint32_t n) { return (n & 0x7) << 18; } - __INLINE uint32_t CxControl_DWidth(uint32_t n) { return (n & 0x7) << 21; } - __INLINE uint32_t CxControl_SI() { return (1UL << 26); } - __INLINE uint32_t CxControl_DI() { return (1UL << 27); } - __INLINE uint32_t CxControl_Prot1() { return (1UL << 28); } - __INLINE uint32_t CxControl_Prot2() { return (1UL << 29); } - __INLINE uint32_t CxControl_Prot3() { return (1UL << 30); } - __INLINE uint32_t CxControl_I() { return (1UL << 31); } - __INLINE uint32_t CxControl_E() { return (1UL << 0); } - __INLINE uint32_t CxConfig_SrcPeripheral(uint32_t n) { return (n & 0x1F) << 1; } - __INLINE uint32_t CxConfig_DestPeripheral(uint32_t n) { return (n & 0x1F) << 6; } - __INLINE uint32_t CxConfig_TransferType(uint32_t n) { return (n & 0x7) << 11; } - __INLINE uint32_t CxConfig_IE() { return (1UL << 14); } - __INLINE uint32_t CxConfig_ITC() { return (1UL << 15); } - __INLINE uint32_t CxConfig_L() { return (1UL << 16); } - __INLINE uint32_t CxConfig_A() { return (1UL << 17); } - __INLINE uint32_t CxConfig_H() { return (1UL << 18); } - - /** - * A store for up to 8 (8 channels) of configurations. - * @see MODDMA_Config - */ - MODDMA_Config *setups[8]; - - /** - * Get a pointer to the current configuration the ISR is servicing. - * - * @ingroup API - * @return MODDMA_Config * A pointer to the setup the ISR is currently servicing. - */ - MODDMA_Config *getConfig(void) { return setups[IrqProcessingChannel]; } - - /** - * Set which channel the ISR is currently servicing. - * - * *** USED INTERNALLY. DO NOT CALL FROM USER PROGRAMS *** - * - * Must be public so the extern "C" ISR can use it. - */ - void setIrqProcessingChannel(CHANNELS n) { IrqProcessingChannel = n; } - - /** - * Gets which channel the ISR is currently servicing. - * - * @ingroup API - * @return CHANNELS The current channel the ISR is servicing. - */ - CHANNELS irqProcessingChannel(void) { return IrqProcessingChannel; } - - /** - * Sets which type of IRQ the ISR is making a callback for. - * - * *** USED INTERNALLY. DO NOT CALL FROM USER PROGRAMS *** - * - * Must be public so the extern "C" ISR can use it. - */ - void setIrqType(IrqType_t n) { IrqType = n; } - - /** - * Get which type of IRQ the ISR is calling you about, - * terminal count or error. - */ - IrqType_t irqType(void) { return IrqType; } - - /** - * Clear the interrupt after handling. - * - * @param CHANNELS The channel the IQR occured on. - */ - void clearTcIrq(CHANNELS n) { LPC_GPDMA->DMACIntTCClear = (uint32_t)(1UL << n); } - - /** - * Clear the interrupt the ISR is currently handing.. - */ - void clearTcIrq(void) { clearTcIrq( IrqProcessingChannel ); } - - /** - * Clear the error interrupt after handling. - * - * @ingroup API - * @param CHANNELS The channel the IQR occured on. - */ - void clearErrIrq(CHANNELS n) { LPC_GPDMA->DMACIntTCClear = (uint32_t)(1UL << n); } - - /** - * Clear the error interrupt the ISR is currently handing. - * @ingroup API - */ - void clearErrIrq(void) { clearErrIrq( IrqProcessingChannel ); } - - /** - * Is the supplied channel currently active? - * - * @ingroup API - * @param CHANNELS The channel to inquire about. - * @return bool true if active, false otherwise. - */ - bool isActive(CHANNELS ChannelNumber); - - /** - * Halt the supplied channel. - * - * @ingroup API - * @param CHANNELS The channel to halt. - */ - void haltChannel(CHANNELS ChannelNumber); - - /** - * Wait for channel transfer to complete and then halt. - * - * @ingroup API - * @param CHANNELS The channel to wait for then halt. - */ - void haltAndWaitChannelComplete(CHANNELS n) { haltChannel(n); while (isActive(n)); } - - /** - * Attach a callback to the TC IRQ controller. - * - * @ingroup API - * @param fptr A function pointer to call - * @return this - */ - void attach_tc(void (*fptr)(void)) { - isrIntTCStat.attach(fptr); - } - - /** - * Attach a callback to the TC IRQ controller. - * - * @ingroup API - * @param tptr A template pointer to the calling object - * @param mptr A method pointer within the object to call. - * @return this - */ - template<typename T> - void attach_tc(T* tptr, void (T::*mptr)(void)) { - if((mptr != NULL) && (tptr != NULL)) { - isrIntTCStat.attach(tptr, mptr); - } - } - - /** - * The MODDMA controllers terminal count interrupt callback. - */ - FunctionPointer isrIntTCStat; - - /** - * Attach a callback to the ERR IRQ controller. - * - * @ingroup API - * @param fptr A function pointer to call - * @return this - */ - void attach_err(void (*fptr)(void)) { - isrIntErrStat.attach(fptr); - } - - /** - * Attach a callback to the ERR IRQ controller. - * - * @ingroup API - * @param tptr A template pointer to the calling object - * @param mptr A method pointer within the object to call. - * @return this - */ - template<typename T> - void attach_err(T* tptr, void (T::*mptr)(void)) { - if((mptr != NULL) && (tptr != NULL)) { - isrIntErrStat.attach(tptr, mptr); - } - } - - /** - * Get the Linked List index regsiter for the requested channel. - * - * @param channelNum The channel number. - * @return uint32_t The valie of the DMACCLLI register - */ - uint32_t lli(int channelNum) { - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( channelNum & 0x7 ); - return pChannel->DMACCLLI; - } - - /** - * The MODDMA controllers error interrupt callback. - */ - FunctionPointer isrIntErrStat; - -protected: - - // Data LUTs. - uint32_t LUTPerAddr(int n); - uint8_t LUTPerBurst(int n); - uint8_t LUTPerWid(int n); - uint32_t Channel_p(int channel); - - CHANNELS IrqProcessingChannel; - - IrqType_t IrqType; -}; - -}; // namespace AjK ends. - -using namespace AjK; - -#endif +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + @file MODDMA.h + @purpose Adds DMA controller and multiple transfer configurations + @version see ChangeLog.c + @date Nov 2010 + @author Andy Kirkham +*/ + +#ifndef MODDMA_H +#define MODDMA_H + +/** @defgroup API The MODDMA API */ +/** @defgroup MISC Misc MODSERIAL functions */ +/** @defgroup INTERNALS MODSERIAL Internals */ + +#include "mbed.h" +#include "iomacros.h" + +namespace AjK { + +/** + * @brief The MODDMA configuration system + * @author Andy Kirkham + * @see http://mbed.org/cookbook/MODDMA_Config + * @see MODDMA + * @see API + * + * <b>MODDMA_Config</b> defines a configuration that can be passed to the MODDMA controller + * instance to perform a GPDMA data transfer. + */ +class MODDMA_Config { +protected: + + // ***************************************** + // From GPDMA by NXP MCU SW Application Team + // ***************************************** + + uint32_t ChannelNum; //!< DMA channel number, should be in range from 0 to 7. + uint32_t TransferSize; //!< Length/Size of transfer + uint32_t TransferWidth; //!< Transfer width - used for TransferType is GPDMA_TRANSFERTYPE_m2m only + uint32_t SrcMemAddr; //!< Physical Src Addr, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::m2p + uint32_t DstMemAddr; //!< Physical Destination Address, used in case TransferType is chosen as MODDMA::GPDMA_TRANSFERTYPE::m2m or MODDMA::GPDMA_TRANSFERTYPE::p2m + uint32_t TransferType; //!< Transfer Type + uint32_t SrcConn; //!< Peripheral Source Connection type, used in case TransferType is chosen as + uint32_t DstConn; //!< Peripheral Destination Connection type, used in case TransferType is chosen as + uint32_t DMALLI; //!< Linker List Item structure data address if there's no Linker List, set as '0' + + // Mbed specifics. + +public: + + MODDMA_Config() { + isrIntTCStat = new FunctionPointer; + isrIntErrStat = new FunctionPointer; + ChannelNum = 0xFFFF; + TransferSize = 0; + TransferWidth = 0; + SrcMemAddr = 0; + DstMemAddr = 0; + TransferType = 0; + SrcConn = 0; + DstConn = 0; + DMALLI = 0; + } + + ~MODDMA_Config() { + delete(isrIntTCStat); + delete(isrIntErrStat); + } + + class MODDMA_Config * channelNum(uint32_t n) { ChannelNum = n & 0x7; return this; } + class MODDMA_Config * transferSize(uint32_t n) { TransferSize = n; return this; } + class MODDMA_Config * transferWidth(uint32_t n) { TransferWidth = n; return this; } + class MODDMA_Config * srcMemAddr(uint32_t n) { SrcMemAddr = n; return this; } + class MODDMA_Config * dstMemAddr(uint32_t n) { DstMemAddr = n; return this; } + class MODDMA_Config * transferType(uint32_t n) { TransferType = n; return this; } + class MODDMA_Config * srcConn(uint32_t n) { SrcConn = n; return this; } + class MODDMA_Config * dstConn(uint32_t n) { DstConn = n; return this; } + class MODDMA_Config * dmaLLI(uint32_t n) { DMALLI = n; return this; } + + uint32_t channelNum(void) { return ChannelNum; } + uint32_t transferSize(void) { return TransferSize; } + uint32_t transferWidth(void) { return TransferWidth; } + uint32_t srcMemAddr(void) { return SrcMemAddr; } + uint32_t dstMemAddr(void) { return DstMemAddr; } + uint32_t transferType(void) { return TransferType; } + uint32_t srcConn(void) { return SrcConn; } + uint32_t dstConn(void) { return DstConn; } + uint32_t dmaLLI(void) { return DMALLI; } + + /** + * Attach a callback to the TC IRQ configuration. + * + * @param fptr A function pointer to call + * @return this + */ + class MODDMA_Config * attach_tc(void (*fptr)(void)) { + isrIntTCStat->attach(fptr); + return this; + } + + /** + * Attach a callback to the ERR IRQ configuration. + * + * @param fptr A function pointer to call + * @return this + */ + class MODDMA_Config * attach_err(void (*fptr)(void)) { + isrIntErrStat->attach(fptr); + return this; + } + + /** + * Attach a callback to the TC IRQ configuration. + * + * @param tptr A template pointer to the calling object + * @param mptr A method pointer within the object to call. + * @return this + */ + template<typename T> + class MODDMA_Config * attach_tc(T* tptr, void (T::*mptr)(void)) { + if((mptr != NULL) && (tptr != NULL)) { + isrIntTCStat->attach(tptr, mptr); + } + return this; + } + + /** + * Attach a callback to the ERR IRQ configuration. + * + * @param tptr A template pointer to the calling object + * @param mptr A method pointer within the object to call. + * @return this + */ + template<typename T> + class MODDMA_Config * attach_err(T* tptr, void (T::*mptr)(void)) { + if((mptr != NULL) && (tptr != NULL)) { + isrIntErrStat->attach(tptr, mptr); + } + return this; + } + FunctionPointer *isrIntTCStat; + FunctionPointer *isrIntErrStat; +}; + +/** + * @brief The MODDMA configuration system (linked list items) + * @author Andy Kirkham + * @see http://mbed.org/cookbook/MODDMA_Config + * @see MODDMA + * @see MODDMA_Config + * @see API + */ +class MODDMA_LLI { +public: + class MODDMA_LLI *srcAddr(uint32_t n) { SrcAddr = n; return this; } + class MODDMA_LLI *dstAddr(uint32_t n) { DstAddr = n; return this; } + class MODDMA_LLI *nextLLI(uint32_t n) { NextLLI = n; return this; } + class MODDMA_LLI *control(uint32_t n) { Control = n; return this; } + uint32_t srcAddr(void) { return SrcAddr; } + uint32_t dstAddr(void) { return DstAddr; } + uint32_t nextLLI(void) { return NextLLI; } + uint32_t control(void) { return Control; } + + uint32_t SrcAddr; //!< Source Address + uint32_t DstAddr; //!< Destination address + uint32_t NextLLI; //!< Next LLI address, otherwise set to '0' + uint32_t Control; //!< GPDMA Control of this LLI +}; + + + + /** + * @brief MODDMA GPDMA Controller + * @author Andy Kirkham + * @see http://mbed.org/cookbook/MODDMA + * @see example1.cpp + * @see API + * + * <b>MODDMA</b> defines a GPDMA controller and multiple DMA configurations that allow for DMA + * transfers from memory to memory, memory to peripheral or peripheral to memory. + * + * At the heart of the library is the MODDMA class that defines a single instance controller that + * manages all the GPDMA hardware registers and interrupts. The controller can accept multiple + * configurations that define the channel transfers. Each configuration specifies the source and + * destination information and other associated parts to maintain the transfer process. + * + * Standard example: + * @code + * #include "mbed.h" + * #include "MODDMA.h" + * + * DigitalOut led1(LED1); + * Serial pc(USBTX, USBRX); // tx, rx + * MODDMA dma; + * + * int main() { + * + * // Create a string buffer to send directly to a Uart/Serial + * char s[] = "***DMA*** ABCDEFGHIJKLMNOPQRSTUVWXYZ ***DMA***"; + * + * // Create a transfer configuarion + * MODDMA_Config *config = new MODDMA_Config; + * + * // Provide a "minimal" setup for demo purposes. + * config + * ->channelNum ( MODDMA::Channel_0 ) // The DMA channel to use. + * ->srcMemAddr ( (uint32_t) &s ) // A pointer to the buffer to send. + * ->transferSize ( sizeof(s) ) // The size of that buffer. + * ->transferType ( MODDMA::m2p ) // Source is memory, destination is peripheral + * ->dstConn ( MODDMA::UART0_Tx ) // Specifically, peripheral is Uart0 TX (USBTX, USBRX) + * ; // config end. + * + * // Pass the configuration to the MODDMA controller. + * dma.Setup( config ); + * + * // Enable the channel and begin transfer. + * dma.Enable( config->channelNum() ); + * + * while(1) { + * led1 = !led1; + * wait(0.25); + * } + * } + * @endcode + */ +class MODDMA +{ +public: + + //! Channel definitions. + enum CHANNELS { + Channel_0 = 0 /*!< Channel 0 */ + , Channel_1 /*!< Channel 1 */ + , Channel_2 /*!< Channel 2 */ + , Channel_3 /*!< Channel 3 */ + , Channel_4 /*!< Channel 4 */ + , Channel_5 /*!< Channel 5 */ + , Channel_6 /*!< Channel 6 */ + , Channel_7 /*!< Channel 7 */ + }; + + //! Interrupt callback types. + enum IrqType_t { + TcIrq = 0 /*!< Terminal Count interrupt */ + , ErrIrq /*!< Error interrupt */ + }; + + //! Return status codes. + enum Status { + Ok = 0 /*!< Ok, suceeded */ + , Error = -1 /*!< General error */ + , ErrChInUse = -2 /*!< Specific error, channel in use */ + }; + + //! DMA Connection number definitions + enum GPDMA_CONNECTION { + SSP0_Tx = 0UL /*!< SSP0 Tx */ + , SSP0_Rx = 1UL /*!< SSP0 Rx */ + , SSP1_Tx = 2UL /*!< SSP1 Tx */ + , SSP1_Rx = 3UL /*!< SSP1 Rx */ + , ADC = 4UL /*!< ADC */ + , I2S_Channel_0 = 5UL /*!< I2S channel 0 */ + , I2S_Channel_1 = 6UL /*!< I2S channel 1 */ + , DAC = 7UL /*!< DAC */ + , UART0_Tx = 8UL /*!< UART0 Tx */ + , UART0_Rx = 9UL /*!< UART0 Rx */ + , UART1_Tx = 10UL /*!< UART1 Tx */ + , UART1_Rx = 11UL /*!< UART1 Rx */ + , UART2_Tx = 12UL /*!< UART2 Tx */ + , UART2_Rx = 13UL /*!< UART2 Rx */ + , UART3_Tx = 14UL /*!< UART3 Tx */ + , UART3_Rx = 15UL /*!< UART3 Rx */ + , MAT0_0 = 16UL /*!< MAT0.0 */ + , MAT0_1 = 17UL /*!< MAT0.1 */ + , MAT1_0 = 18UL /*!< MAT1.0 */ + , MAT1_1 = 19UL /*!< MAT1.1 */ + , MAT2_0 = 20UL /**< MAT2.0 */ + , MAT2_1 = 21UL /*!< MAT2.1 */ + , MAT3_0 = 22UL /*!< MAT3.0 */ + , MAT3_1 = 23UL /*!< MAT3.1 */ + }; + + //! GPDMA Transfer type definitions + enum GPDMA_TRANSFERTYPE { + m2m = 0UL /*!< Memory to memory - DMA control */ + , m2p = 1UL /*!< Memory to peripheral - DMA control */ + , p2m = 2UL /*!< Peripheral to memory - DMA control */ + , p2p = 3UL /*!< Src peripheral to dest peripheral - DMA control */ + }; + + //! Burst size in Source and Destination definitions */ + enum GPDMA_BSIZE { + _1 = 0UL /*!< Burst size = 1 */ + , _4 = 1UL /*!< Burst size = 4 */ + , _8 = 2UL /*!< Burst size = 8 */ + , _16 = 3UL /*!< Burst size = 16 */ + , _32 = 4UL /*!< Burst size = 32 */ + , _64 = 5UL /*!< Burst size = 64 */ + , _128 = 6UL /*!< Burst size = 128 */ + , _256 = 7UL /*!< Burst size = 256 */ + }; + + //! Width in Src transfer width and Dest transfer width definitions */ + enum GPDMA_WIDTH { + byte = 0UL /*!< Width = 1 byte */ + , halfword = 1UL /*!< Width = 2 bytes */ + , word = 2UL /*!< Width = 4 bytes */ + }; + + //! DMA Request Select Mode definitions. */ + enum GPDMA_REQSEL { + uart = 0UL /*!< UART TX/RX is selected */ + , timer = 1UL /*!< Timer match is selected */ + }; + + //! GPDMA Control register bits. + enum Config { + _E = 1 /*!< DMA Controller enable */ + , _M = 2 /*!< AHB Master endianness configuration */ + }; + + //! GPDMA Channel config register bits. + enum CConfig { + _CE = (1UL << 0) /*!< Channel enable */ + , _IE = (1UL << 14) /*!< Interrupt error mask */ + , _ITC = (1UL << 15) /*!< Terminal count interrupt mask */ + , _L = (1UL << 16) /*!< Lock */ + , _A = (1UL << 17) /*!< Active */ + , _H = (1UL << 18) /*!< Halt */ + }; + + /** + * The MODDMA constructor is used to initialise the DMA controller object. + */ + MODDMA() { init(true); } + + /** + * The MODDMA destructor. + */ + ~MODDMA() {} + + /** + * Used to setup the DMA controller to prepare for a data transfer. + * + * @ingroup API + * @param isConstructorCalling Set true when called from teh constructor + * @param + */ + void init(bool isConstructorCalling, int Channels = 0xFF, int Tc = 0xFF, int Err = 0xFF); + + /** + * Used to setup the DMA controller to prepare for a data transfer. + * + * @ingroup API + * @param c A pointer to an instance of MODDMA_Config to setup. + */ + uint32_t Setup(MODDMA_Config *c); + + /** + * Enable and begin data transfer. + * + * @ingroup API + * @param ChannelNumber Type CHANNELS, the channel number to enable + */ + void Enable(CHANNELS ChannelNumber); + + /** + * Enable and begin data transfer (overloaded function) + * + * @ingroup API + * @param ChannelNumber Type uin32_t, the channel number to enable + */ + void Enable(uint32_t ChannelNumber) { Enable((CHANNELS)(ChannelNumber & 0x7)); } + + /** + * Enable and begin data transfer (overloaded function) + * + * @ingroup API + * @param config A pointer to teh configuration + */ + void Enable(MODDMA_Config *config) { Enable( config->channelNum() ); } + + + /** + * Disable a channel and end data transfer. + * + * @ingroup API + * @param ChannelNumber Type CHANNELS, the channel number to enable + */ + void Disable(CHANNELS ChannelNumber); + + /** + * Disable a channel and end data transfer (overloaded function) + * + * @ingroup API + * @param ChannelNumber Type uin32_t, the channel number to disable + */ + void Disable(uint32_t ChannelNumber) { Disable((CHANNELS)(ChannelNumber & 0x7)); } + + /** + * Is the specified channel enabled? + * + * @ingroup API + * @param ChannelNumber Type CHANNELS, the channel number to test + * @return bool true if enabled, false otherwise. + */ + bool Enabled(CHANNELS ChannelNumber); + + /** + * Is the specified channel enabled? (overloaded function) + * + * @ingroup API + * @param ChannelNumber Type uin32_t, the channel number to test + * @return bool true if enabled, false otherwise. + */ + bool Enabled(uint32_t ChannelNumber) { return Enabled((CHANNELS)(ChannelNumber & 0x7)); } + + __INLINE uint32_t IntStat(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t IntTCStat_Ch(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t IntTCClear_Ch(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t IntErrStat_Ch(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t IntErrClr_Ch(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t RawIntErrStat_Ch(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t EnbldChns_Ch(uint32_t n) { return (1UL << n) & 0xFF; } + __INLINE uint32_t SoftBReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } + __INLINE uint32_t SoftSReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } + __INLINE uint32_t SoftLBReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } + __INLINE uint32_t SoftLSReq_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } + __INLINE uint32_t Sync_Src(uint32_t n) { return (1UL << n) & 0xFFFF; } + __INLINE uint32_t ReqSel_Input(uint32_t n) { return (1UL << (n - 8)) & 0xFF; } + + + __INLINE uint32_t CxControl_TransferSize(uint32_t n) { return (n & 0xFFF) << 0; } + __INLINE uint32_t CxControl_SBSize(uint32_t n) { return (n & 0x7) << 12; } + __INLINE uint32_t CxControl_DBSize(uint32_t n) { return (n & 0x7) << 15; } + __INLINE uint32_t CxControl_SWidth(uint32_t n) { return (n & 0x7) << 18; } + __INLINE uint32_t CxControl_DWidth(uint32_t n) { return (n & 0x7) << 21; } + __INLINE uint32_t CxControl_SI() { return (1UL << 26); } + __INLINE uint32_t CxControl_DI() { return (1UL << 27); } + __INLINE uint32_t CxControl_Prot1() { return (1UL << 28); } + __INLINE uint32_t CxControl_Prot2() { return (1UL << 29); } + __INLINE uint32_t CxControl_Prot3() { return (1UL << 30); } + __INLINE uint32_t CxControl_I() { return (1UL << 31); } + __INLINE uint32_t CxControl_E() { return (1UL << 0); } + __INLINE uint32_t CxConfig_SrcPeripheral(uint32_t n) { return (n & 0x1F) << 1; } + __INLINE uint32_t CxConfig_DestPeripheral(uint32_t n) { return (n & 0x1F) << 6; } + __INLINE uint32_t CxConfig_TransferType(uint32_t n) { return (n & 0x7) << 11; } + __INLINE uint32_t CxConfig_IE() { return (1UL << 14); } + __INLINE uint32_t CxConfig_ITC() { return (1UL << 15); } + __INLINE uint32_t CxConfig_L() { return (1UL << 16); } + __INLINE uint32_t CxConfig_A() { return (1UL << 17); } + __INLINE uint32_t CxConfig_H() { return (1UL << 18); } + + /** + * A store for up to 8 (8 channels) of configurations. + * @see MODDMA_Config + */ + MODDMA_Config *setups[8]; + + /** + * Get a pointer to the current configuration the ISR is servicing. + * + * @ingroup API + * @return MODDMA_Config * A pointer to the setup the ISR is currently servicing. + */ + MODDMA_Config *getConfig(void) { return setups[IrqProcessingChannel]; } + + /** + * Set which channel the ISR is currently servicing. + * + * *** USED INTERNALLY. DO NOT CALL FROM USER PROGRAMS *** + * + * Must be public so the extern "C" ISR can use it. + */ + void setIrqProcessingChannel(CHANNELS n) { IrqProcessingChannel = n; } + + /** + * Gets which channel the ISR is currently servicing. + * + * @ingroup API + * @return CHANNELS The current channel the ISR is servicing. + */ + CHANNELS irqProcessingChannel(void) { return IrqProcessingChannel; } + + /** + * Sets which type of IRQ the ISR is making a callback for. + * + * *** USED INTERNALLY. DO NOT CALL FROM USER PROGRAMS *** + * + * Must be public so the extern "C" ISR can use it. + */ + void setIrqType(IrqType_t n) { IrqType = n; } + + /** + * Get which type of IRQ the ISR is calling you about, + * terminal count or error. + */ + IrqType_t irqType(void) { return IrqType; } + + /** + * Clear the interrupt after handling. + * + * @param CHANNELS The channel the IQR occured on. + */ + void clearTcIrq(CHANNELS n) { LPC_GPDMA->DMACIntTCClear = (uint32_t)(1UL << n); } + + /** + * Clear the interrupt the ISR is currently handing.. + */ + void clearTcIrq(void) { clearTcIrq( IrqProcessingChannel ); } + + /** + * Clear the error interrupt after handling. + * + * @ingroup API + * @param CHANNELS The channel the IQR occured on. + */ + void clearErrIrq(CHANNELS n) { LPC_GPDMA->DMACIntTCClear = (uint32_t)(1UL << n); } + + /** + * Clear the error interrupt the ISR is currently handing. + * @ingroup API + */ + void clearErrIrq(void) { clearErrIrq( IrqProcessingChannel ); } + + /** + * Is the supplied channel currently active? + * + * @ingroup API + * @param CHANNELS The channel to inquire about. + * @return bool true if active, false otherwise. + */ + bool isActive(CHANNELS ChannelNumber); + + /** + * Halt the supplied channel. + * + * @ingroup API + * @param CHANNELS The channel to halt. + */ + void haltChannel(CHANNELS ChannelNumber); + + /** + * get a channels control register. + * + * @ingroup API + * @param CHANNELS The channel to get the control register for. + */ + uint32_t getControl(CHANNELS ChannelNumber); + + /** + * Wait for channel transfer to complete and then halt. + * + * @ingroup API + * @param CHANNELS The channel to wait for then halt. + */ + void haltAndWaitChannelComplete(CHANNELS n) { haltChannel(n); while (isActive(n)); } + + /** + * Attach a callback to the TC IRQ controller. + * + * @ingroup API + * @param fptr A function pointer to call + * @return this + */ + void attach_tc(void (*fptr)(void)) { + isrIntTCStat.attach(fptr); + } + + /** + * Attach a callback to the TC IRQ controller. + * + * @ingroup API + * @param tptr A template pointer to the calling object + * @param mptr A method pointer within the object to call. + * @return this + */ + template<typename T> + void attach_tc(T* tptr, void (T::*mptr)(void)) { + if((mptr != NULL) && (tptr != NULL)) { + isrIntTCStat.attach(tptr, mptr); + } + } + + /** + * The MODDMA controllers terminal count interrupt callback. + */ + FunctionPointer isrIntTCStat; + + /** + * Attach a callback to the ERR IRQ controller. + * + * @ingroup API + * @param fptr A function pointer to call + * @return this + */ + void attach_err(void (*fptr)(void)) { + isrIntErrStat.attach(fptr); + } + + /** + * Attach a callback to the ERR IRQ controller. + * + * @ingroup API + * @param tptr A template pointer to the calling object + * @param mptr A method pointer within the object to call. + * @return this + */ + template<typename T> + void attach_err(T* tptr, void (T::*mptr)(void)) { + if((mptr != NULL) && (tptr != NULL)) { + isrIntErrStat.attach(tptr, mptr); + } + } + + /** + * Get the Linked List index regsiter for the requested channel. + * + * @param channelNum The channel number. + * @return uint32_t The value of the DMACCLLI register + */ + uint32_t lli(CHANNELS ChannelNumber, MODDMA_LLI *set = 0) { + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( ChannelNumber & 0x7 ); + if (set) pChannel->DMACCLLI = (uint32_t)set; + return pChannel->DMACCLLI; + } + + /** + * The MODDMA controllers error interrupt callback. + */ + FunctionPointer isrIntErrStat; + +protected: + + // Data LUTs. + uint32_t LUTPerAddr(int n); + uint8_t LUTPerBurst(int n); + uint8_t LUTPerWid(int n); + uint32_t Channel_p(int channel); + + CHANNELS IrqProcessingChannel; + + IrqType_t IrqType; +}; + +}; // namespace AjK ends. + +using namespace AjK; + +#endif
--- a/SETUP.cpp Wed Nov 24 00:32:49 2010 +0000 +++ b/SETUP.cpp Sat Feb 05 08:53:26 2011 +0000 @@ -1,156 +1,156 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#include "MODDMA.h" - -namespace AjK { - -MODDMA::Status -MODDMA::Setup(MODDMA_Config *config) -{ - LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( config->channelNum() ); - - if (LPC_GPDMA->DMACEnbldChns & EnbldChns_Ch( config->channelNum() )) { - return ErrChInUse; - } - - setups[config->channelNum() & 0x7] = config; - - // Reset the Interrupt status - LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() ); - LPC_GPDMA->DMACIntErrClr = IntErrClr_Ch ( config->channelNum() ); - - // Clear DMA configure - pChannel->DMACCControl = 0x00; - pChannel->DMACCConfig = 0x00; - - // Assign Linker List Item value - pChannel->DMACCLLI = config->dmaLLI(); - - // Set value to Channel Control Registers - switch (config->transferType()) { - - // Memory to memory - case m2m: - // Assign physical source and destination address - pChannel->DMACCSrcAddr = config->srcMemAddr(); - pChannel->DMACCDestAddr = config->dstMemAddr(); - pChannel->DMACCControl - = CxControl_TransferSize(config->transferSize()) - | CxControl_SBSize(_32) - | CxControl_DBSize(_32) - | CxControl_SWidth(config->transferWidth()) - | CxControl_DWidth(config->transferWidth()) - | CxControl_SI() - | CxControl_DI() - | CxControl_I(); - break; - - // Memory to peripheral - case m2p: - // Assign physical source - pChannel->DMACCSrcAddr = config->srcMemAddr(); - // Assign peripheral destination address - pChannel->DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn()); - pChannel->DMACCControl - = CxControl_TransferSize((uint32_t)config->transferSize()) - | CxControl_SBSize((uint32_t)LUTPerBurst(config->dstConn())) - | CxControl_DBSize((uint32_t)LUTPerBurst(config->dstConn())) - | CxControl_SWidth((uint32_t)LUTPerWid(config->dstConn())) - | CxControl_DWidth((uint32_t)LUTPerWid(config->dstConn())) - | CxControl_SI() - | CxControl_I(); - break; - - // Peripheral to memory - case p2m: - // Assign peripheral source address - pChannel->DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn()); - // Assign memory destination address - pChannel->DMACCDestAddr = config->dstMemAddr(); - pChannel->DMACCControl - = CxControl_TransferSize((uint32_t)config->transferSize()) - | CxControl_SBSize((uint32_t)LUTPerBurst(config->srcConn())) - | CxControl_DBSize((uint32_t)LUTPerBurst(config->srcConn())) - | CxControl_SWidth((uint32_t)LUTPerWid(config->srcConn())) - | CxControl_DWidth((uint32_t)LUTPerWid(config->srcConn())) - | CxControl_DI() - | CxControl_I(); - break; - - // Peripheral to peripheral - case p2p: - // Assign peripheral source address - pChannel->DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn()); - // Assign peripheral destination address - pChannel->DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn()); - pChannel->DMACCControl - = CxControl_TransferSize((uint32_t)config->transferSize()) - | CxControl_SBSize((uint32_t)LUTPerBurst(config->srcConn())) - | CxControl_DBSize((uint32_t)LUTPerBurst(config->dstConn())) - | CxControl_SWidth((uint32_t)LUTPerWid(config->srcConn())) - | CxControl_DWidth((uint32_t)LUTPerWid(config->dstConn())) - | CxControl_I(); - break; - - // Do not support any more transfer type, return ERROR - default: - return Error; - } - - // Re-Configure DMA Request Select for source peripheral - if (config->srcConn() > 15) { - LPC_SC->RESERVED9 |= (1 << (config->srcConn() - 16)); - } - else { - LPC_SC->RESERVED9 &= ~(1 << (config->srcConn() - 8)); - } - - // Re-Configure DMA Request Select for Destination peripheral - if (config->dstConn() > 15) { - LPC_SC->RESERVED9 |= (1 << (config->dstConn() - 16)); - } - else { - LPC_SC->RESERVED9 &= ~(1 << (config->dstConn() - 8)); - } - - // Enable DMA channels, little endian - LPC_GPDMA->DMACConfig = _E; - while (!(LPC_GPDMA->DMACConfig & _E)); - - // Calculate absolute value for Connection number - uint32_t tmp1 = config->srcConn(); tmp1 = ((tmp1 > 15) ? (tmp1 - 8) : tmp1); - uint32_t tmp2 = config->dstConn(); tmp2 = ((tmp2 > 15) ? (tmp2 - 8) : tmp2); - - // Configure DMA Channel, enable Error Counter and Terminate counter - pChannel->DMACCConfig - = CxConfig_IE() - | CxConfig_ITC() - | CxConfig_TransferType((uint32_t)config->transferType()) - | CxConfig_SrcPeripheral(tmp1) - | CxConfig_DestPeripheral(tmp2); - - return Ok; -} - -}; // namespace AjK ends - +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "MODDMA.h" + +namespace AjK { + +uint32_t +MODDMA::Setup(MODDMA_Config *config) +{ + LPC_GPDMACH_TypeDef *pChannel = (LPC_GPDMACH_TypeDef *)Channel_p( config->channelNum() ); + + if (LPC_GPDMA->DMACEnbldChns & EnbldChns_Ch( config->channelNum() )) { + return 0; + } + + setups[config->channelNum() & 0x7] = config; + + // Reset the Interrupt status + LPC_GPDMA->DMACIntTCClear = IntTCClear_Ch( config->channelNum() ); + LPC_GPDMA->DMACIntErrClr = IntErrClr_Ch ( config->channelNum() ); + + // Clear DMA configure + pChannel->DMACCControl = 0x00; + pChannel->DMACCConfig = 0x00; + + // Assign Linker List Item value + pChannel->DMACCLLI = config->dmaLLI(); + + // Set value to Channel Control Registers + switch (config->transferType()) { + + // Memory to memory + case m2m: + // Assign physical source and destination address + pChannel->DMACCSrcAddr = config->srcMemAddr(); + pChannel->DMACCDestAddr = config->dstMemAddr(); + pChannel->DMACCControl + = CxControl_TransferSize(config->transferSize()) + | CxControl_SBSize(_32) + | CxControl_DBSize(_32) + | CxControl_SWidth(config->transferWidth()) + | CxControl_DWidth(config->transferWidth()) + | CxControl_SI() + | CxControl_DI() + | CxControl_I(); + break; + + // Memory to peripheral + case m2p: + // Assign physical source + pChannel->DMACCSrcAddr = config->srcMemAddr(); + // Assign peripheral destination address + pChannel->DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn()); + pChannel->DMACCControl + = CxControl_TransferSize((uint32_t)config->transferSize()) + | CxControl_SBSize((uint32_t)LUTPerBurst(config->dstConn())) + | CxControl_DBSize((uint32_t)LUTPerBurst(config->dstConn())) + | CxControl_SWidth((uint32_t)LUTPerWid(config->dstConn())) + | CxControl_DWidth((uint32_t)LUTPerWid(config->dstConn())) + | CxControl_SI() + | CxControl_I(); + break; + + // Peripheral to memory + case p2m: + // Assign peripheral source address + pChannel->DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn()); + // Assign memory destination address + pChannel->DMACCDestAddr = config->dstMemAddr(); + pChannel->DMACCControl + = CxControl_TransferSize((uint32_t)config->transferSize()) + | CxControl_SBSize((uint32_t)LUTPerBurst(config->srcConn())) + | CxControl_DBSize((uint32_t)LUTPerBurst(config->srcConn())) + | CxControl_SWidth((uint32_t)LUTPerWid(config->srcConn())) + | CxControl_DWidth((uint32_t)LUTPerWid(config->srcConn())) + | CxControl_DI() + | CxControl_I(); + break; + + // Peripheral to peripheral + case p2p: + // Assign peripheral source address + pChannel->DMACCSrcAddr = (uint32_t)LUTPerAddr(config->srcConn()); + // Assign peripheral destination address + pChannel->DMACCDestAddr = (uint32_t)LUTPerAddr(config->dstConn()); + pChannel->DMACCControl + = CxControl_TransferSize((uint32_t)config->transferSize()) + | CxControl_SBSize((uint32_t)LUTPerBurst(config->srcConn())) + | CxControl_DBSize((uint32_t)LUTPerBurst(config->dstConn())) + | CxControl_SWidth((uint32_t)LUTPerWid(config->srcConn())) + | CxControl_DWidth((uint32_t)LUTPerWid(config->dstConn())) + | CxControl_I(); + break; + + // Do not support any more transfer type, return ERROR + default: + return 0; + } + + // Re-Configure DMA Request Select for source peripheral + if (config->srcConn() > 15) { + LPC_SC->RESERVED9 |= (1 << (config->srcConn() - 16)); + } + else { + LPC_SC->RESERVED9 &= ~(1 << (config->srcConn() - 8)); + } + + // Re-Configure DMA Request Select for Destination peripheral + if (config->dstConn() > 15) { + LPC_SC->RESERVED9 |= (1 << (config->dstConn() - 16)); + } + else { + LPC_SC->RESERVED9 &= ~(1 << (config->dstConn() - 8)); + } + + // Enable DMA channels, little endian + LPC_GPDMA->DMACConfig = _E; + while (!(LPC_GPDMA->DMACConfig & _E)); + + // Calculate absolute value for Connection number + uint32_t tmp1 = config->srcConn(); tmp1 = ((tmp1 > 15) ? (tmp1 - 8) : tmp1); + uint32_t tmp2 = config->dstConn(); tmp2 = ((tmp2 > 15) ? (tmp2 - 8) : tmp2); + + // Configure DMA Channel, enable Error Counter and Terminate counter + pChannel->DMACCConfig + = CxConfig_IE() + | CxConfig_ITC() + | CxConfig_TransferType((uint32_t)config->transferType()) + | CxConfig_SrcPeripheral(tmp1) + | CxConfig_DestPeripheral(tmp2); + + return pChannel->DMACCControl; +} + +}; // namespace AjK ends +
--- a/example1.cpp Wed Nov 24 00:32:49 2010 +0000 +++ b/example1.cpp Sat Feb 05 08:53:26 2011 +0000 @@ -1,92 +1,92 @@ -#ifdef COMPILE_EXAMPLE_CODE_MODDMA - -#include "mbed.h" -#include "MODDMA.h" -#include "MODSERIAL.h" - -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); -MODDMA dma; -MODSERIAL pc(USBTX, USBRX); - -// Function prototypes for IRQ callbacks. -// See definitions following main() below. -void dmaTCCallback(void); -void dmaERRCallback(void); -void TC0_callback(void); -void ERR0_callback(void); - -int main() { - char s[] = "**DMA** ABCDEFGHIJKLMNOPQRSTUVWXYZ **DMA**"; - - pc.baud(PC_BAUD); - - dma.attach_tc( &dmaTCCallback ); - dma.attach_err( &dmaERRCallback ); - - MODDMA_Config *config = new MODDMA_Config; - config - ->channelNum ( MODDMA::Channel_0 ) - ->srcMemAddr ( (uint32_t) &s ) - ->dstMemAddr ( 0 ) - ->transferSize ( sizeof(s) ) - ->transferType ( MODDMA::m2p ) - ->transferWidth ( 0 ) - ->srcConn ( 0 ) - ->dstConn ( MODDMA::UART0_Tx ) - ->dmaLLI ( 0 ) - ->attach_tc ( &TC0_callback ) - ->attach_err ( &ERR0_callback ) - ; // config end - - // Setup the configuration. - dma.Setup(config); - - //dma.Enable( MODDMA::Channel_0 ); - //dma.Enable( config->channelNum() ); - dma.Enable( config ); - - while (1) { - led1 = !led1; - wait(0.25); - } -} - -// Main controller TC IRQ callback -void dmaTCCallback(void) { - led2 = 1; -} - -// Main controller ERR IRQ callback -void dmaERRCallback(void) { - error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); -} - -// Configuration callback on TC -void TC0_callback(void) { - MODDMA_Config *config = dma.getConfig(); - dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); - dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); - - // Configurations have two IRQ callbacks for TC and Err so you - // know which you are processing. However, if you want to use - // a single callback function you can tell what type of IRQ - // is being processed thus:- - if (dma.irqType() == MODDMA::TcIrq) { - led3 = 1; - dma.clearTcIrq(); - } - if (dma.irqType() == MODDMA::ErrIrq) { - led4 = 1; - dma.clearErrIrq(); - } -} - -// Configuration cakllback on Error -void ERR0_callback(void) { - error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); -} - -#endif +#ifdef COMPILE_EXAMPLE1_CODE_MODDMA + +#include "mbed.h" +#include "MODDMA.h" +#include "MODSERIAL.h" + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); +MODDMA dma; +MODSERIAL pc(USBTX, USBRX); + +// Function prototypes for IRQ callbacks. +// See definitions following main() below. +void dmaTCCallback(void); +void dmaERRCallback(void); +void TC0_callback(void); +void ERR0_callback(void); + +int main() { + char s[] = "**DMA** ABCDEFGHIJKLMNOPQRSTUVWXYZ **DMA**"; + + pc.baud(PC_BAUD); + + dma.attach_tc( &dmaTCCallback ); + dma.attach_err( &dmaERRCallback ); + + MODDMA_Config *config = new MODDMA_Config; + config + ->channelNum ( MODDMA::Channel_0 ) + ->srcMemAddr ( (uint32_t) &s ) + ->dstMemAddr ( 0 ) + ->transferSize ( sizeof(s) ) + ->transferType ( MODDMA::m2p ) + ->transferWidth ( 0 ) + ->srcConn ( 0 ) + ->dstConn ( MODDMA::UART0_Tx ) + ->dmaLLI ( 0 ) + ->attach_tc ( &TC0_callback ) + ->attach_err ( &ERR0_callback ) + ; // config end + + // Setup the configuration. + dma.Setup(config); + + //dma.Enable( MODDMA::Channel_0 ); + //dma.Enable( config->channelNum() ); + dma.Enable( config ); + + while (1) { + led1 = !led1; + wait(0.25); + } +} + +// Main controller TC IRQ callback +void dmaTCCallback(void) { + led2 = 1; +} + +// Main controller ERR IRQ callback +void dmaERRCallback(void) { + error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); +} + +// Configuration callback on TC +void TC0_callback(void) { + MODDMA_Config *config = dma.getConfig(); + dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); + dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); + + // Configurations have two IRQ callbacks for TC and Err so you + // know which you are processing. However, if you want to use + // a single callback function you can tell what type of IRQ + // is being processed thus:- + if (dma.irqType() == MODDMA::TcIrq) { + led3 = 1; + dma.clearTcIrq(); + } + if (dma.irqType() == MODDMA::ErrIrq) { + led4 = 1; + dma.clearErrIrq(); + } +} + +// Configuration cakllback on Error +void ERR0_callback(void) { + error("Oh no! My Mbed exploded! :( Only kidding, find the problem"); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example2.cpp Sat Feb 05 08:53:26 2011 +0000 @@ -0,0 +1,140 @@ +#ifdef COMPILE_EXAMPLE2_CODE_MODDMA + +/* + * This example was provided to support Mbed forum thread:- + * http://mbed.org/forum/mbed/topic/1798 + */ + +#include "mbed.h" +#include "MODDMA.h" + +#define SAMPLE_BUFFER_LENGTH 32 + +DigitalOut led1(LED1); +DigitalOut led2(LED2); + +MODDMA dma; +Serial pc(USBTX, USBRX); + +// ISR set's this when transfer complete. +bool dmaTransferComplete = false; + +// Function prototypes for IRQ callbacks. +// See definitions following main() below. +void TC0_callback(void); +void ERR0_callback(void); + +int main() { + + // Create a buffer to hold the ADC samples and clear it. + // Note, we are going to sample two ADC inputs so they + // end up in this buffer "interleaved". So you will want + // a buffer twice this size to a real life given sample + // frequency. See the printf() output for details. + uint32_t adcInputBuffer[SAMPLE_BUFFER_LENGTH]; + memset(adcInputBuffer, 0, sizeof(adcInputBuffer)); + + // We use the ADC irq to trigger DMA and the manual says + // that in this case the NVIC for ADC must be disabled. + NVIC_DisableIRQ(ADC_IRQn); + + // Power up the ADC and set PCLK + LPC_SC->PCONP |= (1UL << 12); + LPC_SC->PCLKSEL0 &= ~(3UL << 16); // PCLK = CCLK/4 96M/4 = 24MHz + + // Enable the ADC, 12MHz, ADC0.0 & .1 + LPC_ADC->ADCR = (1UL << 21) | (1UL << 8) | (3UL << 0); + + // Set the pin functions to ADC + LPC_PINCON->PINSEL1 &= ~(3UL << 14); /* P0.23, Mbed p15. */ + LPC_PINCON->PINSEL1 |= (1UL << 14); + LPC_PINCON->PINSEL1 &= ~(3UL << 16); /* P0.24, Mbed p16. */ + LPC_PINCON->PINSEL1 |= (1UL << 16); + + // Setup the serial port to print out results. + pc.baud(115200); + pc.printf("ADC with DMA example\n"); + pc.printf("====================\n"); + + // Prepare an ADC configuration. + MODDMA_Config *conf = new MODDMA_Config; + conf + ->channelNum ( MODDMA::Channel_0 ) + ->srcMemAddr ( 0 ) + ->dstMemAddr ( (uint32_t)adcInputBuffer ) + ->transferSize ( SAMPLE_BUFFER_LENGTH ) + ->transferType ( MODDMA::p2m ) + ->transferWidth ( MODDMA::word ) + ->srcConn ( MODDMA::ADC ) + ->dstConn ( 0 ) + ->dmaLLI ( 0 ) + ->attach_tc ( &TC0_callback ) + ->attach_err ( &ERR0_callback ) + ; // end conf. + + // Prepare configuration. + dma.Setup( conf ); + + // Enable configuration. + dma.Enable( conf ); + + // Enable ADC irq flag (to DMA). + // Note, don't set the individual flags, + // just set the global flag. + LPC_ADC->ADINTEN = 0x100; + + // Enable burst mode on inputs 0 and 1. + LPC_ADC->ADCR |= (1UL << 16); + + while (1) { + // When transfer complete do this block. + if (dmaTransferComplete) { + delete conf; // No memory leaks, delete the configuration. + dmaTransferComplete = false; + for (int i = 0; i < SAMPLE_BUFFER_LENGTH; i++) { + int channel = (adcInputBuffer[i] >> 24) & 0x7; + int iVal = (adcInputBuffer[i] >> 4) & 0xFFF; + double fVal = 3.3 * (double)((double)iVal) / ((double)0x1000); // scale to 0v to 3.3v + pc.printf("Array index %02d : ADC input channel %d = 0x%03x %01.3f volts\n", i, channel, iVal, fVal); + } + } + + // Just flash LED1 for something to do. + led1 = !led1; + wait(0.25); + } +} + +// Configuration callback on TC +void TC0_callback(void) { + + MODDMA_Config *config = dma.getConfig(); + + // Disbale burst mode and switch off the IRQ flag. + LPC_ADC->ADCR &= ~(1UL << 16); + LPC_ADC->ADINTEN = 0; + + // Finish the DMA cycle by shutting down the channel. + dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); + dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); + + // Tell main() while(1) loop to print the results. + dmaTransferComplete = true; + + // Switch on LED2 to show transfer complete. + led2 = 1; + + // Clear DMA IRQ flags. + if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); + if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); +} + +// Configuration callback on Error +void ERR0_callback(void) { + // Switch off burst conversions. + LPC_ADC->ADCR |= ~(1UL << 16); + LPC_ADC->ADINTEN = 0; + error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iomacros.h Sat Feb 05 08:53:26 2011 +0000 @@ -0,0 +1,417 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef IOMACROS_H +#define IOMACROS_H + +#ifndef __LPC17xx_H__ +#include "LPC17xx.h" +#endif + +#define PIN_PULLUP 0UL +#define PIN_REPEAT 1UL +#define PIN_NONE 2UL +#define PIN_PULLDOWN 3UL + +/* p5 is P0.9 */ +#define p5_SEL_MASK ~(3UL << 18) +#define p5_SET_MASK (1UL << 9) +#define p5_CLR_MASK ~(p5_SET_MASK) +#define p5_AS_OUTPUT LPC_PINCON->PINSEL0&=p5_SEL_MASK;LPC_GPIO0->FIODIR|=p5_SET_MASK +#define p5_AS_INPUT LPC_GPIO0->FIOMASK &= p5_CLR_MASK; +#define p5_SET LPC_GPIO0->FIOSET = p5_SET_MASK +#define p5_CLR LPC_GPIO0->FIOCLR = p5_SET_MASK +#define p5_IS_SET (bool)(LPC_GPIO0->FIOPIN & p5_SET_MASK) +#define p5_IS_CLR !(p5_IS_SET) +#define p5_MODE(x) LPC_PINCON->PINMODE0&=p5_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<18) + +/* p6 is P0.8 */ +#define p6_SEL_MASK ~(3UL << 16) +#define p6_SET_MASK (1UL << 8) +#define p6_CLR_MASK ~(p6_SET_MASK) +#define p6_AS_OUTPUT LPC_PINCON->PINSEL0&=p6_SEL_MASK;LPC_GPIO0->FIODIR|=p6-SET_MASK +#define p6_AS_INPUT LPC_GPIO0->FIOMASK &= p6_CLR_MASK; +#define p6_SET LPC_GPIO0->FIOSET = p6_SET_MASK +#define p6_CLR LPC_GPIO0->FIOCLR = p6_SET_MASK +#define p6_IS_SET (bool)(LPC_GPIO0->FIOPIN & p6_SET_MASK) +#define p6_IS_CLR !(p6_IS_SET) +#define p6_MODE(x) LPC_PINCON->PINMODE0&=p6_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<16) + +/* p7 is P0.7 */ +#define p7_SEL_MASK ~(3UL << 14) +#define p7_SET_MASK (1UL << 7) +#define p7_CLR_MASK ~(p7_SET_MASK) +#define p7_AS_OUTPUT LPC_PINCON->PINSEL0&=p7_SEL_MASK;LPC_GPIO0->FIODIR|=p7_SET_MASK +#define p7_AS_INPUT LPC_GPIO0->FIOMASK &= p7_CLR_MASK; +#define p7_SET LPC_GPIO0->FIOSET = p7_SET_MASK +#define p7_CLR LPC_GPIO0->FIOCLR = p7_SET_MASK +#define p7_IS_SET (bool)(LPC_GPIO0->FIOPIN & p7_SET_MASK) +#define p7_IS_CLR !(p7_IS_SET) +#define p7_MODE(x) LPC_PINCON->PINMODE0&=p7_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<14) + +/* p8 is P0.6 */ +#define p8_SEL_MASK ~(3UL << 12) +#define p8_SET_MASK (1UL << 6) +#define p8_AS_OUTPUT LPC_PINCON->PINSEL0&=p8_SEL_MASK;LPC_GPIO0->FIODIR|=p8_SET_MASK +#define p8_AS_INPUT LPC_GPIO0->FIOMASK &= p8_CLR_MASK; +#define p8_SET LPC_GPIO0->FIOSET = p8_SET_MASK +#define p8_CLR LPC_GPIO0->FIOCLR = p8_SET_MASK +#define p8_IS_SET (bool)(LPC_GPIO0->FIOPIN & p8_SET_MASK) +#define p8_IS_CLR !(p8_IS_SET) +#define p8_MODE(x) LPC_PINCON->PINMODE0&=p8_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<12) + +/* p9 is P0.0 */ +#define p9_SEL_MASK ~(3UL << 0) +#define p9_SET_MASK (1UL << 0) +#define p9_CLR_MASK ~(p9_SET_MASK) +#define p9_AS_OUTPUT LPC_PINCON->PINSEL0&=p9_SEL_MASK;LPC_GPIO0->FIODIR|=p9_SET_MASK +#define p9_AS_INPUT LPC_GPIO0->FIOMASK &= p9_CLR_MASK; +#define p9_SET LPC_GPIO0->FIOSET = p9_SET_MASK +#define p9_CLR LPC_GPIO0->FIOCLR = p9_SET_MASK +#define p9_IS_SET (bool)(LPC_GPIO0->FIOPIN & p9_SET_MASK) +#define p9_IS_CLR !(p9_IS_SET) +#define p9_MODE(x) LPC_PINCON->PINMODE0&=p9_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<0) + +/* p10 is P0.1 */ +#define p10_SEL_MASK ~(3UL << 2) +#define p10_SET_MASK (1UL << 1) +#define p10_CLR_MASK ~(p10_SET_MASK) +#define p10_AS_OUTPUT LPC_PINCON->PINSEL0&=p10_SEL_MASK;LPC_GPIO0->FIODIR|=p10_SET_MASK +#define p10_AS_INPUT LPC_GPIO0->FIOMASK &= p10_CLR_MASK; +#define p10_SET LPC_GPIO0->FIOSET = p10_SET_MASK +#define p10_CLR LPC_GPIO0->FIOCLR = p10_SET_MASK +#define p10_IS_SET (bool)(LPC_GPIO0->FIOPIN & p10_SET_MASK) +#define p10_IS_CLR !(p10_IS_SET) +#define p10_MODE(x) LPC_PINCON->PINMODE0&=p10_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<2) + +/* p11 is P0.18 */ +#define p11_SEL_MASK ~(3UL << 4) +#define p11_SET_MASK (1UL << 18) +#define p11_CLR_MASK ~(p11_SET_MASK) +#define p11_AS_OUTPUT LPC_PINCON->PINSEL1&=p11_SEL_MASK;LPC_GPIO0->FIODIR|=p11_SET_MASK +#define p11_AS_INPUT LPC_GPIO0->FIOMASK &= p11_CLR_MASK; +#define p11_SET LPC_GPIO0->FIOSET = p11_SET_MASK +#define p11_CLR LPC_GPIO0->FIOCLR = p11_SET_MASK +#define p11_IS_SET (bool)(LPC_GPIO0->FIOPIN & p11_SET_MASK) +#define p11_IS_CLR !(p11_IS_SET) +#define p11_MODE(x) LPC_PINCON->PINMODE1&=p11_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<4) + +/* p12 is P0.17 */ +#define p12_SEL_MASK ~(3UL << 2) +#define p12_SET_MASK (1UL << 17) +#define p12_CLR_MASK ~(p12_SET_MASK) +#define p12_AS_OUTPUT LPC_PINCON->PINSEL1&=p12_SEL_MASK;LPC_GPIO0->FIODIR|=p12_SET_MASK +#define p12_AS_INPUT LPC_GPIO0->FIOMASK &= p12_CLR_MASK; +#define p12_SET LPC_GPIO0->FIOSET = p12_SET_MASK +#define p12_CLR LPC_GPIO0->FIOCLR = p12_SET_MASK +#define p12_IS_SET (bool)(LPC_GPIO0->FIOPIN & p12_SET_MASK) +#define p12_IS_CLR !(p12_IS_SET) +#define p12_MODE(x) LPC_PINCON->PINMODE1&=p12_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<2) + +/* p13 is P0.15 */ +#define p13_SEL_MASK ~(3UL << 30) +#define p13_SET_MASK (1UL << 15) +#define p13_CLR_MASK ~(p13_SET_MASK) +#define p13_AS_OUTPUT LPC_PINCON->PINSEL0&=p13_SEL_MASK;LPC_GPIO0->FIODIR|=p13_SET_MASK +#define p13_AS_INPUT LPC_GPIO0->FIOMASK &= p13_CLR_MASK; +#define p13_SET LPC_GPIO0->FIOSET = p13_SET_MASK +#define p13_CLR LPC_GPIO0->FIOCLR = p13_SET_MASK +#define p13_IS_SET (bool)(LPC_GPIO0->FIOPIN & p13_SET_MASK) +#define p13_IS_CLR !(p13_IS_SET) +#define p13_MODE(x) LPC_PINCON->PINMODE0&=p13_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<30) + +/* p14 is P0.16 */ +#define p14_SEL_MASK ~(3UL << 0) +#define p14_SET_MASK (1UL << 16) +#define p14_CLR_MASK ~(p14_SET_MASK) +#define p14_AS_OUTPUT LPC_PINCON->PINSEL1&=p14_SEL_MASK;LPC_GPIO0->FIODIR|=p14_SET_MASK +#define p14_AS_INPUT LPC_GPIO0->FIOMASK &= p14_CLR_MASK; +#define p14_SET LPC_GPIO0->FIOSET = p14_SET_MASK +#define p14_CLR LPC_GPIO0->FIOCLR = p14_SET_MASK +#define p14_IS_SET (bool)(LPC_GPIO0->FIOPIN & p14_SET_MASK) +#define p14_IS_CLR !(p14_IS_SET) +#define p14_MODE(x) LPC_PINCON->PINMODE1&=p14_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<0) + +/* p15 is P0.23 */ +#define p15_SEL_MASK ~(3UL << 14) +#define p15_SET_MASK (1UL << 23) +#define p15_CLR_MASK ~(p15_SET_MASK) +#define p15_AS_OUTPUT LPC_PINCON->PINSEL1&=p15_SEL_MASK;LPC_GPIO0->FIODIR|=p15_SET_MASK +#define p15_AS_INPUT LPC_GPIO0->FIOMASK &= p15_CLR_MASK; +#define p15_SET LPC_GPIO0->FIOSET = p15_SET_MASK +#define p15_CLR LPC_GPIO0->FIOCLR = p15_SET_MASK +#define p15_IS_SET (bool)(LPC_GPIO0->FIOPIN & p15_SET_MASK) +#define p15_IS_CLR !(p15_IS_SET) +#define p15_MODE(x) LPC_PINCON->PINMODE1&=p15_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<14) + +/* p16 is P0.24 */ +#define p16_SEL_MASK ~(3UL << 16) +#define p16_SET_MASK (1UL << 24) +#define p16_CLR_MASK ~(p16_SET_MASK) +#define p16_AS_OUTPUT LPC_PINCON->PINSEL1&=p16_SEL_MASK;LPC_GPIO0->FIODIR|=p16_SET_MASK +#define p16_AS_INPUT LPC_GPIO0->FIOMASK &= p16_CLR_MASK; +#define p16_SET LPC_GPIO0->FIOSET = p16_SET_MASK +#define p16_CLR LPC_GPIO0->FIOCLR = p16_SET_MASK +#define p16_IS_SET (bool)(LPC_GPIO0->FIOPIN & p16_SET_MASK) +#define p16_IS_CLR !(p16_IS_SET) +#define p16_MODE(x) LPC_PINCON->PINMODE1&=p16_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<16) + +/* p17 is P0.25 */ +#define p17_SEL_MASK ~(3UL << 18) +#define p17_SET_MASK (1UL << 25) +#define p17_CLR_MASK ~(p17_SET_MASK) +#define p17_AS_OUTPUT LPC_PINCON->PINSEL1&=p17_SEL_MASK;LPC_GPIO0->FIODIR|=p17_SET_MASK +#define p17_AS_INPUT LPC_GPIO0->FIOMASK &= p17_CLR_MASK; +#define p17_SET LPC_GPIO0->FIOSET = p17_SET_MASK +#define p17_CLR LPC_GPIO0->FIOCLR = p17_SET_MASK +#define p17_IS_SET (bool)(LPC_GPIO0->FIOPIN & p17_SET_MASK) +#define p17_IS_CLR !(p17_IS_SET) +#define p17_MODE(x) LPC_PINCON->PINMODE1&=p17_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<18) + +/* p18 is P0.26 */ +#define p18_SEL_MASK ~(3UL << 20) +#define p18_SET_MASK (1UL << 26) +#define p18_CLR_MASK ~(p18_SET_MASK) +#define p18_AS_OUTPUT LPC_PINCON->PINSEL1&=p18_SEL_MASK;LPC_GPIO0->FIODIR|=p18_SET_MASK +#define p18_AS_INPUT LPC_GPIO0->FIOMASK &= p18_CLR_MASK; +#define p18_SET LPC_GPIO0->FIOSET = p18_SET_MASK +#define p18_CLR LPC_GPIO0->FIOCLR = p18_SET_MASK +#define p18_IS_SET (bool)(LPC_GPIO0->FIOPIN & p18_SET_MASK) +#define p18_IS_CLR !(p18_IS_SET) +#define p18_MODE(x) LPC_PINCON->PINMODE1&=p18_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<20) + +/* p19 is P1.30 */ +#define p19_SEL_MASK ~(3UL << 28) +#define p19_SET_MASK (1UL << 30) +#define p19_AS_OUTPUT LPC_PINCON->PINSEL3&=p19_SEL_MASK;LPC_GPIO1->FIODIR|=p19_SET_MASK +#define p19_AS_INPUT LPC_GPIO1->FIOMASK &= p19_CLR_MASK; +#define p19_SET LPC_GPIO1->FIOSET = p19_SET_MASK +#define p19_CLR LPC_GPIO1->FIOCLR = p19_SET_MASK +#define p19_IS_SET (bool)(LPC_GPIO1->FIOPIN & p19_SET_MASK) +#define p19_IS_CLR !(p19_IS_SET) +#define p19_MODE(x) LPC_PINCON->PINMODE3&=p19_SEL_MASK;LPC_PINCON->PINMODE3|=((x&0x3)<<28) + +/* p20 is P1.31 */ +#define p20_SEL_MASK ~(3UL << 30) +#define p20_SET_MASK (1UL << 31) +#define p20_CLR_MASK ~(p20_SET_MASK) +#define p20_AS_OUTPUT LPC_PINCON->PINSEL3&=p20_SEL_MASK;LPC_GPIO1->FIODIR|=p20_SET_MASK +#define p20_AS_INPUT LPC_GPIO1->FIOMASK &= p20_CLR_MASK; +#define p20_SET LPC_GPIO1->FIOSET = p20_SET_MASK +#define p20_CLR LPC_GPIO1->FIOCLR = p20_SET_MASK +#define p20_IS_SET (bool)(LPC_GPIO1->FIOPIN & p20_SET_MASK) +#define p20_IS_CLR !(p20_IS_SET) +#define p20_MODE(x) LPC_PINCON->PINMODE3&=p20_SEL_MASK;LPC_PINCON->PINMODE3|=((x&0x3)<<30) + +/* p21 is P2.5 */ +#define p21_SEL_MASK ~(3UL << 10) +#define p21_SET_MASK (1UL << 5) +#define p21_CLR_MASK ~(p21_SET_MASK) +#define p21_AS_OUTPUT LPC_PINCON->PINSEL4&=p21_SEL_MASK;LPC_GPIO2->FIODIR|=p21_SET_MASK +#define p21_AS_INPUT LPC_GPIO2->FIOMASK &= p21_CLR_MASK; +#define p21_SET LPC_GPIO2->FIOSET = p21_SET_MASK +#define p21_CLR LPC_GPIO2->FIOCLR = p21_SET_MASK +#define p21_IS_SET (bool)(LPC_GPIO2->FIOPIN & p21_SET_MASK) +#define p21_IS_CLR !(p21_IS_SET) +#define p21_TOGGLE p21_IS_SET?p21_CLR:p21_SET +#define p21_MODE(x) LPC_PINCON->PINMODE4&=p21_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<10) + +/* p22 is P2.4 */ +#define p22_SEL_MASK ~(3UL << 8) +#define p22_SET_MASK (1UL << 4) +#define p22_CLR_MASK ~(p22_SET_MASK) +#define p22_AS_OUTPUT LPC_PINCON->PINSEL4&=p22_SEL_MASK;LPC_GPIO2->FIODIR|=p22_SET_MASK +#define p22_AS_INPUT LPC_GPIO2->FIOMASK &= p22_CLR_MASK; +#define p22_SET LPC_GPIO2->FIOSET = p22_SET_MASK +#define p22_CLR LPC_GPIO2->FIOCLR = p22_SET_MASK +#define p22_IS_SET (bool)(LPC_GPIO2->FIOPIN & p22_SET_MASK) +#define p22_IS_CLR !(p22_IS_SET) +#define p22_TOGGLE p22_IS_SET?p22_CLR:p22_SET +#define p22_MODE(x) LPC_PINCON->PINMODE4&=p22_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<8) + +/* p23 is P2.3 */ +#define p23_SEL_MASK ~(3UL << 6) +#define p23_SET_MASK (1UL << 3) +#define p23_CLR_MASK ~(p23_SET_MASK) +#define p23_AS_OUTPUT LPC_PINCON->PINSEL4&=p23_SEL_MASK;LPC_GPIO2->FIODIR|=p23_SET_MASK +#define p23_AS_INPUT LPC_GPIO2->FIOMASK &= p23_CLR_MASK; +#define p23_SET LPC_GPIO2->FIOSET = p23_SET_MASK +#define p23_CLR LPC_GPIO2->FIOCLR = p23_SET_MASK +#define p23_IS_SET (bool)(LPC_GPIO2->FIOPIN & p23_SET_MASK) +#define p23_IS_CLR !(p23_IS_SET) +#define p23_TOGGLE p23_IS_SET?p23_CLR:p23_SET +#define p23_MODE(x) LPC_PINCON->PINMODE4&=p23_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<6) + +/* p24 is P2.2 */ +#define p24_SEL_MASK ~(3UL << 4) +#define p24_SET_MASK (1UL << 2) +#define p24_CLR_MASK ~(p24_SET_MASK) +#define p24_AS_OUTPUT LPC_PINCON->PINSEL4&=p24_SEL_MASK;LPC_GPIO2->FIODIR|=p24_SET_MASK +#define p24_AS_INPUT LPC_GPIO2->FIOMASK &= p24_CLR_MASK; +#define p24_SET LPC_GPIO2->FIOSET = p24_SET_MASK +#define p24_CLR LPC_GPIO2->FIOCLR = p24_SET_MASK +#define p24_IS_SET (bool)(LPC_GPIO2->FIOPIN & p24_SET_MASK) +#define p24_IS_CLR !(p24_IS_SET) +#define p24_TOGGLE p24_IS_SET?p24_CLR:p24_SET +#define p24_MODE(x) LPC_PINCON->PINMODE4&=p24_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<4) + +/* p25 is P2.1 */ +#define p25_SEL_MASK ~(3UL << 2) +#define p25_SET_MASK (1UL << 1) +#define p25_CLR_MASK ~(p25_SET_MASK) +#define p25_AS_OUTPUT LPC_PINCON->PINSEL4&=p25_SEL_MASK;LPC_GPIO2->FIODIR|=p25_SET_MASK +#define p25_AS_INPUT LPC_GPIO2->FIOMASK &= p25_CLR_MASK; +#define p25_SET LPC_GPIO2->FIOSET = p25_SET_MASK +#define p25_CLR LPC_GPIO2->FIOCLR = p25_SET_MASK +#define p25_IS_SET (bool)(LPC_GPIO2->FIOPIN & p25_SET_MASK) +#define p25_IS_CLR !(p25_IS_SET) +#define p25_MODE(x) LPC_PINCON->PINMODE4&=p25_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<2) + +/* p26 is P2.0 */ +#define p26_SEL_MASK ~(3UL << 0) +#define p26_SET_MASK (1UL << 0) +#define p26_CLR_MASK ~(p26_SET_MASK) +#define p26_AS_OUTPUT LPC_PINCON->PINSEL4&=p26_SEL_MASK;LPC_GPIO2->FIODIR|=p26_SET_MASK +#define p26_AS_INPUT LPC_GPIO2->FIOMASK &= p26_CLR_MASK; +#define p26_SET LPC_GPIO2->FIOSET = p26_SET_MASK +#define p26_CLR LPC_GPIO2->FIOCLR = p26_SET_MASK +#define p26_IS_SET (bool)(LPC_GPIO2->FIOPIN & p26_SET_MASK) +#define p26_IS_CLR !(p26_IS_SET) +#define p26_MODE(x) LPC_PINCON->PINMODE4&=p26_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<0) + +/* p27 is P0.11 */ +#define p27_SEL_MASK ~(3UL << 22) +#define p27_SET_MASK (1UL << 11) +#define p27_CLR_MASK ~(p27_SET_MASK) +#define p27_AS_OUTPUT LPC_PINCON->PINSEL0&=p27_SEL_MASK;LPC_GPIO0->FIODIR|=p27_SET_MASK +#define p27_AS_INPUT LPC_GPIO0->FIOMASK &= p27_CLR_MASK; +#define p27_SET LPC_GPIO0->FIOSET = p27_SET_MASK +#define p27_CLR LPC_GPIO0->FIOCLR = p27_SET_MASK +#define p27_IS_SET (bool)(LPC_GPIO0->FIOPIN & p27_SET_MASK) +#define p27_IS_CLR !(p27_IS_SET) +#define p27_MODE(x) LPC_PINCON->PINMODE0&=p27_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<22) + +/* p28 is P0.10 */ +#define p28_SEL_MASK ~(3UL << 20) +#define p28_SET_MASK (1UL << 10) +#define p28_CLR_MASK ~(p28_SET_MASK) +#define p28_AS_OUTPUT LPC_PINCON->PINSEL0&=p28_SEL_MASK;LPC_GPIO0->FIODIR|=p28_SET_MASK +#define p28_AS_INPUT LPC_GPIO0->FIOMASK &= p28_CLR_MASK; +#define p28_SET LPC_GPIO0->FIOSET = p28_SET_MASK +#define p28_CLR LPC_GPIO0->FIOCLR = p28_SET_MASK +#define p28_IS_SET (bool)(LPC_GPIO0->FIOPIN & p28_SET_MASK) +#define p28_IS_CLR !(p28_IS_SET) +#define p28_MODE(x) LPC_PINCON->PINMODE0&=p28_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<20) + +/* p29 is P0.5 */ +#define p29_SEL_MASK ~(3UL << 10) +#define p29_SET_MASK (1UL << 5) +#define p29_CLR_MASK ~(p29_SET_MASK) +#define p29_AS_OUTPUT LPC_PINCON->PINSEL0&=p29_SEL_MASK;LPC_GPIO0->FIODIR|=p29_SET_MASK +#define p29_AS_INPUT LPC_GPIO0->FIOMASK &= p29_CLR_MASK; +#define p29_SET LPC_GPIO0->FIOSET = p29_SET_MASK +#define p29_CLR LPC_GPIO0->FIOCLR = p29_SET_MASK +#define p29_IS_SET (bool)(LPC_GPIO0->FIOPIN & p29_SET_MASK) +#define p29_IS_CLR !(p29_IS_SET) +#define p29_TOGGLE p29_IS_SET?p29_CLR:p29_SET +#define p29_MODE(x) LPC_PINCON->PINMODE0&=p29_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<10) + +/* p30 is P0.4 */ +#define p30_SEL_MASK ~(3UL << 8) +#define p30_SET_MASK (1UL << 4) +#define p30_CLR_MASK ~(p30_SET_MASK) +#define p30_AS_OUTPUT LPC_PINCON->PINSEL0&=p30_SEL_MASK;LPC_GPIO0->FIODIR|=p30_SET_MASK +#define p30_AS_INPUT LPC_GPIO0->FIOMASK &= p30_CLR_MASK; +#define p30_SET LPC_GPIO0->FIOSET = p30_SET_MASK +#define p30_CLR LPC_GPIO0->FIOCLR = p30_SET_MASK +#define p30_IS_SET (bool)(LPC_GPIO0->FIOPIN & p30_SET_MASK) +#define p30_IS_CLR !(p30_IS_SET) +#define p30_MODE(x) LPC_PINCON->PINMODE0&=p30_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<8) + +/* The following definitions are for the four Mbed LEDs. + LED1 = P1.18 + LED2 = P1.20 + LED3 = P1.21 + LED4 = P1.23 */ + +#define P1_18_SEL_MASK ~(3UL << 4) +#define P1_18_SET_MASK (1UL << 18) +#define P1_18_CLR_MASK ~(P1_18_SET_MASK) +#define P1_18_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_18_SEL_MASK;LPC_GPIO1->FIODIR|=P1_18_SET_MASK +#define P1_18_AS_INPUT LPC_GPIO1->FIOMASK &= P1_18_CLR_MASK; +#define P1_18_SET LPC_GPIO1->FIOSET = P1_18_SET_MASK +#define P1_18_CLR LPC_GPIO1->FIOCLR = P1_18_SET_MASK +#define P1_18_IS_SET (bool)(LPC_GPIO1->FIOPIN & P1_18_SET_MASK) +#define P1_18_IS_CLR !(P1_18_IS_SET) +#define LED1_USE P1_18_AS_OUTPUT;P1_18_AS_INPUT +#define LED1_ON P1_18_SET +#define LED1_OFF P1_18_CLR +#define LED1_IS_ON P1_18_IS_SET +#define LED1_TOGGLE P1_18_IS_SET?LED1_OFF:LED1_ON + +#define P1_20_SEL_MASK ~(3UL << 8) +#define P1_20_SET_MASK (1UL << 20) +#define P1_20_CLR_MASK ~(P1_20_SET_MASK) +#define P1_20_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_20_SEL_MASK;LPC_GPIO1->FIODIR|=P1_20_SET_MASK +#define P1_20_AS_INPUT LPC_GPIO1->FIOMASK &= P1_20_CLR_MASK; +#define P1_20_SET LPC_GPIO1->FIOSET = P1_20_SET_MASK +#define P1_20_CLR LPC_GPIO1->FIOCLR = P1_20_SET_MASK +#define P1_20_IS_SET (bool)(LPC_GPIO1->FIOPIN & P1_20_SET_MASK) +#define P1_20_IS_CLR !(P1_20_IS_SET) +#define LED2_USE P1_20_AS_OUTPUT;P1_20_AS_INPUT +#define LED2_ON P1_20_SET +#define LED2_OFF P1_20_CLR +#define LED2_IS_ON P1_20_IS_SET +#define LED2_TOGGLE P1_20_IS_SET?LED2_OFF:LED2_ON + +#define P1_21_SEL_MASK ~(3UL << 10) +#define P1_21_SET_MASK (1UL << 21) +#define P1_21_CLR_MASK ~(P1_21_SET_MASK) +#define P1_21_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_21_SEL_MASK;LPC_GPIO1->FIODIR|=P1_21_SET_MASK +#define P1_21_AS_INPUT LPC_GPIO1->FIOMASK &= P1_21_CLR_MASK; +#define P1_21_SET LPC_GPIO1->FIOSET = P1_21_SET_MASK +#define P1_21_CLR LPC_GPIO1->FIOCLR = P1_21_SET_MASK +#define P1_21_IS_SET (bool)(LPC_GPIO1->FIOPIN & P1_21_SET_MASK) +#define P1_21_IS_CLR !(P1_21_IS_SET) +#define LED3_USE P1_21_AS_OUTPUT;P1_21_AS_INPUT +#define LED3_ON P1_21_SET +#define LED3_OFF P1_21_CLR +#define LED3_IS_ON P1_21_IS_SET +#define LED3_TOGGLE P1_21_IS_SET?LED3_OFF:LED3_ON + +#define P1_23_SEL_MASK ~(3UL << 14) +#define P1_23_SET_MASK (1UL << 23) +#define P1_23_CLR_MASK ~(P1_23_SET_MASK) +#define P1_23_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_23_SEL_MASK;LPC_GPIO1->FIODIR|=P1_23_SET_MASK +#define P1_23_AS_INPUT LPC_GPIO1->FIOMASK &= P1_23_CLR_MASK; +#define P1_23_SET LPC_GPIO1->FIOSET = P1_23_SET_MASK +#define P1_23_CLR LPC_GPIO1->FIOCLR = P1_23_SET_MASK +#define P1_23_IS_SET (bool)(LPC_GPIO1->FIOPIN & P1_23_SET_MASK) +#define P1_23_IS_CLR !(P1_23_IS_SET) +#define LED4_USE P1_23_AS_OUTPUT;P1_23_AS_INPUT +#define LED4_ON P1_23_SET +#define LED4_OFF P1_23_CLR +#define LED4_IS_ON P1_23_IS_SET +#define LED4_TOGGLE P1_23_IS_SET?LED4_OFF:LED4_ON + +#endif +