/*------------------------------------------------------------------------------ -- This file is a part of the libuc, microcontroler library -- Copyright (C) 2012, Alexis Jeandet -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------------- -- Author : Alexis Jeandet -- Mail : alexis.jeandet@member.fsf.org -------------------------------------------------------------------------------*/ #include #include #include #include #include #define GPIOGETPORT(gpio) ((GPIO_TypeDef*)(((((uint32_t)gpio) & (uint32_t)0x0000FF00)*(uint32_t)4) + (uint32_t)GPIOA)) #define GPIOPORTNUM(gpio) (((uint32_t)(gpio) & (uint32_t)0x0000FF00)>>(uint32_t)8) typedef enum dmaStreamState { avail=0, inUse=1, locked=2, }dmaStreamState; char __DMA2_streams__[8]={avail,avail,avail,avail,avail,avail,avail,avail}; DMA_Stream_TypeDef* __DMA2_streams_list__[8]={DMA2_Stream0,DMA2_Stream1,DMA2_Stream2,DMA2_Stream3,DMA2_Stream4,DMA2_Stream5,DMA2_Stream6,DMA2_Stream7}; int __DMA2_streams_channels__[8]={DMA_Channel_1,DMA_Channel_3,DMA_Channel_2,DMA_Channel_0,DMA_Channel_3,DMA_Channel_5,DMA_Channel_3,DMA_Channel_3}; uint32_t __DMA2_streams_remainig_data__[8]={0,0,0,0,0,0,0,0}; int __DMA_Csts__[8]={0,0,0,0,0,0,0,0}; char __dma_is_initialised =0; typedef struct _dma_config_ { uint32_t source; uint32_t dest; int size; int count; char incSrc; char incDest; }_dma_config_; _dma_config_ __DMA2_streams_config__[8]; void __set_DMA_inc__(DMA_InitTypeDef* DMA_InitStructure,int* incsz,int*datacnt) { switch (*incsz) { case 1: DMA_InitStructure->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; break; case 2: DMA_InitStructure->DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure->DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; break; case 4: DMA_InitStructure->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA_InitStructure->DMA_MemoryDataSize = DMA_MemoryDataSize_Word; break; default: DMA_InitStructure->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; (*datacnt)*=(*incsz); *incsz=1; break; } } void __DMA2_init() { int irq[8]={DMA2_Stream0_IRQn,DMA2_Stream1_IRQn,DMA2_Stream2_IRQn,DMA2_Stream3_IRQn,DMA2_Stream4_IRQn,DMA2_Stream5_IRQn,DMA2_Stream6_IRQn,DMA2_Stream7_IRQn}; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); for(int i=0;i<8;i++) { if(__DMA2_streams__[i]!=locked) { DMA_DeInit(__DMA2_streams_list__[i]); DMA_ITConfig(__DMA2_streams_list__[i], DMA_IT_TC, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = irq[i]; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } } __dma_is_initialised = 1; } void __dmacopy__(uint32_t source, uint32_t dest, int size, int count,char incSrc,char incDest,int streamIndex) { DMA_InitTypeDef DMA_InitStructure; DMA_Stream_TypeDef* stream=__DMA2_streams_list__[streamIndex]; while (DMA_GetCmdStatus(stream) != DISABLE); __set_DMA_inc__(&DMA_InitStructure,&size,&count); DMA_InitStructure.DMA_Channel = __DMA2_streams_channels__[streamIndex]; DMA_InitStructure.DMA_PeripheralBaseAddr = source; DMA_InitStructure.DMA_Memory0BaseAddr = dest; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory; if(count>65535) { DMA_InitStructure.DMA_BufferSize = 65535; __DMA2_streams_config__[streamIndex].count = count-65535; } else { DMA_InitStructure.DMA_BufferSize = count; __DMA2_streams_config__[streamIndex].count = 0; } __DMA2_streams_config__[streamIndex].incDest = incDest; __DMA2_streams_config__[streamIndex].incSrc = incSrc; __DMA2_streams_config__[streamIndex].size = size; if(incSrc) { __DMA2_streams_config__[streamIndex].source = source+(DMA_InitStructure.DMA_BufferSize*size); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; } else { __DMA2_streams_config__[streamIndex].source = source; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; } if(incDest) { __DMA2_streams_config__[streamIndex].dest = dest+(DMA_InitStructure.DMA_BufferSize*size); DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; } else { __DMA2_streams_config__[streamIndex].dest = dest; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; } DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(stream, &DMA_InitStructure); DMA_Cmd(stream, ENABLE); } dmaID_t dmacopy(uint32_t source, uint32_t dest, int size, int count,char incSrc,char incDest) { int streamIndex; if(!__dma_is_initialised) { __DMA2_init(); } for(int i=0;i<8;i++) { if(__DMA2_streams__[i]==avail) { streamIndex=i; __DMA2_streams__[i]=inUse; break; } } __dmacopy__(source,dest,size,count,incSrc,incDest,streamIndex); return streamIndex; } void DMA2_continueCp(int streamIndex) { DMA_InitTypeDef DMA_InitStructure; DMA_Stream_TypeDef* stream = __DMA2_streams_list__[streamIndex]; if ((DMA_GetCmdStatus(stream) != DISABLE) && (__DMA2_streams__[streamIndex]==inUse)) { return; } if(__DMA2_streams_config__[streamIndex].count==0) { __DMA2_streams__[streamIndex]=avail; return; } __set_DMA_inc__(&DMA_InitStructure,&(__DMA2_streams_config__[streamIndex].size),&(__DMA2_streams_config__[streamIndex].count)); DMA_InitStructure.DMA_Channel = __DMA2_streams_channels__[streamIndex]; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory; DMA_InitStructure.DMA_PeripheralBaseAddr = __DMA2_streams_config__[streamIndex].source; DMA_InitStructure.DMA_Memory0BaseAddr = __DMA2_streams_config__[streamIndex].dest; if(__DMA2_streams_config__[streamIndex].count>65535) { DMA_InitStructure.DMA_BufferSize = 65535; __DMA2_streams_config__[streamIndex].count = __DMA2_streams_config__[streamIndex].count-65535; } else { DMA_InitStructure.DMA_BufferSize = __DMA2_streams_config__[streamIndex].count; __DMA2_streams_config__[streamIndex].count = 0; } if(__DMA2_streams_config__[streamIndex].incSrc) { __DMA2_streams_config__[streamIndex].source +=(DMA_InitStructure.DMA_BufferSize*__DMA2_streams_config__[streamIndex].size); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; } else { __DMA2_streams_config__[streamIndex].source = __DMA2_streams_config__[streamIndex].source; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; } if(__DMA2_streams_config__[streamIndex].incDest) { __DMA2_streams_config__[streamIndex].dest +=(DMA_InitStructure.DMA_BufferSize*__DMA2_streams_config__[streamIndex].size); DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; } else { __DMA2_streams_config__[streamIndex].dest = __DMA2_streams_config__[streamIndex].dest; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; } DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(stream, &DMA_InitStructure); DMA_Cmd(stream, ENABLE); } void DMA2_Stream0_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); DMA2_continueCp(0); } } void DMA2_Stream1_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1); DMA2_continueCp(1); } } void DMA2_Stream2_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF2)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2); DMA2_continueCp(2); } } void DMA2_Stream3_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream3, DMA_IT_TCIF3)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream3, DMA_IT_TCIF3); DMA2_continueCp(3); } } void DMA2_Stream4_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream4, DMA_IT_TCIF4)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_TCIF4); DMA2_continueCp(4); } } void DMA2_Stream5_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream5, DMA_IT_TCIF5)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5); DMA2_continueCp(5); } } void DMA2_Stream6_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream6, DMA_IT_TCIF6)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream6, DMA_IT_TCIF6); DMA2_continueCp(6); } } void DMA2_Stream7_IRQHandler(void) { if(DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7); DMA2_continueCp(7); } } int dmaIsReady(dmaID_t dmaID) { if(!__dma_is_initialised) { __DMA2_init(); } return __DMA2_streams__[dmaID]==avail; } int dmaLockStream(int stream, int dmaDev) { if(!__dma_is_initialised) { __DMA2_init(); } if(dmaDev==2) { if(__DMA2_streams__[stream]==locked) { return 0; } while(__DMA2_streams__[stream]==inUse); __DMA2_streams__[stream]=locked; return 1; } } dmaID_t dmamemset(uint32_t dest, int val, int size) { int streamIndex; if(!__dma_is_initialised) { __DMA2_init(); } for(int i=0;i<8;i++) { if(__DMA2_streams__[i]==avail) { streamIndex=i; __DMA2_streams__[i]=inUse; break; } } __DMA_Csts__[streamIndex]=val; __dmacopy__((uint32_t)(__DMA_Csts__ + streamIndex),dest,1,size,0,1,streamIndex); return streamIndex; }