4

I have c code runned from RAM in low power run mode (so interrupt are no handled). This mode enabled by code sequence:

  • jump to RAM
  • SIM
  • switch off internal flash, and power regulator, switch to low speed clock source (LSE)
  • do some work with WFE mode (low power wait mode)
  • switch on power regulator and flash, restore clock source
  • RIM
  • jump to flash

So there no problem whith WFE instruction that described in errata sheet. Problem with this construction, it may be cause of CPU lock in low power wait mode forever:

while nbit(TIM1_SR1,CC3IF) asm("wfe");

that is disassembly as:

000035    720252B602     BTJT      TIM1_SR1, #1, 0xB6
00003A    728F           WFE

Event from timer has a probabilistic nature, and this code don't guarantee that it will happen after WFE instruction be executed:

  • BTJT instruction exucted in 2 cycles, and have length 5;
  • code executed from RAM may be not continuous because "fetch" states pause execution on few cycles

I use manual PM0044, and at page 26 it content pretty table:

example code execution from RAM

There 2 cases when code execution stalled at 3 cycles. So I'm not sure that my asynchronous wakeup event will not occur between BTJT and WFE instructions.

Is there ways to be ensure strict logical sequence (check condition > wfe > wakeup event)?

Stephan
  • 41,764
  • 65
  • 238
  • 329
imbearr
  • 999
  • 7
  • 22
  • It's not clear what you're asking. After the WFE instruction is executed the CPU has already been woken up by an event and the following instruction is executed. The following instruction should be JRA instruction that jumps back to the BTJT instruction. The sequence is 1) test bit and exit loop if set 2) wait for wake up event 3) jump to step 1. If you've programmed WFE control registers correctly then it should be the equivalent to the sequence 1) test bit and exit loop if set 2) jump to step 1. The WFE instruction just saves power. – Ross Ridge Apr 02 '16 at 21:20
  • @Ross, Is it really as you think? _After the WFE instruction is executed the CPU has already been woken up by an event and the following instruction is executed._ Now I believe that this buggly code construction, and right way is to use WFE intruction only if there is a fairly large margin of time. And in more complex cases don't use it after any rival wakeup events. – imbearr Apr 03 '16 at 08:42
  • I'm sure it works the way I described. During the execution of the WFE instruction the CPU is asleep and waiting for an event. After the execution of the WFE instruction is finished the CPU is no longer asleep and is no longer waiting for an event. It then goes onto execute the next instruction, just like what normally happens when an instruction completes execution. However, I still don't see what your problem is. so we may not be talking about the same things. What problem would a large margin of time solve? – Ross Ridge Apr 03 '16 at 09:57
  • I'm not sure that CPU will not go to sleep mode if wakeup event will occured after execution of BTJT inctruction and before execution of WFE inctruction. This case can occur when code execution stalled at few cycles by fetch procedures because on stm8 when code runned from RAM 8bit bus used for data and 16bit for address instead 32bit for data and 24 bit for adress in case when code runned from FLASH. – imbearr Apr 03 '16 at 10:40
  • @Ross I have updated my question - now it's more explain my problem. – imbearr Apr 03 '16 at 15:54
  • Ah, ok, you're worried about happens *before* the WFE instruction executes. I'd assume wake up events are level triggered otherwise race conditions are unavoidable. It's not just in the time between execution of the BTJT and WFE instructions, but since interrupts are processed during the WFE instruction any wake up events would be lost during interrupt processing. However I can't find anything that confirms my assumption. You can test this by adding a `while !nbit(TIM1_SR1,CC3IF) {}`` statement to the top of the body of your loop before the WFE instruction and see if it locks up. – Ross Ridge Apr 03 '16 at 17:11
  • @Ross Interrupts are not handled because I use low power run mode, flash memory is switched off. CPU will lock forever - i have construction like this: `for (;;) { if bit(TIM1_SR1,CC1IF) break; if bit(TIM1_SR1,CC2IF) { do_something; } asm("wfe"); }` each compare channels are wakeup CPU by event and sometimes it locked execution. – imbearr Apr 03 '16 at 18:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108102/discussion-between-imbearr-and-ross-ridge). – imbearr Apr 03 '16 at 18:27
  • Check the errata for the chip you're using. Some implementations of WFE are broken depending on how the instruction is aligned in a 32-bit word. – Ross Ridge Apr 03 '16 at 19:33

2 Answers2

5

If your lockup problems are caused by the WFE errata I mentioned then there should be an easier solution than trying to achieve "proper application timing".

The errata provided by STMicroelectronics reads:

Two types of failures can occur:

Case 1:
In case WFE instruction is placed in the two MSB of the 32-bit word within the memory, an event which occurs during the WFE execution cycle or re-execution cycle (when returning from ISR handler) will cause an incorrect code execution.

Case 2:
An interrupt request, which occurs during the WFE execution cycle will lead to incorrect code execution. This is also valid for the WFE re-execution cycle, while returning from an ISR handler

Case 2 shouldn't apply in your case as you say "Interrupts are not handled because I use low power run mode". If interrupts can't occur during the WFE instruction only the failure described in the first case could be causing your lockups.

Case 1 only applies if the WFE instruction is in a certain alignment within a 32-bit word in memory. So if you can ensure the WFE instruction never appears in code aligned this way then you won't encounter this failure. If your assembler supports an align directive you could use it achieve this, maybe along with a label and a jump if the assembler doesn't insert NOPs. However an easier solution is given as a "dedicated workaround" in errata:

Replace the WFE instruction with

     WFE
     JRA next
next:

This appears to work around the failure by putting what amounts to a 2-byte NOP after the WFE instruction. My guess is the failure results in the CPU not executing the instruction immediately following the WFE instruction, instead skipping ahead two bytes to the instruction (if any) at the start of the next 32-bit world. Putting a 2-byte NOP in the space skipped over means it doesn't matter if the failure occurs or not.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
  • it's not so difficult to revise code for ensure proper timing, and this is more right way for my opinion. – imbearr Apr 06 '16 at 10:33
1

Solution found by OP:

I have read errata (thanks to Ross Ridge) few times more attentively, and this is main idea:

General solution is to ensure no interrupt request or event occurs during WFE instruction execution or re-execution cycle by proper application timing.

Community
  • 1
  • 1
Stephan
  • 41,764
  • 65
  • 238
  • 329