FreeRTOS - what consumes power?

Hello, my first post here!

I’ve got a FreeRTOS-program that i’m working on, based on an example from the Ambiq Micro SDK (/apollo3_evb/examples/freertos_lowpower/).

I’ve replaced the LED functionality with calculation of prime numbers, to show processor current consuption (~440 uA, VDD 3,3 V).

I’ve read and implemented the functions to shutdown peripherals and IO’s explained here: https://forum.sparkfun.com/viewtopic.php?f=169&t=50904 and disconnected the microphone and so on.

I have measured with this board without the RTOS, deepsleep currents of 1,5 uA SRAM_off-no-wake-up and 2,9 uA SRAM_on-RTC-wake-up.

Currently my FreeRTOS project consumes about 70 microamperes in deepsleep, with the same initializations as in the 2,9 uA “while loop program”.

Does the RTOS itself enable some clocks or do you know what consumes the power?

I’ve attached the program and i apologise if it is a bit messy, it being still under development.

FreeRTOSConfig.h - untouched

Cheers -Turo

ulp_deepsleep_freertos_SF_Forum.zip (474 KB)

I’ll take a shot in the dark here - I am far from an expert in either low power or RTOS applications. I is my understanding that the RTOS needs to check when the next scheduled task is meant to execute, then do that when needed. Unless the tasks are handled with interrupts (generated by a system timer or other peripheral) then there would need to be a polling system? That sounds not “low power” to me.

On the other hand - I have spoken with some contacts at Ambiq Micro and they have implied that FreeRTOS was “low power” compared to mbed-os. So perhaps there is a way to achieve low power while using FreeRTOS… worthy of further investigation I’d say!

Hello liquid.soulder, there is a pdf about FreeRTOS & Apollo3 in the SDK, but for me, it doesn’t answer the questions at hand or i don’t understand something. FreeRTOS is very new thing for me.

Low power FreeRTOS implementation in the AmbiqSuite SDK uses some custom “Ambiq Tickless Idle Mode”, which i again don’t understand how it works:

"This is Ambiq specific implementation geared towards lowest power usage with FreeRTOS9.

This implementation relies on an external timer instead of ARM SysTick to keep track of time allowing the core to be completely powered down when idling."

I have to mention that ARM is new to me also.

What i think about low power, ~70 uA deep sleep consumption is not it for me, but everything is always application specific.

My task is to measure as low as possible deep sleep consumption, with for example timed wakeup or pin state change interrupt.

-Turo

I use the tickless FreeRTOS system for extremely low power applications. It works great.

To explain a tickless RTOS : When there are multiple tasks that want to run, there really is no difference between a tickless and a ‘normal’ RTOS. They both use timer ‘tick’ interrupts to split time into discrete slices that they divvy up between all the competing tasks. The difference shows up when there are no tasks that need to run. A ‘normal’ RTOS always gets the timeslice tick interrupt, then figures out that it has nothing to do, and goes back to sleep again. From a software perspective, It’s completely harmless, but all those tick interrupts waste battery power. In contrast, a ‘tickless’ RTOS is able to figure out when has nothing to do. Before going to sleep, it suppresses all further timeslice ticks. When some event occurs that causes a task to become ready to run again, the ticks get restarted for as long as there is work to do. This allows a battery-powered system to remain undisturbed in deepsleep when it has nothing to do. It is a simple concept, but there are a lot of complexities to make it work. Fortunately, the RTOS takes care of most of it.

The comment about the SysTick timer is important for a Arm Cortex processor: the systick timer stops running when the processor is asleep. It’s a simple solution: the Ambiq version of FreeRTOS uses the Apollo3 STIMER peripheral instead. All you need to know is that the STIMER is off-limits because FreeRTOS is already using it.

To get back to the original question, some unexpected bit of hardware is obviously turned on when your system goes to sleep. There is a routine (below) that you need to supply to FreeRTOS that FreeRTOS will call when it knows that there is nothing to do and it wants the processor to go to sleep. You should check and see what peripherals are enabled at that exact point in time just before the processor goes to sleep. Obviously, something is turned on.

//*****************************************************************************
//
// Sleep function called from FreeRTOS IDLE task.
// Do necessary application specific Power down operations here
// Return 0 if this function also incorporates the WFI, else return value same
// as idleTime
//
//*****************************************************************************
uint32_t am_freertos_sleep(uint32_t idleTime)
{
  am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
  return 0;
}

One test you could try is to include all your power-down code in this routine before it calls am_hal_sysctrl_sleep(). If that improves the power consumption, then you can start narrowing down which bit of the hardware is responsible for the extra power, and then you can start to investigate why that peripheral is enabled.

Hey,

thank you robin_hodgson for the input! Interesting post.

This is quite embarassing now, because the current consumption went down to three micro amperes in deep sleep and I have no idea how this happened.

I had defined NOFPU for some reason to test something in the past and when i commented out that, i guess at that point the current went down. Redefining it didn’t increase the current consumption back so i guess this doesn’t make a difference.

I even tested this with the program i posted here, which i had made no modifications since, and it was the same 3 uA.

I’ll do some more testing to make sure of it.

-Turo

If the software didn’t change, it’s a good hint that something could be up with your hardware setup. For example, an accidentally floating GPIO input may draw excess current if there is noise on it. Make sure that all unused GPIOs are disabled.