2014-03-11 12:52 AM
Hello
I am trying to configure a timer to get interruption at 12 MHz on the STM32F429 Discovery Kit.I am currently using TIM2 and I cannot reach more than 2.25 MHzTheoritically I could reach 45MHz right?Thank you for helping me.&sharpinclude <stm32f4xx_gpio.h>&sharpinclude <stm32f4xx_tim.h>&sharpinclude <stm32f4xx_rcc.h>&sharpinclude <misc.h>void InitializeTimer(){ TIM_TimeBaseInitTypeDef timerInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); timerInitStructure.TIM_Prescaler = 1; timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; timerInitStructure.TIM_Period = 1; timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; timerInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &timerInitStructure); TIM_Cmd(TIM2, ENABLE); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);}void EnableTimerInterrupt(){ NVIC_InitTypeDef nvicStructure; nvicStructure.NVIC_IRQChannel = TIM2_IRQn; nvicStructure.NVIC_IRQChannelPreemptionPriority = 0; nvicStructure.NVIC_IRQChannelSubPriority = 1; nvicStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvicStructure);}void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);}void TIM2_IRQHandler(void){ if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){ TIM_ClearITPendingBit(TIM2, TIM_IT_Update); GPIO_ToggleBits(GPIOC, GPIO_Pin_8); }}/** * @brief Main program * @param None * @retval None */int main(void){ GPIO_Configuration(); InitializeTimer(); EnableTimerInterrupt(); while (1) { }} #interrupt #timer #stm32f4292014-03-11 01:10 AM
> Theoritically I could reach 45MHz right?
No. For those who came from the 8-bit world, the ARM interrupts appear very costly in terms of machine clocks, as they automatically push/pop to/from stack a bunch of registers upon interrupt entry/exit. From the Cortex-M4 Technical Reference Manual: - There is a maximum of a twelve cycle latency from asserting the interrupt to execution of the first instruction of the ISR when the memory being accessed has no wait states being applied. [...] - Returns from interrupts similarly take twelve cycles [...] Review basic ARM literature. In addition, the C compiler adds some ISR entry/exit code (prologue/epilogue), and in the mcus where the processor core runs at speeds higher than the FLASH speed is, it's very likely that invocation of an ISR will involve FLASH reading latency, too. All in all, for high-speed operations, you are bound to use hardware. JW2014-03-11 01:17 AM
Highly impractical to generate interrupts this fast, processor will quickly saturate.
Want to toggle signals fast, or generate frequency outputs, let the TIM hardware do it, that's what it's designed to do, use the processor to do useful things, not mindless stuff better to suited to logic implementation.2014-03-11 01:46 AM
Ok thank you clive1 and JW for your quick answers. Sorry if I miss the basics, I am still a student!
Actually I was trying to do that to generate the quadrature of a signal at 6Mbits/s on the USART1 (by waiting 1/12MHz and copy the state of the pin where the signal is generate). Do you have an idea how I can do this at this baudrate?2014-03-11 02:20 AM
Yeah, I'm not clear what the purpose of doing that with the USART is.
I can generate quadrature (90 phase shifted) square waves with the TIM using two channels and toggle mode, with the phase shift inferred using the Pulse/CCRx setting.2014-03-11 02:44 AM
I have seen some code to generate square waves and its quadrature, thank you.
But I need to generate the quadrature of a signal sent by serial communication at 6Mbits/s (so it's not square wave, but ''random'' because its data coming from sensors).My first idea was, that on each edge of the Tx line, I generate an interruption, read and memorize the state of the Tx, start the timer, and copy the previous state on another pin :void EXTI0_IRQHandler(void){ if(EXTI_GetITStatus(EXTI_Line0) != RESET) { BitVal_Tx= (GPIOA->IDR & GPIO_Pin_0); TIM2->CNT=0; TIM_Cmd(TIM2, ENABLE); /* Clear the EXTI line 0 pending bit */ EXTI_ClearITPendingBit(EXTI_Line0); }}void TIM2_IRQHandler(void){ if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){ TIM_Cmd(TIM2, DISABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); GPIO_WriteBit(GPIOC, GPIO_Pin_8,BitVal_Tx); }}This works at 500,000 baud, but not higher (because I cannot generate interruptions faster with the timer).2014-03-11 03:07 AM
If I were compelled to use the USART to do this, I'd stick a delay line (shift register) externally.
You're not going to solve this with interrupts. I'd probably attack it using TIM -> DMA -> GPIO[2] clocking patterns at 4x rate. At 6 Mbps you really should be doing it in your own hardware implementation, FPGA/CPLD2014-03-11 03:40 AM
Maybe, in one of the timers, the input capture filter could be (ab)used to yield the required delay; then use it as both-edge clock source through the slave mode controller, finally output it on a different channel set to a ''degenerate'' PWM with ARR=1...? But I'm lazy to work out the details.
JW