Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ChibiOS timer fixes #16017

Merged
merged 4 commits into from
Feb 4, 2022
Merged

ChibiOS timer fixes #16017

merged 4 commits into from
Feb 4, 2022

Commits on Jan 23, 2022

  1. chibios/timer: Move the 16-bit timer handling into a separate function

    Extract the code which effectively makes a 32-bit tick counter from a
    possibly 16-bit ChibiOS system timer into a separate function.  Does
    not really change the behavior of the timer API, but makes the actions
    done in `timer_clear()` and `timer_read32()` more obvious.
    sigprof committed Jan 23, 2022
    Configuration menu
    Copy the full SHA
    a4e5a24 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    ca5ef66 View commit details
    Browse the repository at this point in the history
  3. chibios/timer: Fix 32-bit tick counter overflow handling

    The QMK timer API implementation for ChibiOS used a 32-bit tick counter
    (obtained from the ChibiOS system timer) and then converted the value to
    milliseconds to produce the timer value for QMK.  However, the frequency
    of the ChibiOS timer is above 1000 Hz in most cases (values of 10000 Hz
    or even 100000 Hz are typically used), and therefore the 32-bit tick
    counter was overflowing and wrapping around much earlier than expected
    (after about 5 days for 10000 Hz, or about 12 hours for 100000 Hz).
    When this wraparound happened, the QMK timer value was jumping back to
    zero, which broke various code dealing with timers (e.g., deferred
    executors).
    
    Just making the tick counter 64-bit to avoid the overflow is not a good
    solution, because the ChibiOS code which performs the conversion from
    ticks to milliseconds may encounter overflows when handling a 64-bit
    value.  Adjusting just the value converted to milliseconds to account
    for lost 2**32 ticks is also not possible, because 2**32 ticks may not
    correspond to an integer number of milliseconds.  Therefore the tick
    counter overflow is handled as follows:
    
      - A reasonably large number of ticks (the highest multiple of the
        ChibiOS timer frequency that fits into uint32_t) is subtracted from
        the tick counter, so that its value is again brought below 2**32.
        The subtracted value is chosen so that it would correspond to an
        integer number of seconds, therefore it could be converted to
        milliseconds without any loss of precision.
    
      - The equivalent number of milliseconds is then added to the converted
        QMK timer value, so that the QMK timer continues to count
        milliseconds as it was before the tick counter overflow.
    sigprof committed Jan 23, 2022
    Configuration menu
    Copy the full SHA
    a913e95 View commit details
    Browse the repository at this point in the history
  4. chibios/timer: Add a virtual timer to make 16-bit timer updates more …

    …reliable
    
    The code which extends the 16-bit ChibiOS system timer to a 32-bit tick
    counter requires that it is called at least once for every overflow of
    the system timer (otherwise the tick counter can skip one or more
    overflow periods).  Normally this requirement is satisfied just from
    various parts of QMK code reading the current timer value; however, in
    some rare circumstances the QMK code may be blocked waiting for some
    event, and when this situation is combined with having a rather high
    timer frequency, this may result in improper timekeeping.
    
    Enhance the timer reliability by adding a ChibiOS virtual timer which
    invokes a callback every half of the timer overflow period.  The virtual
    timer callback can be invoked even when the normal QMK code is blocked;
    the only requirement is that the timer interrupts are enabled, and the
    ChibiOS kernel is not locked for an excessive time (but the timer update
    will eventually work correctly if the virtual timer handling is not
    delayed by more than a half of the timer overflow period).
    
    Keeping a virtual timer always active also works around a ChibiOS bug
    that can manifest with a 16-bit system timer and a relatively high timer
    frequency: when all active virtual timers have delays longer than the
    timer overflow period, the handling of virtual timers stops completely.
    In QMK this bug can result in a `wait_ms()` call with a delay larger
    than the timer overflow period just hanging indefinitely.  However, when
    the timer update code adds a virtual timer with a shorter delay, all
    other virtual timers are also handled properly.
    sigprof committed Jan 23, 2022
    Configuration menu
    Copy the full SHA
    6f4d09d View commit details
    Browse the repository at this point in the history