2013-07-18 06:47 AM
Hi,
I have a problem where I cannot get a higher priority interrupt to interrupt a lower priority one. My understanding is that this should 'just work' so I'd really appreciate your input on this... I've created a basic example which is designed to run on the STM32VLDISCOVERY board, but I've had the same issue with the F4 (and I imagine I would on other chips too)In the example, LED1 is flashed slowly by the SysTick interrupt, and LED2 is flashed by the main loop.
Expected outcome
When BTN1 is pressed, the EXTI0 interrupt is called, it flashes LED2 quickly until the higher priority SysTick interrupt is fired, and then it exits. The LED1 keeps on flashing as before.
Actual outcome
When BTN1 is pressed, the EXTI0 interrupt is called, it flashes LED2 quickly. The higher priority SysTick interrupt is never fired, LED1 never flashes and the LED2 continues to blink quickly.
#include ''stm32f10x.h''
typedef
char bool ; volatile bool toggle;void
delay( void ) { volatile int i = 100000; while (i-- > 0) { } } void delaySlow( void ) { volatile int i = 1000000; while (i-- > 0) { } }// Toggle LED1 on SysTick
void SysTick_Handler( void ) { if (toggle = !toggle) GPIO_SetBits(GPIOC, GPIO_Pin_8); else GPIO_ResetBits(GPIOC, GPIO_Pin_8); }// On EXTI IRQ, flash LED2 quickly, and wait for a SysTick
void EXTI0_IRQHandler( void ) { bool lastToggle = toggle; GPIO_SetBits(GPIOC, GPIO_Pin_9); while (lastToggle==toggle) { // wait for systick // Flash LED2 slowly GPIO_SetBits(GPIOC, GPIO_Pin_9); delay(); GPIO_ResetBits(GPIOC, GPIO_Pin_9); delay(); } GPIO_ResetBits(GPIOC, GPIO_Pin_9);EXTI_ClearITPendingBit(EXTI_Line0);
}int
main( void ){ GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE); // set preemption NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure); // button GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // leds GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); // systick SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); SysTick_Config(0xFFFFFF); // 24 bit NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Highest priority NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // exti 0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; // Lowest priority NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_Init(&NVIC_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); EXTI_InitTypeDef s; EXTI_StructInit(&s); s.EXTI_Line = EXTI_Line0; s.EXTI_Mode = EXTI_Mode_Interrupt; s.EXTI_Trigger = EXTI_Trigger_Rising; s.EXTI_LineCmd = ENABLE; EXTI_Init(&s);while
(1) { // Flash LED2 slowly GPIO_SetBits(GPIOC, GPIO_Pin_9); delaySlow(); GPIO_ResetBits(GPIOC, GPIO_Pin_9); delaySlow(); } }2013-07-18 07:10 AM
Observations :
There are only 4-bits to share between preemption/priority, you define how to split them. Setting F/F doesn't really seem valid. SysTick is not an ''Interrupt'' in the sense you want it to be, it's a ''System Handler'', SysTick_IRQn will be negative, and you don't use NVIC_Init() to set it up. On the F2/F4 you'd use NVIC_SetPriority(SysTick_IRQn, SysTickPriority); It's also critical to do this AFTER SysTick_Config(), as this messes with the priority.2013-07-18 07:49 AM
Hi Clive,
Thanks, that's perfect! Using NVIC_SetPriority solved it!I wasn't actually aware that SysTick was that special - I checked the docs to make sure I could set priority, but I should have looked a bit more closely!It's crazy really as NVIC_Init does the same thing (ish) if the IRQn>=0. It has all the usual assert_params in, but it DOESN'T assert that it's been given the right IRQ. Ahh well.I guess it should have thrown up a signed to unsigned conversion warning but I must have missed that.(As for the two Fs - I was just playing safe. I wanted to be absolutely sure it was the lowest priority!)Thanks again,- Gordon2013-07-18 08:13 AM
It's one of those Cortex-Mx traps, the demarcation moved a little with the introduction of the CMSIS libraries. The original STM32F1xx libraries had ST specific NVIC and SYSTICK files.
2015-05-11 02:16 AM
Hello,
I've very similar problem, but without any good results on STM32L100RCT6. I want TIM3 to be higher priority interrupt than USART1. I've set priority group to 4 (NVIC_PriorityGroup_4) and configure priority of timer and usart like this:
void
timer3_init()
{
/* other code */
NVIC_SetPriority(TIM3_IRQn, 0);
NVIC_EnableIRQ (TIM3_IRQn);
timer3_int.NVIC_IRQChannel = TIM3_IRQn;
timer3_int.NVIC_IRQChannelPreemptionPriority = 0;
timer3_int.NVIC_IRQChannelSubPriority = 0;
timer3_int.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&timer3_int);
/* other code */
}
void
init_usart_RXint()
{
/* other code */
NVIC_SetPriority(USARTx_IRQn, 4);
NVIC_EnableIRQ(USARTx_IRQn);
NVIC_InitStructure.NVIC_IRQChannel = USARTx_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* other code */
}
void
main()
{
/* i configured NVIC priority group in main and then call TIM and USART functions */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
timer3_init();
init_usart_RXint();
/* other code */
}
I'm using:
- KEIL MDK-Middleware 5.1.6,
- CMSIS: 3.4
- STM32L1xx_DFP 1.0.2
-STM32L1xx Standard Peripherals Library Drivers V1.3.1
Can you see where I'm making mistake? I do get interrupt from both sources(TIM3 and USART), but TIM3 doesn't nest into USART interrupt like it should. [I've got USART interrupt handler, where I call function that waits for TIM3 interrupt, but this interrupt never happens so uC ir stuck in that while loop.]
Any help would be appreciated.
Thank you!
2015-05-11 03:25 AM
You selected NVIC_PriorityGroup_4 which does not leave any space for preemption (all 4 bits go to sub-priority). Change the group to NVIC_PriorityGroup_2 which will leave you 2 bits (values 0-3) for preemption and another 2 bits for subpriorities for each preemption priority. And change the priority values accordingly.
2015-05-11 02:43 PM
This is copied from misc.c file:
/**
* @brief Configures the priority grouping: preemption priority and subpriority.
* @param NVIC_PriorityGroup: specifies the priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PriorityGroup_0: 0 bits for preemption priority
* 4 bits for subpriority.
* @note When NVIC_PriorityGroup_0 is selected, it will no be any nested
* interrupt. This interrupts priority is managed only with subpriority.
* @arg NVIC_PriorityGroup_1: 1 bits for preemption priority.
* 3 bits for subpriority.
* @arg NVIC_PriorityGroup_2: 2 bits for preemption priority.
* 2 bits for subpriority.
* @arg NVIC_PriorityGroup_3: 3 bits for preemption priority.
* 1 bits for subpriority.
* @arg NVIC_PriorityGroup_4: 4 bits for preemption priority.
* 0 bits for subpriority.
* @retval None
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
Anyway, just couple of minutes ago I figured it out - another interrupt priority was missing - I was so focused on these two interrupts, that I just didn't see the third oneonce these two were set correctly. In order to control priorities of all interrupts, systick must also be configured withNVIC_SetPriority(). I've had small delay at the and of the function and USART interrupt was higher priority than systick.
Thanks for quick response anyway.