Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: FirstTest WaveSim IO-dma-memmem DACDMAfuncgenlib ... more
Revision 0:c409efd8df78, committed 2010-11-23
- Comitter:
- AjK
- Date:
- Tue Nov 23 14:50:39 2010 +0000
- Child:
- 1:9700b9455cbf
- Commit message:
- 0.1
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CONFIG.h Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,96 @@
+/*
+ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ChangeLog.c Tue Nov 23 14:50:39 2010 +0000 @@ -0,0 +1,8 @@ +/* $Id:$ + + +1.0 - 22/11/2010 + + * First release + +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DATALUTS.cpp Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/INIT.cpp Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MODDMA.cpp Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,144 @@
+/*
+ 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.
+ if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) {
+ 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.
+ if (moddma_p->Enabled( (MODDMA::CHANNELS)channel_number )) {
+ 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
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MODDMA.h Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,508 @@
+/*
+ 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 1.0
+ @date Nov 2010
+ @author Andy Kirkham
+*/
+
+#ifndef MODDMA_H
+#define MODDMA_H
+
+/** @defgroup API The MODSERIAL API */
+/** @defgroup MISC Misc MODSERIAL functions */
+/** @defgroup INTERNALS MODSERIAL Internals */
+
+#include "mbed.h"
+
+namespace AjK {
+
+/**
+ * @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 the defines a single instance controller that
+ * manages all the GPDMA hardware registers and interrupts. The controller can accept multiple
+ * configurations that define the transfer. Each configuration specifies the src and dest 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 ) // Buffer is memory, dest 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_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; }
+
+ 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;
+*/
+
+/**
+ * @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.
+ * transfers from memory to memory, memory to peripheral or peripheral to memory.
+ */
+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.
+ *
+ * @param c A pointer to an instance of MODDMA_Config to setup.
+ */
+ Status Setup(MODDMA_Config *c);
+
+ /**
+ * Enable and begin data transfer.
+ *
+ * @param ChannelNumber Type CHANNELS, the channel number to enable
+ */
+ void Enable(CHANNELS ChannelNumber);
+
+ /**
+ * Enable and begin data transfer (overloaded function)
+ *
+ * @param ChannelNumber Type uin32_t, the channel number to enable
+ */
+ void Enable(uint32_t ChannelNumber) { Enable((CHANNELS)(ChannelNumber & 0x7)); }
+
+ /**
+ * Disable a channel and end data transfer.
+ *
+ * @param ChannelNumber Type CHANNELS, the channel number to enable
+ */
+ void Disable(CHANNELS ChannelNumber);
+
+ /**
+ * Disable a channel and end data transfer (overloaded function)
+ *
+ * @param ChannelNumber Type uin32_t, the channel number to disable
+ */
+ void Disable(uint32_t ChannelNumber) { Disable((CHANNELS)(ChannelNumber & 0x7)); }
+
+ /**
+ * Is the specified channel enabled?
+ *
+ * @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)
+ *
+ * @param ChannelNumber Type uin32_t, the channel number to test
+ * @return bool true if enabled, false otherwise.
+ */
+ bool Enabled(uint32_t ChannelNumber) { 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.
+ *
+ * @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.
+ *
+ * @return CHANNELS The current channel the ISR is servicing.
+ */
+ CHANNELS irqProcessingChannel(void) { return IrqProcessingChannel; }
+
+ /**
+ * Gets which channel the ISR is currently servicing.
+ *
+ * @return uint32_t The current channel the ISR is servicing.
+ */
+ uint32_t irqProcessingChannel(void) { return (uint32_t)(IrqProcessingChannel & 0x7); }
+
+ /**
+ * 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.
+ *
+ * @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.
+ */
+ void clearErrIrq(void) { clearErrIrq( IrqProcessingChannel ); }
+
+ /**
+ * Is the supplied channel currently active?
+ *
+ * @param CHANNELS The channel to inquire about.
+ * @return bool true if active, false otherwise.
+ */
+ bool isActive(CHANNELS ChannelNumber);
+
+ /**
+ * Halt the supplied channel.
+ *
+ * @param CHANNELS The channel to halt.
+ */
+ void haltChannel(CHANNELS ChannelNumber);
+
+ /**
+ * Wait for channel transfer to complete and then halt.
+ *
+ * @param CHANNELS The channel to wait for then halt.
+ */
+ void haltAndWaitChannelComplete(CHANNELS n) { haltChannel(n); while (isActive(n)); }
+
+ /**
+ * The MODDMA controllers terminal count interrupt callback.
+ */
+ FunctionPointer isrIntTCStat;
+
+ /**
+ * The MODDMA controllers error interrupt callback.
+ */
+ FunctionPointer isrIntErrStat;
+
+protected:
+
+ void init(bool isConstructorCalling, int Channels = 0xFF, int Tc = 0xFF, int Err = 0xFF);
+
+ // 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SETUP.cpp Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +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
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/example1.cpp Tue Nov 23 14:50:39 2010 +0000
@@ -0,0 +1,71 @@
+#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);
+//Serial pc(USBTX, USBRX);
+
+void dmaCallback(void) {
+ led2 = 1;
+}
+
+void C0callback(void) {
+ MODDMA_Config *config = dma.getConfig();
+ dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
+ dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+ if (dma.irqType() == MODDMA::TcIrq) {
+ led3 = 1;
+ dma.clearTcIrq();
+ }
+ if (dma.irqType() == MODDMA::ErrIrq) {
+ led4 = 1;
+ dma.clearErrIrq();
+ }
+}
+
+int main() {
+ char s[] = "**DMA** ABCDEFGHIJKLMNOPQRSTUVWXYZ **DMA**";
+
+ pc.baud(115200);
+
+ dma.isrIntTCStat.attach(&dmaCallback);
+
+ 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 )
+ ;//->isrIntTCStat->attach(&C0callback)
+ ; // config end
+
+ dma.Setup(config);
+
+ //dma.Enable( MODDMA::Channel_0 );
+ dma.Enable( config->channelNum() );
+
+ pc.printf("123456789\r\n");
+ pc.printf("\r\nRESERVED9 = %p", &LPC_SC->RESERVED9);
+ pc.printf("\r\nOther = %p", &LPC_UART0->DMAREQSEL);
+
+ while (1) {
+ led1 = !led1;
+ wait(0.2);
+ led1 = !led1;
+ wait(0.2);
+ }
+}
+
+#endif