2018-12-17 07:33 AM
Hello everyone,
I am facing a issue I can't explain.
I am migrating a code from F1 to F2.
I am using UART4. If I only use this peripheral I can send and receive data and everything work well.
Then I am using a the TIM6 to have a 2ms counter.
In the IRQ of the timer I only do this (minimal code to find the bug).
void TIMER_LCD_IRQHandler(void)
{
if (TIM_GetITStatus(TIMER_LCD, TIM_IT_Update) != RESET)
{
TIM_Cmd(TIMER_LCD, DISABLE);
TIM_ClearITPendingBit(TIMER_LCD, TIM_IT_Update);
TIM_Cmd(TIMER_LCD, ENABLE);
}
}
Now with this activation I am loosing data in UART reception. If I comment the TIM_Cmd line everything work well.
This code is working well on the STM32F1. But on the STM32F2 from time to time I loose some data from my UART reception (throught interrupt).
I don't understand the issue because there is no interraction between those 2 peripheral.
I guess I'm missing something about the interrupts.
Does someone have an idea of what the issue could be ?
Thank you for your help !
2018-12-17 07:56 AM
>>Does someone have an idea of what the issue could be ?
You're interrupting too frequently? >= 250 KHz perhaps?
Don't see TIM initialization, hard to guess. 2ms (500 Hz) should be fine, but is that what you've configured?
2018-12-17 08:01 AM
Is there any other interrupt enabled for the timer's IRQ handler besides the TIM_IT_Update? Maybe something else is firing, and you don't clear its pending bit, and it keeps firing.
Also make the UART interrupt priority higher (lower number), with pre-emption.
2018-12-17 08:06 AM
Thank you for your answer Clive.
Here is the timer configuration for 2ms (I check at the oscilloscope and the period is 2ms):
#define TIMER_LCD TIM6
#define TIMER_LCD_IRQn TIM6_DAC_IRQn
#define TIMER_LCD_IRQHandler TIM6_DAC_IRQHandler
#define TIMER_LCD_PRIORITY 2
#define TIMER_LCD_NB_MS 2
#define TIMER_LCD_PULSE_PER_MS 4375
#define TIMER_LCD_PRESCALER 13
#define TIMER_LCD_ENABLE_IT TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE)
void TIMER_LCD_init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6 , ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIMER_LCD_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMER_LCD_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = TIMER_LCD_PULSE_PER_MS * TIMER_LCD_NB_MS;
TIM_TimeBaseStructure.TIM_Prescaler = TIMER_LCD_PRESCALER;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseInit(TIMER_LCD, &TIM_TimeBaseStructure);
/* TIM enable counter */
TIM_Cmd(TIMER_LCD, ENABLE);
/* TIM IT enable */
TIMER_LCD_ENABLE_IT;
}
2018-12-17 08:11 AM
Thank you for your answer Clive.
Here is the timer configuration for 2ms (I check at the oscilloscope and the period is 2ms):
#define TIMER_LCD TIM6
#define TIMER_LCD_IRQn TIM6_DAC_IRQn
#define TIMER_LCD_IRQHandler TIM6_DAC_IRQHandler
#define TIMER_LCD_PRIORITY 2
#define TIMER_LCD_NB_MS 2
#define TIMER_LCD_PULSE_PER_MS 4375
#define TIMER_LCD_PRESCALER 13
#define TIMER_LCD_ENABLE_IT TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE)
void TIMER_LCD_init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6 , ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIMER_LCD_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TIMER_LCD_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = TIMER_LCD_PULSE_PER_MS * TIMER_LCD_NB_MS;
TIM_TimeBaseStructure.TIM_Prescaler = TIMER_LCD_PRESCALER;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseInit(TIMER_LCD, &TIM_TimeBaseStructure);
/* TIM enable counter */
TIM_Cmd(TIMER_LCD, ENABLE);
/* TIM IT enable */
TIMER_LCD_ENABLE_IT;
}
2018-12-17 08:18 AM
Thank you for your answer.
There is no other interrupts enabled.
Concerning the priority I could change it to get the UART interrupt triggering first. But on the F1 with those priority there is no problem.
2018-12-17 08:57 AM
Are you using C++ or .cpp files?
Might want to clear the local/auto variables, and check the math on the dividers, don't know the clock speeds here.
Don't do work in the interrupt that blocks.
Set the USART preemption level higher (lower number), and make sure the NVIC group setting is splitting priority/preemption usefully.
extern "C" void TIMER_LCD_IRQHandler(void)
{
if (TIM_GetITStatus(TIMER_LCD, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIMER_LCD, TIM_IT_Update);
// Do work that takes a few microseconds here
}
}
2018-12-18 12:19 AM
I am using C files. The APB2 Clock is 60MHz.
In the interrupt block I do only what I post (Disable clear Enable)
The thing I don't understand is the exact same code work on a F1 and don't on the F2
2018-12-23 12:04 PM
F1 and F2 have generation difference, for example the way to program the alternate functions in GPIO is very much different. The USART RX interrupt should have the priority over the other sources. Use 2 GPIO to check how long last each interrupt and look at their timings. Maybe something is bogus... an oscilloscope for debugging is advised.
2018-12-23 12:48 PM
60,000,000 / 14 / 8751 = 489.74 Hz or 2.0419 ms ... close enough
60,000,000 / 40 / 3000 = 500 Hz
Prescaler = 40-1;
Period = 3000-1;
I would expect the IRQ Handler code I showed about, if you added a pin toggle, would generate an ~250 Hz signal on the scope.
If it doesn't then something else is amiss in the system. I'd recommend outputting data via a USART, and printing out the SystemCoreClock and the AHB/APB2/APB1 clock settings.