2016-05-13 06:49 AM
Hello,
I tried to use the TIM2/3/4/5 Input-Capture with DMA (''TIM_DMA_CC1'') to trigger a DMA-Transfer (this writes to a GPIO-Port for parallel Data-transmission) but it just Work with DMA2, not DMA1. All (TIM2/3/4/5) APB1-Timer (with DMA1) didn't trigger a DMA-Transfer, but with the APB2-Timers TIM1 and TIM8 (with DMA2) will work correctly. (Yes , I checked the correct GPIO-Input-Pin by every Timer-change) Can someone explain, why the DMA1 in the Reference under 3.3 have not working TIM mappings ? Tried with STM32F407 and STM32F429 and got same results. Code:
void setupParallelPort(){
GPIO_InitTypeDef GPIO_InitStructure;
// Enable the GPIOD
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
int main(void) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t testData[2048];
/* write a Ramp for OutputData */
for (ct = 0; ct <
sizeof
(testData)/sizeof(*testData); ct++) {
testData[ct] = ct;
}
setupParallelPort();
/* TIM5 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
// Clock Enable
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
/* PH10 == TIM5CH1 */
GPIO_InitStructure.GPIO_Pin
=
GPIO_Pin_10
;
GPIO_InitStructure.GPIO_Mode
=
GPIO_Mode_AF
;
GPIO_InitStructure.GPIO_Speed
=
GPIO_Speed_100MHz
;
GPIO_InitStructure.GPIO_OType
=
GPIO_OType_PP
;
GPIO_InitStructure.GPIO_PuPd
=
GPIO_PuPd_NOPULL
;
GPIO_Init(GPIOH, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOH, GPIO_PinSource10, GPIO_AF_TIM5);
/* ** IC-Pin ** */
TIM_ICInitStructure.TIM_Channel
=
TIM_Channel_1
;
TIM_ICInitStructure.TIM_ICFilter
=
0
;
TIM_ICInitStructure.TIM_ICPolarity
=
TIM_ICPolarity_Rising
;
TIM_ICInitStructure.TIM_ICPrescaler
=
TIM_ICPSC_DIV1
;
TIM_ICInitStructure.TIM_ICSelection
=
TIM_ICSelection_DirectTI
;
TIM_ICInit(TIM5,&TIM_ICInitStructure);
// DMA-Disable
DMA_Cmd(DMA1_Stream2, DISABLE);
// warten bis DMA-Stream disable
while(DMA_GetCmdStatus(DMA1_Stream2) == ENABLE);
DMA_DeInit(DMA1_Stream2);
// DMA-Config
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel
=
DMA_Channel_6
;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&GPIOD->ODR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)testData;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = sizeof(testData)/sizeof(*testData);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream2, &DMA_InitStructure);
// clear the DMA-Flag
DMA_ClearITPendingBit(DMA1_Stream2, DMA_IT_TCIF6);
// DMA-enable
DMA_Cmd(DMA1_Stream2, ENABLE);
while(DMA_GetCmdStatus(DMA1_Stream2) == DISABLE);
// NVIC-Config
DMA_ITConfig(DMA1_Stream2, DMA_IT_TC , ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_DMACmd(TIM5,TIM_DMA_CC1,ENABLE);
}
void DMA1_Stream2_IRQHandler(){
printf(''interrupt ...'');//DEBUG: this will never executed
if (DMA_GetFlagStatus(DMA1_Stream2,DMA_FLAG_TCIF6) == SET){
TIM_Cmd(TIM5, DISABLE);
DMA_Cmd(DMA1_Stream2, DISABLE);
DMA_ClearITPendingBit(DMA1_Stream2,DMA_FLAG_TCIF6);
}
}
#tim-dma1-icc
2016-05-13 06:58 AM
Only DMA2 (on APB2 peripherals) supports memory-to-memory required to get data from memory to the GPIO port, also in memory.
You could use DMA1 to write TIM2->CCR1 for example, because it's on APB12016-05-13 07:10 AM
The problem is that the peripheral port on DMA1 only has access to peripherals on APB1, not to other parts of the chip - in particular it can access neither memory or GPIOs (which are on the AHB1 bus). So it can transfer from an APB1 peripherals' registers to GPIO/memory, _or_ from memory/GPIO to an APB1 peripheral, but not memory-to-GPIO (or memory to memory).
In contrast, DMA2's peripheral port is connected to the bus matrix, so it has no such restriction. So your code works on DMA2, but not DMA1. You can see this in the reference manual for STM32F07 in the section on DMA functional description (figure 25 in my version of the document), and in the device overview in the datasheet. This was also discussed in this thread: Hope this helps, - Kristian.2016-05-13 07:13 AM
Look carefully at Figure1 and Figure2 in RM0090 rev.11.
GPIO are at AHB1. There is no connection from DMA1 to AHB1 - not even on its memory port. JW2016-05-13 07:30 AM
Thanks for your Help.