What’s the right way to go into and return from stop mode?

I’m running FreeRTOS 10.1.1 (originally ran into this problem on 8.2.1) on a STM32F746. I have a main thread and two threads, separate read and write, to service the usb serial port. Everything works fine until I cycle the device into and back out of low power (“stop”) mode. At some random point after this, can be in an instant or a minute or more later, the processor hangs in xQueueSemaphoreTake(), called from the the read thread. I added some logging and see that in normal operation it looks like the CPU only passes through xQueueSemaphoreTake() once each time it’s called, but in the hang condition it’s comes back around to call vTaskPlaceOnEventList() a second time, which creates a loop in the linked list, then on the third time around it hangs in vListInsert() since the task’s pxNext points back to itself. I added a listISCONTAINEDWITHIN() check to vListInsert before adding the item, but it just punted the error down the road a little bit. (It would then be stuck in the xQueueSemaphoreTake() loop, as I recall..) I suspect the problem is how I’m putting the device to sleep and waking it up. Here’s the order I’m doing things in: ~~~ USBdeinit(); // de-init USB device, doesn’t touch threads HALSuspendTick(); osThreadSuspendAll(); enterLowPower(); // turns off peripherals, slows clock speed to minimum while ( !unlock ) { HALPWREnterSTOPMode(PWRLOWPOWERREGULATORON,PWRSTOPENTRYWFI); } exitLowPower(); HALResumeTick(); USBInit(); osThreadResumeAll(); ~~~ Does anything there look suspicious? I’ve tweaked the order of those steps and played around with the semaphore timeouts but it only moves the hang from one place to another. Is there any other information I can dig up to help sort this out? Many thanks!

What’s the right way to go into and return from stop mode?

Everything works fine until I cycle the device into and back out of low power (“stop”) mode.
What does stop mode do? By which I mean, what does it turn off? (e.g., does it just turn clocks off or does it also clear RAM contents)? Where are you entering stop mode? In a tickless idle implementation, or idle task, or somewhere else? The code you provided does not look like it is using the tickless idle mode functionality.
vTaskPlaceOnEventList() a second time, which creates a loop in the linked list, then on the third time around it hangs in vListInsert() since the task’s pxNext points back to itself.
This is often a symptom of incorrect interrupt priority configurations. Do you have configASSERT() defined (when using V10.1.1)?
I suspect the problem is how I’m putting the device to sleep and waking it up. Here’s the order I’m doing things in: USBdeinit(); // de-init USB device, doesn’t touch threads HALSuspendTick(); osThreadSuspendAll(); enterLowPower(); // turns off peripherals, slows clock speed to minimum while ( !unlock ) { HALPWREnterSTOPMode(PWRLOWPOWERREGULATORON,PWRSTOPENTRYWFI); } exitLowPower(); HALResumeTick(); USBInit(); osThreadResumeAll(); Does anything there look suspicious?
I don’t know the implementation of the functions here but in summary, yes, there is potential for race conditions here. What sets ‘unlock’?

What’s the right way to go into and return from stop mode?

On Mar 8, 2019, at 8:57 AM, Richard Barry rtel@users.sourceforge.net wrote:
Everything works fine until I cycle the device into and back out of low power (“stop”) mode.
What does stop mode do? By which I mean, what does it turn off? (e.g., does it just turn clocks off or does it also clear RAM contents)?
Stop turns off clocks but retains RAM. I have the RTC waking it up every second to reset the watchdog, and button interrupts also wake it up so it can check if the unlock button has been pressed.
Where are you entering stop mode? In a tickless idle implementation, or idle task, or somewhere else? The code you provided does not look like it is using the tickless idle mode functionality.
We’re not using tickless idle, no. (I hadn’t heard of it until digging in trying to sort this bug out..) Would it make a difference? We suspend threads then turn off SysTick, so xPortSysTickHandler() isn’t getting called, so I assume the idle task is irrelevant here? The pseudocode snippet below is run when the device’s lock button is pressed.
vTaskPlaceOnEventList() a second time, which creates a loop in the linked list, then on the third time around it hangs in vListInsert() since the task’s pxNext points back to itself.
This is often a symptom of incorrect interrupt priority configurations. Do you have configASSERT() defined (when using V10.1.1)?
Yep, configASSERT() is defined as an infinite loop, and as far as I know I haven’t hit it. (I double-checked the disassembly to verify it picked up that definition of the function.)
I suspect the problem is how I’m putting the device to sleep and waking it up. Here’s the order I’m doing things in: USBdeinit(); // de-init USB device, doesn’t touch threads HALSuspendTick(); osThreadSuspendAll(); enterLowPower(); // turns off peripherals, slows clock speed to minimum while ( !unlock ) { HALPWREnterSTOPMode(PWRLOWPOWERREGULATORON,PWRSTOPENTRYWFI); } exitLowPower(); HALResumeTick(); USBInit(); osThreadResumeAll(); Does anything there look suspicious?
I don’t know the implementation of the functions here but in summary, yes, there is potential for race conditions here. What sets ‘unlock’?
Sorry, that “unlock” variable was an abstraction but more of a distraction. The actual code is reading the GPIO checking if the lock button has been pushed and released. It’s just doing GPIO reads there, nothing that would touch the FreeRTOS state. I realize now I was confused about which clock was ticking FreeRTOS. I included the HALSuspend/ResumeTick() calls up there because I thought those were turning off and on the FreeRTOS ticks, but those only touch the HAL clock, which is running off a peripheral timer. We’re ticking FreeRTOS from SysTickHandler, which is being disabled when we slow down the clock in enterLowPower() and reenabled when we set it back to normal in exitLowPower(). What I’ve found through trial and error is everything’s okay until we go into full stop or slow and restore the clock. Do either of those and we’ll later get a hang or crash in FreeRTOS. (I can trigger it by generating a lot of activity on the serial port.) It seems like FreeRTOS would be frozen while that’s happening, and the system should be back to the same state when it’s unfrozen.. But I guess not. 🙁 I’ll keep poking at it. If you have any suggestions or things I should check please let me know! Thanks, -Dave