cancel
Showing results for 
Search instead for 
Did you mean: 

Systick, NVIC and how it can go all pear shaped...

nicholas2399
Associate II
Posted on July 12, 2012 at 13:10

Hi, hope someone can help with a little problem I have uncovered in my application.

I am using an STM32F103C8 in a small, custom board. I am not using any library code from any source.

I am using the SYSTICK counter as a 1ms tick, using the interrupt to increment a ''coarse'' time stamp counter.

I have other interrupts in the system, namely a timer, an SPI and a UART.

Under very specific scenario, ie timer, systick, uart occuring in that order but practically coincident (the systick may occur during the timer I can't tell, but the uart I think is happening afte systick), systick will fire a second time after the uart interrupt has completed. So I get a situation where it appears as thought the coarse time stamp has increment by 2 instead of 1.

The priorities are TIM2 - 0, SPI - 16, UART - 224 and SYSTICK 240 (note STM only uses top 4 bits of NVIC priority registers). I have set preemption/subgroup setting as 7.1 assuming that as STM doesn't use bottom four bits all interruprs can be pre-emptive.

This is very sensitive to timing (ie change optimisation problem goes away etc...)

Any ideas anyone?

BTW it is not enough to just fix this symptom, i need to understand the cause so as to decide on the severity of this bug for devices currently in the field

Nick

#nvic #bug #timing #systick
8 REPLIES 8
emalund
Associate III
Posted on July 12, 2012 at 15:41

first of all, the systick routine should be the highest priority and variable++; which is all you need should not 'kill' anything.

as far as what you se my GUESS is that what happens is that the UART interrupt the systick ISR in such a way/place that what you see happens..  not seeing your code this can only be a guess.

Erik

ps

..... SYSTICK 240 (note STM only uses top 4 bits of NVIC priority registers). is not easy to decipher why do you use decimal values when you are interested in bits of a byte, hex (0x00 .. 0xf0) would make it crystal clear,

pps I only know ''pear shaped'' as a type of female body, what does that have to do with your code?

frankmeyer9
Associate II
Posted on July 12, 2012 at 16:09

The Systick is at least listed as having configurable priority, so I see no principal reason why it should not work.

Can you assure that the systick code really misbehaves, i.e. counts twice, if it gets preempted ?

Normally, it should just continue where it was, before the higher-priority interrupt arrived.

Otherwise, you might need to make the counter incrementing atomic.

nicholas2399
Associate II
Posted on July 12, 2012 at 16:44

OK I have been able to determine the following

The first systick interrupt occurs as one would expect (I have modified my code to include a check for COUNTFLAG==1). The interrupt routine appears to exit and then my uart int starts within 10-20 cycles. I have added a test at this point to check the SYSTICK Pending flag and it is SET (I would not expect this - it should be reset). After the uart int has finished, systick int runs again and COUNTFLAG is 0 showing that the interrupt was not caused by a count underun...

It strikes me that something is stopping the pending flag from being reset properly.

To make matters more complicated - this only occurs when the first systick is initially pre-empted by another higher priority (timer) interrupt, so i assume it is entered using the ''tailchaining'' mechanism...

Nick

''going pear shaped'' is a term describing when everything goes wrong...

frankmeyer9
Associate II
Posted on July 12, 2012 at 17:24

The ARM Users Guide describes Systick not as interrupt per se, but as exception.

Further, it describes the registers, but no pending flag to clear.

Thus, one might dig in the vendors manuals, which are the ST reference manuals in this case.

I use the systick quite frequently, but never messed with it's priority, so I never came across this issue. But according your description, it sounds like the systick timer is actually misbehaving.

''going pear shaped'' is a term describing when everything goes wrong...

 

And again something learned...

emalund
Associate III
Posted on July 12, 2012 at 17:51

I use the systick quite frequently, but never messed with it's priority, so I never came across this issue. But according your description, it sounds like the systick timer is actually misbehaving.

 

so do I and I never came across this issue. as well.

3 possibilities

a) as I described before, if the OP would publish his systick ISR I might be able to go beyond guessing.

b) since the systick is set at the lowest priority, the time to process a confluence of interrupts is more than the 1ms the systick is set at

.c) systick timer is, indeed, misbehaving. I doubt it, but if it is I can easily see nobody even dreaming of testing it an any priority than the highest. It is difficult to imagine any other priority, but, evidently, the OP has.

Erik
Posted on July 12, 2012 at 18:03

The USART interrupt code might be instructive too.

I'm not aware of a condition where SYSTICK will re-enter spuriously. Regular interrupts can if the last thing you do is clear the source, a combination of the pipelining, and write buffers and how the data propagates across the APB and when the NVIC decides what's still pending, can result in the same interrupt tail-chaining for a second time only to observe that no interrupt status is pending.

http://www.urbandictionary.com/define.php?term=pear+shaped

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
nicholas2399
Associate II
Posted on July 12, 2012 at 18:14

oke doke

here is my ISR code:

void SYSTIMER_IRQHANDLER(void)

{

    // manually clear the pending bit for this interrupt

//    SCB->IRQControlState = 0x02000000;

TP_ON(1);

   // increment the coarse time stamp counter

    CoarseTimeStamp++;

    // Set a flag for the background loop to process the Timer Task Queue

    bSystemTickFired = true;

    if ((SCB->IRQControlState & 0x04000000) == 0x04000000)

    {

        TP_OFF(1);

        TP_ON(1);

    }

TP_OFF(1);

}

The TP_ON and TP_OFF macros simply switch a GPIO output so I can monitor with a scope.

if ((SCB->IRQControlState & 0x04000000) == 0x04000000) is checking current condition of the SYSTICK pending flag

and

//    SCB->IRQControlState = 0x02000000;

will be my work around (clears the pending flag)

No combination of interrupts in the code could consume anyway near 1ms at most 10us.

(brave statement but i believe this to be the case - indeed if it isn't i have bigger problems than this!)

The confusing thing about this is that it seems to require a pre-cursor event (the timer interrupt during which the systick becomes pending) but also requires that the systick interrupt is followed by the uart interrupt (though due to limitations of my system this could be any other interrupt, i just can't cause other interrupts to fire at the appropriate time).

The reason i have systick as a low priority is that within my system reacting to a low resolution timing strobe is not critical, but reacting to other events such as SPI and Timer is extremley critical...

Thanks for all your thoughts

Nick

nfoss
Associate
Posted on January 25, 2016 at 13:43

Hi All,

I know that this is an old post but but did anyone ever find a solution?

I'm seeing exactly the same problem on a different processor

Thanks,

Neil