Coder Social home page Coder Social logo

lptim-tick's Introduction

LPTIM-Tick

FreeRTOS Tick/Tickless via LPTIM

Use LPTIM for the FreeRTOS tick instead of the SysTick Timer for ultra-low-power applications.

  • No drift or slippage in kernel time
  • Use STOP modes even while FreeRTOS timers are running or delays are underway
  • For any STM32 with LPTIM (STM32L, STM32F, STM32G, STM32H, STM32U, STM32W)

This repository demonstrates integration and testing of the lptimTick.c gist on Nucleo-L476RG (STM32L476). The project uses STM32CubeIDE and its integrated code-generation tool (STM32CubeMX). However, lptimTick.c is compatible with any toolchain supported by FreeRTOS.

A separate repository, LPTIM-Tick-U5, is adapted to the STM32U family.

For a thorough evaluation, this project can be built without tickless idle, with the default tickless idle, or with the custom tickless idle provided by lptimTick.c. See branches for additional evaluation options.


Nucleo-L476RG Demo

Press the blue button to cycle between tests:

  1. Maintain kernel time only. LED blinks every 5 seconds.
  2. Validate tick timing. LED blinks every 2 seconds.
  3. Stress test tick timing. LED blinks every second.

Tests 2 and 3 display live test results to a serial terminal. Connect to the STLink Virtual COM Port at 115200 8N1. Additionally, the LED blinks twice (instead of just once) in case of test failure.

Test Results

Current readings shown are averages, not including the LED

With lptimTick.c (configUSE_TICKLESS_IDLE 2)

  • Test 1: 2μA, no drift
  • Test 2: 55μA, no drift
  • Test 3: 110μA, no drift

Default tickless idle (configUSE_TICKLESS_IDLE 1)

  • Test 1: 3.70mA, trivial drift
  • Test 2: 3.72mA, trivial drift
  • Test 3: 3.74mA, trivial drift (with kernel v10.5.1 or newer)

Tickless disabled (configUSE_TICKLESS_IDLE 0)

  • Test 1: 9.86mA, no drift
  • Test 2: 9.86mA, no drift
  • Test 3: 9.86mA, no drift

Integrating lptimTick.c into your project

  1. Add lptimTick.c to your project folder, configuration, and/or makefile.
  2. In FreeRTOSConfig.h, define configUSE_TICKLESS_IDLE to 2, and eliminate the preprocessor definition for xPortSysTickHandler. If using LSI instead of LSE, define configTICK_USES_LSI and configLPTIM_REF_CLOCK_HZ (typically 32000 or 37000), too.
  3. Update the #include for your MCU.
  4. Update the LPTIM instance selection. (For STM32WL users, here too.) LPTIM1 is the default.
  5. Update the initialization code that is specific to both the MCU family and the LPTIM instance.

lptim-tick's People

Contributors

jefftenney avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

nbrunner efthym

lptim-tick's Issues

Need Demonstration of STOP Mode

The project needs to demonstrate how to use STOP modes. The application should

  • Allow the user to control use of STOP mode at runtime to facilitate comparisons in power consumption
  • Provide an example framework for automatic use of STOP mode whenever application conditions allow
  • Implement a soak test that generates interrupts at varying times in a repeating cycle of STOP usage.

Maybe the button on the Nucleo-64 board should cycle through various application behaviors. Some of these behaviors would be intended to stress test the tickless implementation.

For completeness, sometimes interrupts should make a task ready and sometimes not.

turning off peripherals before idle?

It works great! However, my application uses SPI2 and as soon as I turn it on in CubeMX consumption jumps up to 660 uA in test 1.

Is there a place in the code to turn off peripherals like SPI2 before entering idle to keep consumption low?

Uninitialized helper variable leads to very long sleep

Playing around with unitialized bss (helps the startup time from Standby, yes I informed the compiler about that configuration) I noticed that isTickNowSuppressed

static volatile uint8_t isTickNowSuppressed; // This field helps the tick ISR determine whether
starting up with a non zero value leads to a very long sleep when the ISR is first reached and vPortSuppressTicksAndSleep has not happend before.
I have not reviewed the other helpers to be honest, but I can clearly see on a target that initializing that specific variable to zero fixes my project. E.g. isCmpWriteInProgress might be problematic as well.

Utilizing LSI in Tickless idle might lead to Initialization fail of the IWDG

MCU:
STM32G031G8U6

Core Speed:
2MHz (HSI 8 Div)

Behavior:
Because my application don't have external crystals so I used LSI for the LPTIM. It works fine in the tickless idle. But when it comes to IWDG, the HAL_IWDG_Init(&hiwdg) always failed.

I traced the code to somewhere around here:

/* Check pending flag, if previous update not done, return timeout */
  tickstart = HAL_GetTick();

  /* Wait for register to be updated */
  while ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
  {
    if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT)
    {
      if ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
      {
        return HAL_TIMEOUT;
      }
    }
  }

It seems like it would always return timeout if I don't put a breakpoint in there. Not sure if it related to this but IWDG uses LSI too.

If I removed LPTIM-Tick and go back to the usual Tickless idle, the IWDG works fine.

Add test for immediate wakeups by interrupt

A bug recently fixed in lptimTick.c (2021.08.11) could cause an assertion failure after "immediate" wake-ups from tickless idle. The only other bug in lptimTick.c (fixed 2020.07.10) was also caused by immediate wake-ups -- and landed on the exact same assertion failure (ugh). We should add a test that induces immediate wake-ups, and not just for an ISR but to make a task ready. The woken task should sometimes return very quickly to a blocked state, to address the bug fixed 2020.07.10. The tasks running during this test should also sometimes produce an expected idle time at or above the maximum, in combination with a very quick return to the blocked state, to address the bug fixed 2021.08.11.

Note that the core clock may need to increase from 48 MHz to 80 MHz, and we may need to avoid stop mode, to induce the edge and corner cases of interest. See comments in lptimTick.c regarding counting a tick a little early when precision is enabled.

Also note that the immediate wake-ups may sometimes, but must not always, induce an abort from tickless idle. An abort condition does not test the edge and corner cases of interest. The interrupts used for early wake-up must not come so rapidly that they effectively prevent tickless idle.

Ideally the fixes could be temporarily removed to verify that the new test creates the desired conditions. A long soak may be required.

Need Tests for Tick/Tickless Timing

The project needs tests to validate tick timing and behavior. The tests should

  • Measure, report, and validate drift in kernel time compared to RTC
  • Measure, report, and validate change in drift over short periods of time

The test should run properly with the application configured (1) without tickless idle, (2) with the default tickless idle implementation, and (3) with the lptimTick.c implementation.

Note that use of the RTC as the reference in cases 1 and 2 requires that the core clock and the RTC clock (32kHz LSE) be synchronous. We hope the MSI's PLL mode meets this requirement. Testing in case 1 should prove this MSI characteristic.

One strategy for measuring drift is to use the tick hook to synchronize the RTC subseconds in the first tick and then to capture the RTC subseconds in subsequent ticks. Then the test task could periodically process the most-recently captured subseconds value(s). Configure the RTC for plenty of subsecond resolution.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.