Per Community-PIO-CH32V/framework-wch-noneos-sdk#14.
When compiling a project that uses deepsleep (and thus the WFE function) per
|
__attribute__( (section(".highcode")) ) void WFE(uint32_t t) |
|
{ |
|
asm volatile ("wfi"); |
|
asm volatile ("1:addi a0, a0, -1\n\t" \ |
|
"bnez a0, 1b\n\t" \ |
|
); |
|
} |
with LTO enabled (-flto in compiler and linker), the function gets "optimized" incorrectly, by removing the instruction that writes the value of the argument to the function.
The function is written incorrectly and unsafely, since it does not reference the input parameter t inside the body of the function (which is usually passed in the a0 register), the input parameter can be removed from the function, yet the inline assembly inside the function expects a0 to be filled be holding the value of the input parameter t.
As a result, firmwares compiled with LTO and using WFE essentially never wake up from sleep, because a0 may hold a very large value, and that is used as the "number of cycles to delay after wakeup".
An alternative version
__attribute__( (section(".highcode")) ) void WFE(uint32_t t)
{
/* Force t into RISC-V a0 so the delay loop works */
register uint32_t a0 asm("a0") = t;
asm volatile (
"wfi\n"
"1: addi a0, a0, -1\n"
" bnez a0, 1b\n"
:
: "r"(a0)
: "memory"
);
}
works correctly when compiled with LTO enabled.
Per Community-PIO-CH32V/framework-wch-noneos-sdk#14.
When compiling a project that uses deepsleep (and thus the WFE function) per
ch32v003/EVT/EXAM/SRC/Core/core_riscv.c
Lines 285 to 291 in 2ac6803
with LTO enabled (
-fltoin compiler and linker), the function gets "optimized" incorrectly, by removing the instruction that writes the value of the argument to the function.The function is written incorrectly and unsafely, since it does not reference the input parameter
tinside the body of the function (which is usually passed in the a0 register), the input parameter can be removed from the function, yet the inline assembly inside the function expects a0 to be filled be holding the value of the input parameter t.As a result, firmwares compiled with LTO and using WFE essentially never wake up from sleep, because
a0may hold a very large value, and that is used as the "number of cycles to delay after wakeup".An alternative version
works correctly when compiled with LTO enabled.