If your board has a crystal oscillator fitted (usually a shiny aluminium oval thing with e.g. “8.000” (MHz) written on it, then you can probably reset back to the original sInternalOsc = 0
to use that proper oscillator. The quartz will be a more frequency-stable clock source, and the PLL can also boost it to a higher frequency than with the internal oscillator. The problem seems to have been all the
etc variables which should have been volatile U32 *const
instead. (A constant memory address at which a volatile 32-bit unsigned integer can be found).
You should also note that debug_builds_flags
is only applied when debugging. If you want to always build with -O0
instead of the PlatformIO-default of -Os
(optimize for size), then you have to instead write (docs, docs)
; Remove default -Os, compile with -O0 instead
build_flags = -O0
build_unflags = -Os
It is of course concerning that the firmware code only works when compiler optimizations are disabled. Correctly written code should always work, regardless of compiler optimization level. The code you’re working it seems very buggy, or only having ever been tested in a project that had -O0
.
What I’ve also often seen that this very often happens when people port their projects from the e.g. IAR compiler to the GCC compiler. The IAR compiler recognizes these peripheral write / wait loops and does not optimize them away. Thus, although the programmer has written non-confirming code in regards what is actually wanted, the program works, and they never notice any problems.
Also be aware that this for delay loops like
for (int i = 0; i < 9999999; i++) {
; // do nothing
}
IAR will see this and faithfulll do 9999999 iterations of doing nothing, while GCC under any optimization level greater than 0 will optimize this entire loop away since it has no effect. Thus, the loop creates no delay, and then things can break very subtly if a certain delay is needed at some points (e.g., waiting after sending a character, or waiting a few microseconds before doing something else).
The again correct way would be
for (volatile int i = 0; i < 9999999; i++) {
; // do nothing
}
to disable this optimization, forcing the compiler into actually executing this loop (and incrementing i
). Finely tuned delay loops like this might also need an adjustment of their upper value (9999999 in this case), since IAR and GCC might translate the code slightly differently, causing a different number of instructions to be executed.
See: