Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STM32 µC: SysTick delay doesn't work inside interrupt handler [closed]

So I wrote a program for the STM32F103C8T6 microcontroller in C, using the RTC (Real Time Clock) and a display module.

The RTC and the display both work fine, but when I try to update the display from inside the RTC interrupt handler, it doesn't work.

When I write something to the display from within the main(), it works just fine.

The interrupt handler works as well, so I figured that the problem lied within the function that writes to the display.

This function uses small delays to bit-bang the communication with the display controller.

I previously used the SysTick to generate the delays like this:

void delay(uint32_t n){
    uint32_t start =  systick_count;
    while (systick_count - start < n);
    return;
}

But somehow, inside the interrupt handler of the RTC it doesn't work. So I replaced my delay function with this one, not using the SysTick:

for (; i>0; i--) {
    for (int j = 0; j < 72; ++j) {
        __asm__ __volatile__("nop\n\t":::"memory");
    }
}

and now everything works just fine.

I'm trying to understand, why the SysTick apparently doesn't work inside the RTC interrupt handler.

I figured that maybe it's caused by the Interrupt priorities, but according to the datasheet, by default the SysTick Interrupt's priority is higher than the RTC interrupts priority.

Maybe someone can explain, why this happens?

EDIT1: Ok, so I’ve read a bit more about the interrupt priorities, and it seems that i need to configure the NVIC_IRQChannelPreemptionPriority correctly. I’ll try this as soon as I can...

With regard to the delay inside the interrupt, I know that's not the right way to do It, but I still wanted to understand the program's behaviour

EDIT2: I just tried changing the interrupt priorities in the following way:

// set RTC interrupt priority to 15 (lowest)
NVIC_SetPriority(RTC_IRQn, 15);
// set interrupt priority of SysTick to 0 (highest)
NVIC_SetPriority(SysTick_IRQn, 0);

and now the SysTick delay works within the RTC interrupt handler.

like image 727
Marcel Avatar asked Mar 06 '23 10:03

Marcel


1 Answers

Your way of implementing delay using SysTick is the same as HAL_Delay in HAL library coming from ST. The way it works is that SysTick continually increments (typically in 1ms intervals) a variable - systick_count in your case - that is compared against a local variable inside delay function - start in your case.

Two things to note here:

  1. systick_count needs to be made volatile to force re-reading of its value before each comparison. It's modified by interrupt and not inside that function. Your compiler may choose to optimize this portion of the code.

  2. The SysTick interrupt needs to be "running" when the delay function is called. If it's not e.g. because you're in a higher priority (numerically lower) interrupt, then you're in a deadlock and the delay function will never finish because the counter will never be incremented by SysTick that never happens. Regarding this point - don't assume things and rely just on the datasheet. Go ahead and actually verify that it's running while in delay. Either check NVIC register values at the moment of calling the delay function or simply set a breakpoint in SysTick while you're in the RTC interrupt - it should hit that breakpoint while you're in the delay function. If it doesn't- you probably need to adjust interrupt priorities.

Regarding the whole idea of putting a delay in your interrupts - it is generally considered bad practice. Interrupts are supposed to be used to do very small portions of work very quickly such as setting a flag that something needs to be done in the main program code or putting received byte in a queue for later processing. While this may not seem obvious in a simple program where you only have one interrupt (two if you count Systick), it'll very quickly become problematic once you add more interrupts and will run into issues such as losing information because your interrupts block each other and they don't get called quickly enough.

like image 154
Jacek Ślimok Avatar answered Mar 10 '23 11:03

Jacek Ślimok