cancel
Showing results for 
Search instead for 
Did you mean: 

TIM initialization ruins DMA transfers

eltar
Associate III
Posted on May 30, 2012 at 23:10

I've been trying to make a motor controller out of STM32VL-Discovery (STM32F100RB). However I wanted just to check the waveforms and decided I could do without additional hardware. I'm emulating Hall signal with TIM2+DMA+GPIO. And emulation works great untill I try to initialize TIM3 or TIM4 as an interface timer. When I call TIM_Init() function, Hall emulation forms get corrupted. This happens immediately after entering the function, no actions done. And the optimization level setting of the compiler makes difference for how exactly the form is corrupted. It looks like something is messing with DMA preventing it from setting GPIO bits properly.

I run CooCox IDE 1.4.2 with arm-none-eabi-gcc-4_6. Here's the code and illustrations:


int
main(
void
)

{

RCC_Configuration();

//SysTick_Config(SystemCoreClock / 1);

GPIO_Configuration();

TIM_Configuration ();

HallInterface_Configuration ();


while
(1)

{


}

}

next:


void
RCC_Configuration(
void
)

{

RCC_DeInit (); 
/* RCC system reset(for debug purpose)*/

RCC_HSEConfig (RCC_HSE_ON); 
/* Enable HSE */


/* Wait till HSE is ready */

while
(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);


RCC_HCLKConfig (RCC_SYSCLK_Div1); 
/* HCLK = SYSCLK */

RCC_PCLK2Config (RCC_HCLK_Div1); 
/* PCLK2 = HCLK */

RCC_PCLK1Config (RCC_HCLK_Div2); 
/* PCLK1 = HCLK/2 */

RCC_ADCCLKConfig (RCC_PCLK2_Div4); 
/* ADCCLK = PCLK2/4 */


/* PLLCLK = 8MHz * 3 = 72 MHz */

RCC_PLLConfig (0x00010000, RCC_PLLMul_3);


RCC_PLLCmd (ENABLE); 
/* Enable PLL */


/* Wait till PLL is ready */

while
(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);


/* Select PLL as system clock source */

RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);


/* Wait till PLL is used as system clock source */

while
(RCC_GetSYSCLKSource() != 0x08);

RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK);

}

next:


void
GPIO_Configuration(
void
)

{

/* Initialize Leds mounted on STM32 board */

GPIO_InitTypeDef GPIO_InitStructure;

/* Initialize LED which connected to PC6,9, Enable the Clock*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);


GPIO_DeInit(GPIOC);

/* Configure the GPIO_LED pin */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);


GPIO_ResetBits(GPIOC,GPIO_Pin_9);

}

next:


void
TIM_Configuration (
void
)

{

/**

* TIM2 mocks Hall sensors output by consequently generating DMA request

* to fetch from memory next state of three output pins

* HallU - PC10

* HallV - PC11

* HallW - PC12

*/

GPIO_InitTypeDef GPIO_InitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

DMA_InitTypeDef DMA_InitStructure;


const
uint32_t GPIO_PinsState[6] = {

134222848, 402654208, 268438528,

335546368, 67115008, 201330688 };


uint16_t FullCycleFreq = 1240; 
//Hz, 6 steps, full electrical rotation

uint16_t TimerFreq = FullCycleFreq * 6;

uint16_t TimerPeriod = (uint16_t)(SystemCoreClock/(TimerFreq + 1));


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);


GPIOC->BSRR = (1<<25)+(1<<24)+(1<<11);


RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);


DMA_DeInit(DMA1_Channel2);

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) GPIOC_BSRR_Address;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32) GPIO_PinsState;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;


DMA_InitStructure.DMA_BufferSize = 6;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;


DMA_Init(DMA1_Channel2, &DMA_InitStructure); 
//TIM2_UP = Channel2


DMA_Cmd(DMA1_Channel2, ENABLE);


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


TIM_TimeBaseStructure.TIM_Period = TimerPeriod;

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);



TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);


TIM_Cmd(TIM2, ENABLE);

}

All the way until here everything is great. User LEDs are not powered and the waveform looks exactly as I need it: 0690X00000602sFQAQ.jpg Then something strange happen:


void
InterfaceTimerSetup (
void
)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure1;

TIM_ICInitTypeDef TIM_ICInitStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

NVIC_InitTypeDef NVIC_InitStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);


TIM_TimeBaseStructure1.TIM_Prescaler = 12;
//126;

TIM_TimeBaseStructure1.TIM_CounterMode = TIM_CounterMode_Down;
//TIM_CounterMode_Up;

TIM_TimeBaseStructure1.TIM_Period = 1;
//65535;

TIM_TimeBaseStructure1.TIM_ClockDivision = 1;
//0;

TIM_TimeBaseStructure1.TIM_RepetitionCounter = 1;
//0;

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure1);


}

After this PC9 LED comes to life (constant high level) and the waveforme changes as follows: 0690X00000602xEQAQ.jpg Yellow line is PC I've tried to change interface timer to TIM3/4 - no matter. Changing optimization level changes more than one waveforms. Initing OC/IC changes more than one waveform. This is a complete mistery to me - please please please help me out. Thanks in advance #hall-sensors #dma #stm32f10x
1 REPLY 1
eltar
Associate III
Posted on August 18, 2012 at 12:08

Just in case someone stumbles upon same issue. The problem was in multiple peripherial initialization - in STM32 i guess you should start clocking each peripherials only once.