Calling xQueuePeek in vApplicationIdleHook stopped schedulre

ciaranmaca wrote on Tuesday, November 05, 2013:

I wanted to use a counting semaphore to manage low power so that when all relevant client tasks had ‘checked in’ I would go into a deep sleep in the ApplicationHook instead of a normal sleep. (Cortex M3 port of 7.3.0).

I tried two ways while in the ApplicationHook (idle task) to check if the counting semaphore was non-zero.

  1. Use xQueuePeek with no wait.
  2. See if I can do a take (no wait) on the semaphore. If I can give it back.

Both approaches seem to make the scheduler lock up. Interrupts were still running but the tasks seem to no longer be scheduled. I saw in a few places that API calls can be used in the ApplicationHook / Idle Task AS LONG AS THEY ARE NON BLOCKING, that is, no wait.

But that didn’t seem to work for me. Can anyone explain why I was seeing the failure?

My workaround is to use a mutex protected count variable in my client tasks and check it raw, unprotected in ApplicationHook. That seems to work ok.

Thanks for any insight.

davedoors wrote on Tuesday, November 05, 2013:

Do you have stack overflow checking enabled? It might be you are overflowing the idle task stack. The idle task stack size is set by configMINIMAL_STACK_SIZE.

Why not use the built in low power functionality?

ciaranmaca wrote on Wednesday, November 06, 2013:

Thanks for the reply Dave. Yes I do have stack overflow check on, nevertheless, it is worth adjusting the minimal stack size to see. But that might not solve my problem…

Why not use build in low power? As far as I see there are two very good low power strategies for cortex:

  1. Use a timer other than systick for the rtos tick. This allows the idle hook to drop into a very low power mode where peripheral clocks and system clocks (including the one that drives Systick) are off. (I am using this strategy with a twist - more below)

  2. Tickless Idle. This is the ‘icing on the cake’. I don’t think I need to go this far. I can live with the short wakeup on every sys tick given the short time it takes the sheduler to determine that no tasks are on the ready list and therefore that it will go back to sleep.

The Twist. My app does UART and SPI comms. The driver code for these uses rtos events to determine end of transmission, and for uart, end of message for rcv. During these rtos calls the sheduler can and will drop into IDLE and enter the very low power mode. But this kills my peripherals. The scheme to get around this was to wrap my “send/rcv” primitives in a “don’t do deep sleep” flag system. Now when the idle runs if it sees the flag set, it will drop into a moderately low power mode which leaves the peripherals enabled but which stops the core.

Lovely - except that it doesn’t work :-(. Because IDLE hook cannot block I think there is no way of forcing a safe mutual exclusion so that there cannot be an erroneous drop into very low power. Even if the IDLE hook checks a flag or peeks at a counting semaphore and determines that very low power can be entered, it (that is, the idle task) might now be interrupted by the tick, the scheduler might run allowing a task which is going to communicate to run, and when idle next runs it will drop the system into the very low power mode. Bang. Comms are now compromised.

I cannot think of any way around this at the moment. A plan B is to not use very low power at all, but my current budget is not going to make that attractive. Second is to do what I once did before - implement a low power manager which the tasks check in with and which can then safely put the uP into very low power mode.

But implementing my own power manager is less efficient, since it operates outside the RTOS. Indeed, when you think about it, the RTOS, which manages tasks, is precisely where this management belongs. But at the moment, I’m a bit stuck.

davedoors wrote on Wednesday, November 06, 2013:

In the tickless idle mode you can use the pre sleep hook function to abort the low power entry if a comms operation is in progress.

ciaranmaca wrote on Wednesday, November 06, 2013:

Nice proposal, one issue though. I see that in the tickless idle, where PRE and POST sleep are called (on either side of the key WFI call) that interrupts are disabled using CPSID.

Does this mean that if a tick happens between the CPSID and CPSIE that it will be missed?

But the system will wake because at an outer, microcontroller layer, the interrupt has actually triggered the wakeup logic. The handling is turned off only at the core. So, once sleep happens, i.e. WFI, then there is a low power period, now a tick happens but the tick counter is not incremented. Am I right?

But since we are woken, when will the scheduler next run? I.e when will other tasks be considered again for execution?

My original problem, described in my previous post, was that the IDLE task could be interrupted by the systick, the scheduler might run, causing a syncronisation problem with my flags.

The key difference here in the tickless implementation is the turning off of the interrupts at the core thus preventing any other task being rescheduled. I am trying to assess if that is going to work for me. Perhaps I could manually use this strategy in my ordinary old ‘tickful’ idle.