Tickless Idle Hard Fault

denisdaviau wrote on Tuesday, April 15, 2014:

I am having some difficulty in isolating a Hard Fault error on a project that runs fine with tickless idle turned off but fails with a hard fault when turned on.

The program is based on one of the low power examples. It has a transmit task and a receive task. The receive task waits forever on a queue and flashes an LED when a message comes in. The sender waits forever for a semaphore. The semaphore is set by an RTC interval timer interrupt.

At first, I had some trouble getting into low power sleep mode. The example I was looking at had a timeout value on the semaphore. The implementation of eTaskConfirmSleepModeStatus in tasks.c will not return eNoTasksWaitingTimeout unless ALL the tasks (except idle) are in suspended state. Well, tasks will only enter suspended state if they have no timeout. (Hope I’m right about this.) So, when I removed the timeout on the semaphore, the processor went into stop mode.

It runs for a couple of cycles and then goes to hard fault. I put in the code to find out where it thought it was and it reports that it’s off in deep space somewhere, like a stack corruption issue or something.

I sure hope someone can help me with this, I am in the midst of converting a fully function application for battery operation. I am running on an STM32F205VE with custom hardware.

rtel wrote on Tuesday, April 15, 2014:

Yes - the code will only attempt to go into an indefinite sleep if all the tasks are either suspended or blocked without a timeout - it can only sleep indefinitely if all the tasks are waiting indefinitely - but not having all the tasks waiting indefinitely should not prevent it going into a (time limited) low power sleep. Provided the anticipated sleep time is >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP then sleep mode should be entered. Search for “configEXPECTED_IDLE_TIME_BEFORE_SLEEP” on http://www.freertos.org/low-power-tickless-rtos.html.

You say the program is base on one of the low power examples, and that you are running it on an STM32F205. Is this the example you based it on (click link)? If so, I think that uses some chip specific features that might not be available on the F parts as the L parts are designed specifically for low power. Have you tried running the demo using just the default tickless idle implementation? The default just uses features available directly in the Cortex-M core itself, with no reliance any any chip specific functionality. That severely limits the power saving that can be achieved, but is a good starting point. To try that remove any low power specific code from your application (so don’t override the tick generation source or source code, and don’t define any pre or post sleep hooks) and just run your known good application but with configUSE_TICKLESS_IDLE set to 1 in FreeRTOSConfig.h.


denisdaviau wrote on Tuesday, April 15, 2014:

Thank you for your input, you hit the nail on the head.

I started from a sm32l demo. The demo has a specific implementation of vPortSuppressTicksAndSleep that I looked at and did no change. When I switched back to the default implementation, the hard fault error goes away. With the “stm32l” implementation my current was much lower then the default implementation but it frequently got the hard fault. So, now I have to find out what is different and see if some of the stuff in the “L” implementation will work for the “F” processor.

The search goes on.

denisdaviau wrote on Tuesday, April 15, 2014:

Ok, more stuff on this.

The default implementation calls “wfi” directly while the “stm32l” demo calls PWR_EnterSTOPMode( PWR_Regulator_LowPower, PWR_STOPEntry_WFI ). When I make that simple change, the program fails almost immediately. Looks like this function is not FreeRTOS friendly.

Still no viable solution.

rtel wrote on Wednesday, April 16, 2014:

In the demo the PWR_EnterSTOPMode() function is a driver provided by ST that is presumably doing some stuff that is very specific to the ‘L’ part. Did you try using the exact same function (from the demo) on the ‘F’ part, or did you use a version of PWR_EnterSTOPMode() from ST that is specific to the ‘F’ part?

Once you get into the low power functionality there are (generalising greatly) three layers: The chip, the peripherals that are common to the chip family, and the peripheral/modes that are specific to sub families within the chip family. The top layer is generic and works on all Cortex-M parts. The middle layer is less portable across manufacturers, but should work on any STM32 part. The bottom layer, required for the really low currently, is less portable. So it is likely to be not chip friendly, rather than not FreeRTOS friendly.


denisdaviau wrote on Monday, April 21, 2014:

I am still getting a hard fault when calling the PWR_EnterSTOPMode. Pinning it down further, I have found that the issue does not happen entering stop mode but coming out of it. It’s like there is some registers that FreeRTOS needs to be left alone that are modified causing what looks like a stack corruption error.

I know that the STM32F2xx implementation of PWR_EnterSTOPMode does it’s job as I have seen the processor drop down to 30is uA when called from a non FreeRTOS program. I am going to keep poking around with this as I will definitely get the years of battery life I am expecting if I can get the current that low.

rtel wrote on Monday, April 21, 2014:

Unlike normal critical section, the low power tickless mode has to disable interrupts globally. This is because critical sections only mask a interrupts up to a certain priority, and the mask will prevent the interrupt being taken, which in turn prevents the MCU from exiting sleep mode. Interrupts being globally disabled does not prevent an interrupt from bringing the MCU out of sleep mode, but still prevents the interrupt actually being executed - and the low power mode implementation must be very careful about when this actually happens. Make sure the implementation of PWR_EnterSTOPMode() is not itself re-enabling interrupts - which would mean they get reenabled too soon. I suspect this is what it will be do, and that just might be the cause of your problem.


denisdaviau wrote on Wednesday, May 14, 2014:

I did eventually get this to work properly. It was mostly my misunderstanding about NVIC and priority validation that is in version 8. There were a lot of other little things as well. Thanks all for your assistance.

scottdmorgan wrote on Wednesday, April 22, 2015:

Denis, can you share more details on how you were able to get the HAL_PWR_EnterSTOPMode() to work with FreeRTOS on the STM32F2? I am having the same problem as you had with hard faults. I removed this code from the _weak version of vPortSuppressTicksAndSleep which is in port.c:

if( xModifiableIdleTime > 0 )
__DSB(); // there are two underscores in front of DSB()
__WFI(); // there are two underscores in front of WFI()
__ISB(); // there are two underscores in front of ISB()

I moved all of the sleep code to this function:
void PreSleepProcessing(unsigned long ulExpectedIdleTime)
(void) ulExpectedIdleTime;

if(ulExpectedIdleTime > 100)
else if(ulExpectedIdleTime > 0)


Any ideas on what I might be doing wrong here would be appreciated!

scottdmorgan wrote on Wednesday, April 22, 2015:

I think I found my own answer. There appears to be a bug in HAL_PWR_EnterSTOPMode() that is causing the hard fault. That function needs to be modified to issue a __DSB() before the __WFI() and an __ISB() afterwards. The same is true before/after the __WFE(). I tested the __WFI() case and the hard fault goes away.

Now to figure out why my STM32F2 is waking from stop mode once every second? I’m guessing it’s an interrupt from the RTC.