Page 1 of 1

ICU callback missed @ 5KHz?

Posted: Sat Nov 15, 2014 8:21 pm
by russian
I believe that some of my period callbacks on ICU driver are getting dropped with a square 50% wave 5KHz signal.

Code: Select all

static void shaft_icu_width_callback(ICUDriver *icup) {
   hwHandleShaftSignal(SHAFT_PRIMARY_UP);
}

static void shaft_icu_period_callback(ICUDriver *icup) {
   hwHandleShaftSignal(SHAFT_PRIMARY_DOWN);
}

void handleShaftSignal(trigger_event_e signal) {
    isMismatch  = (curSignal == prevSignal);
   if (isMismatch)
      orderingErrorCounter++;
   prevSignal = curSignal;
   curSignal = signal;

      uint64_t nowNt = getTimeNowNt();
      curDuration = prevTime - nowNt ;
      prevTime = curDuration;
}


curDuration is usually about 17000 native ticks which is the expected value considering 100uS event period and 168 ticks per uS. More or less once per 80 wave cycles on average I am getting two consecutive icu_width_callback which are ~34000 ticks apart. This looks like a missed period callback.

I am not getting missed callbacks with a 500Hz signal. I've checked and I am not getting reentrant ICU callbacks.

What could I be doing wrong? Are there any error or status registers related to this?

Re: ICU callback missed @ 5KHz?

Posted: Sat Nov 15, 2014 10:02 pm
by Giovanni
Do you have large critical zones? that could be a reason for that. The F4 should be able to handle interrupts in the range of few uS.

Giovanni

Re: ICU callback missed @ 5KHz?

Posted: Sat Nov 15, 2014 10:09 pm
by russian
Giovanni wrote:Do you have large critical zones? that could be a reason for that. The F4 should be able to handle interrupts in the range of few uS.

I am doing all I can to reduce the kernel lock mode zones, is that a synonym?

Are you saying that this is expected behavior that my IRQs are dropped? Can I at least know if/how many are being dropped? How do I guarantee IRQ handling since theoretically even a smallest kernel lock zone might happen at the wrong moment?

Re: ICU callback missed @ 5KHz?

Posted: Sat Nov 15, 2014 10:17 pm
by Giovanni
It is a symptom or something wrong, it could be a lock zone.

Note that IRQs are not "lost" when triggered during a critical zone, just delayed until the end of the critical zone, the only way to lose an interrupt is if the IRQ source is triggered again before the previous interrupts has been served.

Basically you need 2 instances of the same IRQ occurring during the same critical zone.

Another consequence is that it is not important to reduce the number of critical zones, you need to reduce the duration of the LARGEST one.

The ChibiOS 3.0 debug plugin is able to tell you the duration of the largest critical zone but currently is broken because changes I did in the kernel yesterday... you could use a previous SVN revision if you want to give it a try.

Giovanni

Re: ICU callback missed @ 5KHz?

Posted: Sat Nov 15, 2014 10:24 pm
by russian
Gotcha. Let me figure out the duration of the longest kernel lock mode zone and get back to you on this.

Are you using hal_lld_get_counter_value for these measurements in 3.0? How do you handle 32 bit overflow for that register - do you track overflow & track your own 64 bit version of this counter?

Re: ICU callback missed @ 5KHz?

Posted: Sat Nov 15, 2014 10:32 pm
by Giovanni
3.0 has a statistics subsystems that uses the RT counter, it is not important if it overflows, differences are calculated correctly even if the counter overflowed.

Giovanni

Re: ICU callback missed @ 5KHz?

Posted: Wed Nov 19, 2014 4:09 pm
by russian
Giovanni wrote:Basically you need 2 instances of the same IRQ occurring during the same critical zone.

Another consequence is that it is not important to reduce the number of critical zones, you need to reduce the duration of the LARGEST one.


Looks like this was my issue exactly. I've discovered that one of my critical zones was about 32K ticks (strlen + strcpy for a 8k logging buffer), once I've changed the implementation to eliminate this things have improved. Thank you for the hint what to look at :)

I've spend some time looking what sections of my code are taking how many ticks and I was surprised that for example 'strlen' invocation for a string of just three chars costs a bit over 100 ticks. Maybe one day I will find an explanation to that - is it the cost of branching, method invocation or debugger magic around method invocation.