2025-11-26 8:06 AM - last edited on 2025-11-27 3:11 AM by KnarfB
According to RM0433 Rev 8:
The Run* mode is entered after a POR reset and a wakeup from Standby. In Run* mode, the performance is limited and the system supply configuration shall be programmed in PWR control register 3 (PWR_CR3). The system enters Run mode only when the ACTVOSRDY bit in PWR control status register 1 (PWR_CSR1) is set to 1.
and
As long as ACTVOSRDY indicates that voltage levels are invalid, the system is in Run* mode, write accesses to the RAMs are not permitted and VOS shall not be changed.
Now, the startup code first jumps (bl ExitRun0Mode) to the C function `ExitRun0Mode()` which probably might involves writes to stack.
Is this construct (calling a C function from ASM) just relying on the compiler not touching the stack or am I'm reading the docs wrongly?
best regards
Torsten
Solved! Go to Solution.
2025-11-28 5:43 AM
Hello @Torsten_Robitzki
Thank you for bringing this issue to our attention.
I reported this internally.
Internal ticket number: 222757 (This is an internal tracking number and is not accessible or usable by customers).
2025-11-26 11:13 AM - edited 2025-11-26 11:14 AM
The bl instruction places the return address in the lr register. If ExitRun0Mode is a leaf function (does not call other functions), there is no need for the compiler to save lr on the stack, but just to generate a bx lr instruction for return. The current implementation is indeed a leaf function that just sets PWR->CR3 and waits for the PWR_CSR1_ACTVOSRDY condition. No need to touch the stack.
But, interestingly, when compiled in Debug configuration (-O0 optimization), it will use the stack for saving r7 (callers frame pointer):
08000434 <ExitRun0Mode>:
8000434: b480 push {r7}
8000436: af00 add r7, sp, #0
8000438: 4b09 ldr r3, [pc, #36] @ (8000460 <ExitRun0Mode+0x2c>)
800043a: 68db ldr r3, [r3, #12]
800043c: 4a08 ldr r2, [pc, #32] @ (8000460 <ExitRun0Mode+0x2c>)
800043e: f023 0302 bic.w r3, r3, #2
8000442: 60d3 str r3, [r2, #12]
8000444: bf00 nop
8000446: 4b06 ldr r3, [pc, #24] @ (8000460 <ExitRun0Mode+0x2c>)
8000448: 685b ldr r3, [r3, #4]
800044a: f403 5300 and.w r3, r3, #8192 @ 0x2000
800044e: 2b00 cmp r3, #0
8000450: d0f9 beq.n 8000446 <ExitRun0Mode+0x12>
8000452: bf00 nop
8000454: bf00 nop
8000456: 46bd mov sp, r7
8000458: f85d 7b04 ldr.w r7, [sp], #4
800045c: 4770 bx lr
800045e: bf00 nop
8000460: 58024800 .word 0x58024800This is pointless as the caller is the startup code that does not use r7 at that time.
Hmm.
hth
KnarfB
2025-11-26 11:12 PM
I think it's not surprising, that the compiler generate sub-optimal code without any optimization.
Do you think, I read the documentation correctly and the startup code is broken?
2025-11-27 3:10 AM
No no surprise, but it looks like you found a bug.
I don't know the internals, but the cited RM explicitely forbids such access.
Maybe @mƎALLEm can help here.
As a quick workaround, you may add #pragma GCC optimize("O3") to the source code.
hth
KnarfB
2025-11-27 3:29 AM - edited 2025-11-27 3:32 AM
Hello all,
@Torsten_Robitzki your interpretation is correct. That's why ExitRun0Mode() has been introduced and implemented, I think starting from the CubeH7 package V1.7.0 (if I'm not mistaken).
@KnarfB that's and interesting finding. When in level -O3, do you have the access to the stack?
@Saket_Om : could you please check? at this stage the RAM memory should not be accessible.
2025-11-27 4:39 AM
-Os -O1 and better are fine:
080006e8 <ExitRun0Mode>:
80006e8: 4b04 ldr r3, [pc, #16] @ (80006fc <ExitRun0Mode+0x14>)
80006ea: 68da ldr r2, [r3, #12]
80006ec: f042 0202 orr.w r2, r2, #2
80006f0: 60da str r2, [r3, #12]
80006f2: 685a ldr r2, [r3, #4]
80006f4: 0492 lsls r2, r2, #18
80006f6: d5fc bpl.n 80006f2 <ExitRun0Mode+0xa>
80006f8: 4770 bx lr
80006fa: bf00 nop
80006fc: 58024800 .word 0x58024800But there is no guarantee for future/alternate toolchains.
hth
KnarfB
2025-11-27 4:42 AM - edited 2025-11-27 4:43 AM
08000434 <ExitRun0Mode>: 8000434: b480 push {r7} 8000436: af00 add r7, sp, #0 8000438: 4b09 ldr r3, [pc, #36] @ (8000460 <ExitRun0Mode+0x2c>) 800043a: 68db ldr r3, [r3, #12] 800043c: 4a08 ldr r2, [pc, #32] @ (8000460 <ExitRun0Mode+0x2c>) 800043e: f023 0302 bic.w r3, r3, #2 8000442: 60d3 str r3, [r2, #12] 8000444: bf00 nop 8000446: 4b06 ldr r3, [pc, #24] @ (8000460 <ExitRun0Mode+0x2c>) 8000448: 685b ldr r3, [r3, #4] 800044a: f403 5300 and.w r3, r3, #8192 @ 0x2000 800044e: 2b00 cmp r3, #0 8000450: d0f9 beq.n 8000446 <ExitRun0Mode+0x12> 8000452: bf00 nop 8000454: bf00 nop 8000456: 46bd mov sp, r7 8000458: f85d 7b04 ldr.w r7, [sp], #4 800045c: 4770 bx lr 800045e: bf00 nop 8000460: 58024800 .word 0x58024800
That assembly code was generated by CubeIDE?
2025-11-27 1:05 PM
2025-11-28 5:39 AM - edited 2025-11-28 5:45 AM
Hi @KnarfB ,
I may found a solution to that unwanted access to the stack by replacing:
void ExitRun0Mode(void)
by
void __attribute__((naked)) ExitRun0Mode(void)
But this is applicable only for GCC.
With the "naked" attribute: no SP is called:
without "naked" attribute: SP is called:
Could you test from your side?
2025-11-28 5:43 AM
Hello @Torsten_Robitzki
Thank you for bringing this issue to our attention.
I reported this internally.
Internal ticket number: 222757 (This is an internal tracking number and is not accessible or usable by customers).