How to exit low power mode with IDLE Hook?

marting2015 wrote on Monday, February 16, 2015:

I have enabled the IDLE hook and using it to put the processor into a low power mode. How do I exit low power mode? It would seem I would need another hook that tells me when a non-IDLE task is scheduled… I am also using tickles mode.

I can see that the scheduler is turned off (SUSPEND) and there is a call to RESUME when FreeRTOS exits sleep mode (see portTASK_FUNCTION()). One solution could be to trigger a special (highest priority) task that restores the CPU (exit low power) before any of the other tasks run, which I guess could be done with a semaphore to a high priority task, and GIVE the semaphore when xTaskResumeAll() is called. However I don’t want to touch FreeRTOS functions, so I don’t think this is the right approach.

I tried putting my exit_low_power code in vPortSuppressTicksAndSleep() but the target crashes hard… I suspect because my exit_low_power uses FreeRTOS APIs, and vPortSuppressTicksAndSleep() is probably running in special (interrupt?) context where I can’t call those APIs. Because I am using tickles mode, my openOCD GDB connection won’t work to debug it further.

rtel wrote on Monday, February 16, 2015:

As we were just discussing in this thread: if you are using tickles idle then you should >not< be doing any of this stuff in the idle hook - all you should be doing is defining the pre and post sleep macros if that is desirable to do something chip specific before and after the sleep respectively.

You cannot use another hook, or another task, because when the CPU is sleeping nothing is running (so the task you want to use to wake up is not running so can’t wake you up).

The tickless idle mode takes care of all this for you. It will wake up at the right time, or when an interrupt occurs.


marting2015 wrote on Tuesday, February 17, 2015:

I thought this was a different enough topic to start a new thread. I think my question is slightly different…

Lets say that I have an LDO that I want to turn off when that component is not being used, and I know its not being used when the IDLE task is running. But when any other task is running, the component may be used. So in the IDLE hook I would turn off the component. But when do I turn it on?

Based on your answer above, and from the other thread, I can use the pre and post sleep macros to turn OFF/ON the LDO. That makes sense. And works in tickles mode. In tick mode, though, those macros aren’t called.

If I wanted to use the IDLE hook to turn off the LDO, if there a mechanism to turn on the LDO when the IDLE task is pre-empted to run (any) other task?

rtel wrote on Tuesday, February 17, 2015:

I think you would have to do that from a trace macro - you could use
traceTASK_SWITCHED_OUT( x ). If x is not the idle task then do whatever
you need to do. Note the macro might be called from an interrupt
though, so whatever you do will have to be fast.

If INCLUDE_xTaskGetIdleTaskHandle() is set to 1 in FreeRTOSConfig.h then
inside the traceTASK_SWITCHED_OUT() macro the handle of the idle task is
held in a variable called xIdleTaskHandle.

To ensure future proofing the code though you would be better off
calling xTaskGetIdleTaskHandle() yourself rather than relying on the
name of the variable not changing in future FreeRTOS versions.