Skip to content

SysTick_Handler very likely to cause significant jitter in timing critical code #49

@mh-dm

Description

@mh-dm

SysTick_Handler very likely to cause significant jitter in timing critical code.

cores/arduino/main.cpp currently implements the handler as follows:

 __attribute__ ((weak)) void SysTick_Callback() {}
// [..]
volatile uint64_t _millis;
// [..]
    NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(0, 0, 0));
// [..]
  void SysTick_Handler(void) {
    ++_millis;
    SysTick_Callback();
  }

0 is the highest priority level which means SysTick_Handler is going to run regardless of anyone. This is absolutely fine if it was just incrementing _millis. But it's also providing that callback - which is a big footgun. At minimum it should come with warning (ideally at compile time) that it's running at the highest priority and to not use it for basically anything because it will interfere with the timing of absolutely every other interrupt. (Even a function call is probably too much but that's beside the point.)

Now for the real life example - Marlin firmware. Looking at Marlin/src/HAL/LPC1768/HAL.cpp, this is the problematic SysTick_Callback:

void SysTick_Callback() { disk_timerproc(); }

Where disk_timerproc() is actually from framework-arduino-lpc176x/system/CMSIS/lib/chanfs/mmc_ssp.c:

/*-----------------------------------------------------------------------*/
/* Device timer function                                                 */
/*-----------------------------------------------------------------------*/
/* This function must be called from timer interrupt routine in period
/  of 1 ms to generate card control timing.
*/
void disk_timerproc (void)

Now disk_timerproc() really doesn't do much (a rewrite just using _millis could get rid of the need for it to exist it in the first place but that's beside the point).

Here's a visual of the issue, namely those 6000mm/s^2 or more acceleration spikes when moving at a leisurely ~100mm/s:
jitter
The spikes are there even after I increased the priority of the stepper interrupt to the highest (0).

And to confirm that it's SysTick_Callback() I've commented it out completely, including definition and use. This is the result:
jitter_no

(Which also makes me wonder why disk_timerproc() exists. Everything, including read write to SD card seems to works fine without it existing. But again, that's beside the point.)

I'm also opening an issue on Marlin side to purge SysTick_Callback calls to actually fix the jitter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions