-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cpu/stm32f1: CPU hangs after wake-up from STOP power mode #13918
Comments
@leandrolanzieri sry for contacting you directly! |
No worries!
I can successfully reproduce the error, but sadly adding the
|
IIRC we've had this issue before. I also remember adding nops for stm32f1. But my memory is cloudy... |
Can you add a few more |
Still does not come back :-/ |
Okay. Thanks for testing :) |
I was done for |
I can't reproduce with a |
Also just to make sure we have the same environment, can you |
This ERRATA has some mentions of wakeup issues under specific conditions, could you take a look if one of them applies? |
@fjmolinas Thanks for you response!
Done that. The problem still persists.
The cold boot seems to fix the problem :) Do you have an idea why the CPU hangs after being in a freshly flashed state? Have you observed something similar on STM CPUs? |
I had the same issue with stm32l152re. Can you check if its under the same conditions as described in #11830 (remove If its of any use I think this comment #11919 (comment) resumed what I had found out for Let me know if the workaround in #11919, I could go back to the suggestion in #11919 (comment). I remember implementing it but having many compiler issues that blocked me, and then I forgot about that. |
This following modifications of the openocd configs fixed the issue. (But I haven't tested if debugging still works, yet.) diff --git a/boards/common/blxxxpill/dist/openocd-128kib.cfg b/boards/common/blxxxpill/dist/openocd-128kib.cfg
index ccaf60b77..d40a29f05 100644
--- a/boards/common/blxxxpill/dist/openocd-128kib.cfg
+++ b/boards/common/blxxxpill/dist/openocd-128kib.cfg
@@ -20,3 +20,31 @@ set FLASH_SIZE 0x20000
source [find target/stm32f1x.cfg]
$_TARGETNAME configure -rtos auto
+
+# We override openocd defualt configuration so DEBUG in sleep mode is
+# not enabled by default
+$_TARGETNAME configure -event examine-end {
+ # Stop watchdog counters during halt
+ # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
+ mmw 0xE0042008 0x00001800 0
+}
+
+# Add gdb-attach/gdb-detach events, DEBUG in sleep modes in now only
+# enabled when a gdb session is started.
+$_TARGETNAME configure -event gdb-attach {
+ # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
+ mmw 0xE0042004 0x00000007 0
+
+ # Stop watchdog counters during halt
+ # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
+ mmw 0xE0042008 0x00001800 0
+}
+
+$_TARGETNAME configure -event gdb-detach {
+ # DBGMCU_CR &= ~(DBG_STANDBY | DBG_STOP | DBG_SLEEP)
+ mmw 0xE0042004 0x00000000 0x00000007
+
+ # Stop watchdog counters during halt diagnoized
+ # DBGMCU_APB1_FZ &= ~(DBG_IWDG_STOP | DBG_WWDG_STOP)
+ mmw 0xE0042008 0x00000000 0x00001800
+}
diff --git a/boards/common/blxxxpill/dist/openocd.cfg b/boards/common/blxxxpill/dist/openocd.cfg
index dd5f28645..dc0f55ad0 100644
--- a/boards/common/blxxxpill/dist/openocd.cfg
+++ b/boards/common/blxxxpill/dist/openocd.cfg
@@ -17,3 +17,31 @@ set CONNECT_UNDER_RESET 1
source [find target/stm32f1x.cfg]
$_TARGETNAME configure -rtos auto
+
+# We override openocd defualt configuration so DEBUG in sleep mode is
+# not enabled by default
+$_TARGETNAME configure -event examine-end {
+ # Stop watchdog counters during halt
+ # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
+ mmw 0xE0042008 0x00001800 0
+}
+
+# Add gdb-attach/gdb-detach events, DEBUG in sleep modes in now only
+# enabled when a gdb session is started.
+$_TARGETNAME configure -event gdb-attach {
+ # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP
+ mmw 0xE0042004 0x00000007 0
+
+ # Stop watchdog counters during halt
+ # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
+ mmw 0xE0042008 0x00001800 0
+}
+
+$_TARGETNAME configure -event gdb-detach {
+ # DBGMCU_CR &= ~(DBG_STANDBY | DBG_STOP | DBG_SLEEP)
+ mmw 0xE0042004 0x00000000 0x00000007
+
+ # Stop watchdog counters during halt diagnoized
+ # DBGMCU_APB1_FZ &= ~(DBG_IWDG_STOP | DBG_WWDG_STOP)
+ mmw 0xE0042008 0x00000000 0x00001800
+} The workaround you mentioned leads to a hardfault: diff --git a/cpu/cortexm_common/include/cpu.h b/cpu/cortexm_common/include/cpu.h
index d79d65495..056ba3aa1 100644
--- a/cpu/cortexm_common/include/cpu.h
+++ b/cpu/cortexm_common/include/cpu.h
@@ -170,7 +170,7 @@ static inline void cortexm_sleep(int deep)
unsigned state = irq_disable();
__DSB();
__WFI();
-#if defined(CPU_MODEL_STM32L152RE)
+#if defined(CPU_MODEL_STM32L152RE) || defined(CPU_MODEL_STM32F103CB) || defined(CPU_MODEL_STM32F103C8)
/* STM32L152RE crashes if branching to irq_restore(state). See #11830. */
__set_PRIMASK(state);
#else
|
Ok, so the issues are somehow similar. Does inserting |
I tried this with the build environment showed above and with The following patch did the trick: diff --git a/cpu/cortexm_common/include/cpu.h b/cpu/cortexm_common/include/cpu.h
index d79d65495..73d396f41 100644
--- a/cpu/cortexm_common/include/cpu.h
+++ b/cpu/cortexm_common/include/cpu.h
@@ -169,6 +169,8 @@ static inline void cortexm_sleep(int deep)
/* ensure that all memory accesses have completed and trigger sleeping */
unsigned state = irq_disable();
__DSB();
+ __NOP();
+ __NOP();
__WFI();
#if defined(CPU_MODEL_STM32L152RE)
/* STM32L152RE crashes if branching to irq_restore(state). See #11830. */ 1, 3 and 4 |
Ups, I'm sorry I actually meant after the Otherwise I snooped around in forums and reference manual today, but I have nothing very clear to contribute ATM. But I saw that TI for one of their applications added |
This actually works: diff --git a/cpu/cortexm_common/include/cpu.h b/cpu/cortexm_common/include/cpu.h
index d79d65495..fe696c15d 100644
--- a/cpu/cortexm_common/include/cpu.h
+++ b/cpu/cortexm_common/include/cpu.h
@@ -170,6 +170,7 @@ static inline void cortexm_sleep(int deep)
unsigned state = irq_disable();
__DSB();
__WFI();
+ __NOP();
#if defined(CPU_MODEL_STM32L152RE)
/* STM32L152RE crashes if branching to irq_restore(state). See #11830. */
__set_PRIMASK(state); |
Aha!, so it seems to be the same kind of issue... |
Cool. Even more reason to get it in :-) Thanks for the quick reply! |
Huh, thats strange how is it that the changes tin #13999 fixed the issue but not #13918 (comment)?? Anyway if it fixes it it still good! |
Indeed. Sorry, I wasn't following the discussion here closely enough. It would be nice to understand what exactly triggers the problem so that we can ensure it does not pop up again. @jue89: Can you check again to rule out human error? Can you temporarily add an |
Sure. Current master: tests/periph_pm hangs
With this patch applied (checked with diff --git a/cpu/cortexm_common/include/cpu.h b/cpu/cortexm_common/include/cpu.h
index d79d65495..9dae3e104 100644
--- a/cpu/cortexm_common/include/cpu.h
+++ b/cpu/cortexm_common/include/cpu.h
@@ -170,7 +170,7 @@ static inline void cortexm_sleep(int deep)
unsigned state = irq_disable();
__DSB();
__WFI();
-#if defined(CPU_MODEL_STM32L152RE)
+#if defined(CPU_MODEL_STM32L152RE) || defined(CPU_MODEL_STM32F103CB) || defined(CPU_MODEL_STM32F103C8)
/* STM32L152RE crashes if branching to irq_restore(state). See #11830. */
__set_PRIMASK(state);
#else tests/periph_pm hardfaults
|
In that case does it make sense to extend #14015 to also mention this platform, and if the issue shows up again consider adding 3 x So if #13999 fixes the issue, I propose to just take that and as I said extend #14015 to mention this platform, since they seem to follow the same pattern. |
I agree with @fjmolinas that we should not spend too much time investigating the issue if #13999 can solve it. Maybe it will never pop up again. But in case it does: @jue89, could you post the dissassembly of |
Sure. pm_set() on current master (8ffd34d) still hangs
And
pm_set() with the modified #ifdef for the in-lined irq_restore() hardfaults
Both differ only at the in-linded pm_set() from #13999 still works (HEAD: 9012c6c)
I hope I caught everything interesting! |
Hmm, the two non-working cases restore the interrupts using: I think I read something about |
I will try to confirm this sometime this week. If that is indeed the cause, adding an
before entering the power saving mode should tell the compiler to either not use |
I tried this to check if the corruption of diff --git a/cpu/cortexm_common/include/cpu.h b/cpu/cortexm_common/include/cpu.h
index ca895972e5..d3889203b0 100644
--- a/cpu/cortexm_common/include/cpu.h
+++ b/cpu/cortexm_common/include/cpu.h
@@ -166,11 +166,18 @@ static inline void cortexm_sleep(int deep)
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
}
+ register unsigned r0 __asm__ ("r0") = 0x42424242;
+
/* ensure that all memory accesses have completed and trigger sleeping */
unsigned state = irq_disable();
__DSB();
__WFI();
irq_restore(state);
+
+ __asm__ volatile ("" : "+r"(r0));
+ if (r0 != 0x42424242) {
+ printf("Bug! r0 = 0x%x\n", r0);
+ }
}
/** So I first us an explicit register variable in The resulting assembly shows that the compiler indeed did what I intended. (And did not back up 0800066c <pm_set>:
800066c: b510 push {r4, lr}
800066e: b1e8 cbz r0, 80006ac <pm_set+0x40>
8000670: 2801 cmp r0, #1
8000672: d02d beq.n 80006d0 <pm_set+0x64>
8000674: 2400 movs r4, #0
8000676: 4a1c ldr r2, [pc, #112] ; (80006e8 <pm_set+0x7c>)
8000678: 6913 ldr r3, [r2, #16]
800067a: f023 0304 bic.w r3, r3, #4
800067e: 6113 str r3, [r2, #16]
8000680: f04f 3042 mov.w r0, #1111638594 ; 0x42424242
8000684: f3ef 8310 mrs r3, PRIMASK
8000688: b672 cpsid i
800068a: f3bf 8f4f dsb sy
800068e: bf30 wfi
8000690: f383 8810 msr PRIMASK, r3
8000694: f1b0 3f42 cmp.w r0, #1111638594 ; 0x42424242
8000698: 4601 mov r1, r0
800069a: d002 beq.n 80006a2 <pm_set+0x36>
800069c: 4813 ldr r0, [pc, #76] ; (80006ec <pm_set+0x80>)
800069e: f001 fe8b bl 80023b8 <iprintf>
[...] I was unable to trigger the test. So no idea, why this failed previously :-/ |
(I just posted a comment to #14015 with a workaround that may fix this, fwiw.) |
See [1] for details. (archive.org backup at [2]). Fixes RIOT-OS#13918 Fixes RIOT-OS#14015 [1]: https://cliffle.com/blog/stm32-wfi-bug/ [2]: https://web.archive.org/web/20231205101603/https://cliffle.com/blog/stm32-wfi-bug/
See [1] for details. (archive.org backup at [2]). Fixes RIOT-OS#13918 Fixes RIOT-OS#14015 [1]: https://cliffle.com/blog/stm32-wfi-bug/ [2]: https://web.archive.org/web/20231205101603/https://cliffle.com/blog/stm32-wfi-bug/
Description
I am experiencing odd behavior with the STM32F103C8 CPU on current master. I am running the application
tests/periph_pm
on the boardbluepill
. After the RTC woke up the board fromSTM32_PM_STOP
, it hangs.After digging around I found out that the problem is solved by introducing two NOPs before re-initializing the clocks:
Steps to reproduce the issue
Flash
tests/periph_pm
on the boardbluepill
:Expected results
(The first unblock is required to release the block issued by the UART behind
stdio_uart
.)Actual results
Versions
The text was updated successfully, but these errors were encountered: