this is my first post here, so forgive me if I violate a rule.
I’ve encountered a strange behavior when compiling the CM3 port *without* optimization.
My first build was a release build with -O2 optimization and it worked perfectly. Then I turned to the debug version (with -g3 an -O0) and I got a HardFaultException after some msec. I couldn’t get the exact reason or position of the crash because the link register is pointing to 0xfffffffc
I made plenty of tests with the result that, whenever I turn on a kind of optimization the code works. -O1 is enough.
The compiler was the CodeWork 2008q3-66 release. Any hints?
CM3 automatically pushes a set of registers on exception, and the LR of 0xfffffffc is a magic value indicating something like the exception-return requirements. You can find the actual return address (or exception address) by looking on the stack (which is pointed to by SP). IIRC, the automatically-pushed registers are R0-R3 and LR.
I can’t help you with your compiler optimization problem, though. Perhaps you’re running out of memory and/or stack if the compiler doesn’t optimize its usage?
I’ve never heard of CodeWord, but presume this is a GCC build? If so then I would also assume it is based on the CodeSourcery as that is the only source of CM3 GCC that I am aware of.
Is your startup code written in C or ASM? If C then can you ascertain whether or not main() is ever called. If the code crashed before main is called on a CM3 then the most likely cause is a loop that clears the RAM being corrupted. If the loop is written in C then without optimisation the loop variables will be read from and written back to RAM on each iteration of the loop - and the loop will most likely zero out these variables. When optimisation is on the loop variables will be held in registers so zeroing out the RAM does not corrupt the loop variables.
One easy solution to this is to keep optimisation on just for the startup code, even when the rest of the code uses zero optimisation.
Sorry, I meant CodeSourcery, my fault.
The stack seems to be OK, I’ve filled all the memory with a pattern, checked it and additionaly watched the sbrk() result (using the heap_3 implementation).
I will read the CM3 manual, check the exception cause and post the results tomorrow
The LR contenet of 0xfffffffx signalizes the type of exception return. Then I checked the state of the "Configurable fault status register" the cause of the exception was this:
"INVSTATE: Invalid state usage fault:
When this bit is set to 1, the PC value stacked for the exception return points to the instruction that attempted the illegal use of the EPSR. …"
But the stacked PC value already points to a non memory location
I might get a Lauterbach with ETM memory next week, but I’m not sure if it works with Cortex nor if it is licenced for Cortex.
I assume a fault in my code or build environment, I don’t think it’s a problem with the compiler or FreeRTOS, but I will try a different compiler.
To answer the other questions:
the startup code is written in ‘C’, memory fill and dump for the stack check was made via JTAG.
The whole project consists of my code, the STM32 firmware lib and FreeRTOS. The only portion of code which requires the optimization is FreeRTOS. All other parts are build with -O0.
The behavior also occurs when I just start one LED flash task. I can observe one scheduler call (SVCHandler) before I get the exception.
All functions are implemented like this:
void PendSVC(void) {DefaultHandler();}
The default handler ends in a loop with flashing LEDs to indicate an unhandeled exception.
Normally the linker will create a weak binding and if he finds a non weak binding, he replaces the function pointer with the address of the non weak function.
But, and I’m not clear why, it doesn’t work with naked functions like this:
void PendSVHandler( void ) __attribute__ (( naked ));
I looked to some old arm code and I’m pretty much sure it worked with ARM. Anyway I removed the weak bindings
Definitely do NOT use the naked attribute on CortexM3 interrupts. That will make it crash for sure. Use the examples in the download as a reference that can be copied.
You can use the naked attribute for sure. The only point is to take care of the stackframe. A scheduler usually doesn’t use normal ‘C’ function stackframes because you don’t leave the scheduler like a normal function, you’re activating a different thread. There is no easy (and generic) way to restore the stack modified when entering the scheduler.
Look at the file .\FreeRTOSV5.2.0\Source\portable\GCC\ARM_CM3\port.c I guess you use it also