DMA library for the KL25Z
Dependents: SimpleDMA_HelloWorld RTOS_SPI spiDMAtest Pinscape_Controller_v1 ... more
SimpleDMA_LPC1768.cpp
00001 #ifdef TARGET_LPC1768 00002 00003 #include "SimpleDMA.h" 00004 00005 SimpleDMA *SimpleDMA::irq_owner[8] = {NULL}; 00006 LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7}; 00007 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination); 00008 00009 SimpleDMA::SimpleDMA(int channel) { 00010 this->channel(channel); 00011 00012 //Power up 00013 LPC_SC->PCONP |= 1<<29; 00014 LPC_GPDMA->DMACConfig = 1; 00015 trigger(Trigger_ALWAYS); 00016 00017 NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0); 00018 NVIC_EnableIRQ(DMA_IRQn); 00019 } 00020 00021 int SimpleDMA::start(uint32_t length) { 00022 if (auto_channel) 00023 _channel = getFreeChannel(); 00024 else 00025 while(isBusy()); 00026 00027 uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31); 00028 switch (source_size) { 00029 case 16: 00030 control |= (1<<18) | (length >> 1); 00031 break; 00032 case 32: 00033 control |= (2<<18) | (length >> 2); 00034 break; 00035 default: 00036 control |= length; 00037 } 00038 switch (destination_size) { 00039 case 16: 00040 control |= (1<<21); 00041 break; 00042 case 32: 00043 control |= (2<<21); 00044 break; 00045 } 00046 00047 LPC_GPDMACH[_channel]->DMACCSrcAddr = _source; 00048 LPC_GPDMACH[_channel]->DMACCDestAddr = _destination; 00049 LPC_GPDMACH[_channel]->DMACCLLI = 0; 00050 LPC_GPDMACH[_channel]->DMACCControl = control; //Enable interrupt also 00051 00052 irq_owner[_channel] = this; 00053 00054 if (_trigger != Trigger_ALWAYS) { 00055 if (_trigger & 16) 00056 LPC_SC->DMAREQSEL |= 1 << (_trigger - 24); 00057 else 00058 LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24)); 00059 00060 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 00061 } else 00062 LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15); //Enable channel 00063 00064 return 0; 00065 } 00066 00067 bool SimpleDMA::isBusy( int channel ) { 00068 if (channel == -1) 00069 channel = _channel; 00070 return (LPC_GPDMA->DMACEnbldChns & (1<<channel)); 00071 } 00072 00073 void SimpleDMA::irq_handler0(void) { 00074 while(LPC_GPDMA->DMACIntTCStat != 0) { 00075 00076 uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF); 00077 if (irq_owner[intloc]!=NULL) 00078 irq_owner[intloc]->irq_handler(); 00079 } 00080 } 00081 00082 void SimpleDMA::irq_handler(void) { 00083 LPC_GPDMA->DMACIntTCClear = 1<<_channel; 00084 _callback.call(); 00085 } 00086 00087 static inline bool isMemory(uint32_t addr) 00088 { 00089 return (addr >> 28) == 0 || (addr >> 28) == 1 || ((addr >= 0x2007C000) && (addr < (0x2007C000 + 0x8000))); 00090 } 00091 00092 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) { 00093 //If it is always, simply put it on memory-to-memory 00094 if (trig == Trigger_ALWAYS) 00095 return 0; 00096 else if (isMemory(source)) { //if source is RAM/Flash 00097 if (isMemory(destination)) //if destination is RAM/flash 00098 return 3; //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do) 00099 else 00100 return 1; //Source is memory, destination is peripheral, so m2p 00101 } 00102 else { 00103 if (isMemory(destination)) 00104 return 2; //Source is peripheral, destination is memory 00105 else 00106 return 3; //Both source and destination are peripherals 00107 } 00108 00109 } 00110 #endif
Generated on Tue Jul 19 2022 07:00:06 by 1.7.2