dma.c
362 lines
| 11.9 KiB
| text/x-c
|
CLexer
r103 | /*------------------------------------------------------------------------------ | |||
-- 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 <dma.h> | ||||
#include <stm32f4xx_gpio.h> | ||||
#include <stm32f4xx_rcc.h> | ||||
#include <stm32f4xx_dma.h> | ||||
#include <misc.h> | ||||
#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; | ||||
} | ||||