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.
Dependencies: USBDevice mbed FastAnalogIn FastIO FastPWM SimpleDMA
Diff: SimpleDMA/SimpleDMA_LPC1768.cpp
- Revision:
- 45:c42166b2878c
diff -r b5ac89b9cd5d -r c42166b2878c SimpleDMA/SimpleDMA_LPC1768.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleDMA/SimpleDMA_LPC1768.cpp Mon Feb 15 20:30:32 2016 +0000
@@ -0,0 +1,110 @@
+#ifdef TARGET_LPC1768
+
+#include "SimpleDMA.h"
+
+SimpleDMA *SimpleDMA::irq_owner[8] = {NULL};
+LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7};
+uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination);
+
+SimpleDMA::SimpleDMA(int channel) {
+ this->channel(channel);
+
+ //Power up
+ LPC_SC->PCONP |= 1<<29;
+ LPC_GPDMA->DMACConfig = 1;
+ trigger(Trigger_ALWAYS);
+
+ NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0);
+ NVIC_EnableIRQ(DMA_IRQn);
+}
+
+int SimpleDMA::start(uint32_t length) {
+ if (auto_channel)
+ _channel = getFreeChannel();
+ else
+ while(isBusy());
+
+ uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31);
+ switch (source_size) {
+ case 16:
+ control |= (1<<18) | (length >> 1);
+ break;
+ case 32:
+ control |= (2<<18) | (length >> 2);
+ break;
+ default:
+ control |= length;
+ }
+ switch (destination_size) {
+ case 16:
+ control |= (1<<21);
+ break;
+ case 32:
+ control |= (2<<21);
+ break;
+ }
+
+ LPC_GPDMACH[_channel]->DMACCSrcAddr = _source;
+ LPC_GPDMACH[_channel]->DMACCDestAddr = _destination;
+ LPC_GPDMACH[_channel]->DMACCLLI = 0;
+ LPC_GPDMACH[_channel]->DMACCControl = control; //Enable interrupt also
+
+ irq_owner[_channel] = this;
+
+ if (_trigger != Trigger_ALWAYS) {
+ if (_trigger & 16)
+ LPC_SC->DMAREQSEL |= 1 << (_trigger - 24);
+ else
+ LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24));
+
+ LPC_GPDMACH[_channel]->DMACCConfig = ((_trigger & 15) << 1) + ((_trigger & 15) << 6) + (getTransferType(_trigger, _source, _destination) << 11) + (1<<15) +1; //Both parts of the transfer get triggered at same time
+ } else
+ LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15); //Enable channel
+
+ return 0;
+}
+
+bool SimpleDMA::isBusy( int channel ) {
+ if (channel == -1)
+ channel = _channel;
+ return (LPC_GPDMA->DMACEnbldChns & (1<<channel));
+}
+
+void SimpleDMA::irq_handler0(void) {
+ while(LPC_GPDMA->DMACIntTCStat != 0) {
+
+ uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF);
+ if (irq_owner[intloc]!=NULL)
+ irq_owner[intloc]->irq_handler();
+ }
+}
+
+void SimpleDMA::irq_handler(void) {
+ LPC_GPDMA->DMACIntTCClear = 1<<_channel;
+ _callback.call();
+}
+
+static inline bool isMemory(uint32_t addr)
+{
+ return (addr >> 28) == 0 || (addr >> 28) == 1 || ((addr >= 0x2007C000) && (addr < (0x2007C000 + 0x8000)));
+}
+
+uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) {
+ //If it is always, simply put it on memory-to-memory
+ if (trig == Trigger_ALWAYS)
+ return 0;
+ else if (isMemory(source)) { //if source is RAM/Flash
+ if (isMemory(destination)) //if destination is RAM/flash
+ return 3; //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do)
+ else
+ return 1; //Source is memory, destination is peripheral, so m2p
+ }
+ else {
+ if (isMemory(destination))
+ return 2; //Source is peripheral, destination is memory
+ else
+ return 3; //Both source and destination are peripherals
+ }
+
+}
+#endif
\ No newline at end of file