Skip to content

EventQueue timing errors when using tickless mode #13801

Closed
@marcemmers

Description

@marcemmers

Description of defect

We have recently been experiencing issues with the timing of the EventQueue since switching to mbed 6.1.0 from 5.12.0. After some testing we have found out that the issue originates from the equeue_tick function is equeue_mbed.cpp. This gets the ticks from a different source if its called from an interrupt context (but only in tickless mode).

When debugging we halt the execution when it lands on main or on a breakpoint. While the core is halted the kernel clock is no longer updated but the rtc peripheral is still running. When we start or continue the program the rtc clock now is ahead of the kernel clock. If an event is posted to the queue in interrupt context, the tick count is also read in interrupt context from the rtc clock, so the wakeup time for that event is ahead of the kernel time which is used to determine the next wakeup event. This leads to a delay in event handling. The delay is proportionate to the time spent halted.

I've tried searching for an easy solution but I couldn't find one. In my opinion there should be only one timebase used for the eventqueue ticks but that's easier said then done. The kernel clock gets updated after the interrupts have been handled and its not that easy to update it while still in the critical sleep section.

There is an issue on the forum which looks to be the same issue: https://forums.mbed.com/t/eventqueue-call-target-method-triggers-much-later-than-expected/10163. It was "solved" by disabling tickless mode but that is not an option for us.

Target(s) affected by this defect ?

NRF52840 and probably NUCLEO_L476RG

Toolchain(s) (name and version) displaying this defect ?

IAR 8.32.3

What version of Mbed-os are you using (tag or sha) ?

mbed-os-6.1.0

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

n/a

How is this defect reproduced ?

The code from the forum should reproduce this issue. I don't know if it is necessary to halt execution for a while to reproduce the issue.

#include "mbed.h"

InterruptIn btnInt(BUTTON1);                     

Thread thread_eq_events;        
EventQueue eq_events;
volatile int isrCallTime;

Timer timer;

void event_function_periodic()
{
    printf("[DEBUG - event_function_periodic] at %d ms\n", timer.read_ms());
}

void event_function_interrupt_handler(bool state)
{
    printf("[DEBUG - event_function_interrupt_handler] delayed (deferred) by %d ms (%s)\n", timer.read_ms() - isrCallTime, state ? "L->H" : "H->L");
}

void btn_interrupt_handler()
{
    isrCallTime = timer.read_ms();
    eq_events.call(&event_function_interrupt_handler, btnInt.read());
}

//////////
// MAIN //
//////////
int main()
{
    eq_events.call_every(1000, &event_function_periodic);                               
    
    btnInt.rise(&btn_interrupt_handler);
    btnInt.fall(&btn_interrupt_handler);
    
    thread_eq_events.start(callback(&eq_events, &EventQueue::dispatch_forever));

    timer.start(); 
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions