cancel
Showing results for 
Search instead for 
Did you mean: 

dma issue when writing to TIM1->BDTR

mhage
Associate II
Posted on May 23, 2014 at 20:15

whenever i perform the dma transfer, I always get a transfer error on the write to TIM1->BDTR. If I write to a different peripheral register, such as TIM3->ARR, it succeeds. Any thoughts?


TIM_TimeBaseInitTypeDef TIM1_TimeBaseStructure;

TIM_OCInitTypeDef TIM1_OCInitStructure;

TIM_BDTRInitTypeDef TIM1_BDTRInitStruct;

TIM_TimeBaseInitTypeDef TIM3_TimeBaseStructure;

TIM_OCInitTypeDef TIM3_OCInitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

RCC_ClocksTypeDef RCC_Clocks;

uint16_t period;

uint8_t dc = 30;

uint16_t pulse1;

uint16_t pulse2;

TIM_TypeDef const * tim1;

TIM_TypeDef const * tim3;

TIM_TypeDef const * tim8;

DMA_InitTypeDef sDMAInitStructureTx;



tim1 = (TIM_TypeDef*)TIM1_BASE;

tim3 = (TIM_TypeDef*)TIM3_BASE;

tim8 = (TIM_TypeDef*)TIM8_BASE;



RCC_GetClocksFreq(&RCC_Clocks);



/* Compute the value for the ARR register to have a period of 350 KHz */

period = (RCC_Clocks.HCLK_Frequency / 350000 ) - 1; 



/* Compute the CCR2 value */

pulse1 = (uint16_t) (((uint32_t) (100 - dc) * (period - 1)) / 100); 



/* Compute the CCR3 value */

pulse2 = (uint16_t) (((uint32_t) (dc) * (period - 1)) / 100); 



/* TIM3 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);



/* GPIOB clock enable */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);



/* TIM1 clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);



/* DMA1 clock enable */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);



/* Initialize PB0, Alternative Function, 100Mhz, Output, Push-pull */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;

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_UP ;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM1); 

GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM1); 



/* Timer Base configuration */

TIM_TimeBaseStructInit(&TIM1_TimeBaseStructure);

TIM1_TimeBaseStructure.TIM_Prescaler = 0;

TIM1_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM1_TimeBaseStructure.TIM_Period = period;

TIM1_TimeBaseStructure.TIM_ClockDivision = 0;

TIM1_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStructure);



/* Channel 2 output configuration */

TIM_OCStructInit(&TIM1_OCInitStructure);

TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

TIM1_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

TIM1_OCInitStructure.TIM_Pulse = pulse2;

TIM1_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;

TIM1_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

TIM_OC2Init(TIM1, &TIM1_OCInitStructure);



/* Enable Preload register on CCR2. */

TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);



/* Channel 3 output configuration */

TIM1_OCInitStructure.TIM_Pulse = pulse1;

TIM1_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

TIM1_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

TIM_OC3Init(TIM1, &TIM1_OCInitStructure);



/* Enable Preload register on CCR3. */

TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);



// Setup dead time register (p-fet delay)

TIM_BDTRStructInit(&TIM1_BDTRInitStruct);

TIM1_BDTRInitStruct.TIM_DeadTime = 0U;

TIM_BDTRConfig(TIM1, &TIM1_BDTRInitStruct);



// Setup Timer 1 output compare Ch1 (Used for timer 3 clock source)

TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; // Timing mode only(no I/O output)

TIM1_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; // don't care

TIM1_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; // don't care

TIM1_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // don't care

TIM1_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // don't care

TIM1_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;

TIM1_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;

TIM1_OCInitStructure.TIM_Pulse = 1;

TIM_OC1Init(TIM1, &TIM1_OCInitStructure);

TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);

TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update); // Used to clock timer 3



// Setup Timer 3 to gate H-Bridge drive signals

TIM_TimeBaseStructInit(&TIM3_TimeBaseStructure);

TIM3_TimeBaseStructure.TIM_ClockDivision = 0;

TIM3_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM3_TimeBaseStructure.TIM_Period = 1; 

TIM3_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseInit(TIM3, &TIM3_TimeBaseStructure);

TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_External1); // Clock timer 3 via timer 1

TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR0); // drive timer 3 via timer 1

TIM_ARRPreloadConfig(TIM3, ENABLE); // Enable pre-load

TIM_SetAutoreload(TIM3, 1);



// Setup Timer 3 output compare 1 to load burst duration

TIM3_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; 

TIM3_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM3_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;

TIM3_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;

TIM3_OCInitStructure.TIM_Pulse = 1;

TIM_OC1Init(TIM3, &TIM3_OCInitStructure);



/* Enable Preload register on CCR1. */

TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);



// Enable DMA channel 2

DMA_Cmd(DMA1_Stream2, DISABLE);



// Enable DMA channel 4

DMA_Cmd(DMA1_Stream4, DISABLE);



// Setup DMA 1 stream 4 to modulate fet drive on/off

DMA_StructInit(&sDMAInitStructureTx);

sDMAInitStructureTx.DMA_Channel = DMA_Channel_5;

sDMAInitStructureTx.DMA_PeripheralBaseAddr = (uint32_t)&(tim1->BDTR);

sDMAInitStructureTx.DMA_BufferSize = 2;

sDMAInitStructureTx.DMA_DIR = DMA_DIR_MemoryToPeripheral;

sDMAInitStructureTx.DMA_Memory0BaseAddr = (uint32_t)gBurstEnable;

sDMAInitStructureTx.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

sDMAInitStructureTx.DMA_MemoryInc = DMA_MemoryInc_Enable;

sDMAInitStructureTx.DMA_Mode = DMA_Mode_Circular;



sDMAInitStructureTx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

sDMAInitStructureTx.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 

sDMAInitStructureTx.DMA_Priority = DMA_Priority_VeryHigh;



// Initialize DMA

DMA_DeInit(DMA1_Stream4);

DMA_Init(DMA1_Stream4, &sDMAInitStructureTx);



// Setup DMA 1 stream 2 to update burst table

DMA_StructInit(&sDMAInitStructureTx);

sDMAInitStructureTx.DMA_Channel = DMA_Channel_5;

sDMAInitStructureTx.DMA_PeripheralBaseAddr = (uint32_t)&(tim3->ARR);

sDMAInitStructureTx.DMA_BufferSize = 8;

sDMAInitStructureTx.DMA_DIR = DMA_DIR_MemoryToPeripheral;

sDMAInitStructureTx.DMA_Memory0BaseAddr = (uint32_t)TimeData;

sDMAInitStructureTx.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

sDMAInitStructureTx.DMA_MemoryInc = DMA_MemoryInc_Enable;

sDMAInitStructureTx.DMA_Mode = DMA_Mode_Circular;

sDMAInitStructureTx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

sDMAInitStructureTx.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 

sDMAInitStructureTx.DMA_Priority = DMA_Priority_VeryHigh;



// Initialize DMA

DMA_DeInit(DMA1_Stream2);

DMA_Init(DMA1_Stream2, &sDMAInitStructureTx);



// Enable Timer DMA request on update

TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);

TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);



/* TIM1 Main Output Enable */

TIM_CtrlPWMOutputs(TIM1, ENABLE);



/* TIM3 counter enable */

TIM_Cmd(TIM3, ENABLE);



/* TIM1 counter enable */

TIM_Cmd(TIM1, ENABLE);



// Enable DMA channel 2

DMA_Cmd(DMA1_Stream2, ENABLE);



// Enable DMA channel 4

DMA_Cmd(DMA1_Stream4, ENABLE);


/* forever... */

while (1) {

__asm(''nop'');

}

2 REPLIES 2
Posted on May 23, 2014 at 20:30

TIM1 is on APB2, you should perhaps be using DMA2?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mhage
Associate II
Posted on May 23, 2014 at 23:13

Worked like a charm.

Thanks Clive.