I started with RTX_ex2 and got it running on an STM32F3Discovery board with uVision V5.10.0.2 Then I ported this example to a Makefile based project that builds with gcc 4.8 downloaded from here: launchpad.net/gcc-arm-embedded
I customized startup.S to initialize and start RTX before calling main on an osThread and got the same program running.
Next I modified RTX_Conf_CM.c so OS_TIMERS = 1 and I added a one-shot timer that calls a function after 5 seconds. This works fine in the uVision project but the one built w/ gcc crashes as soon as the timer goes off.
Unfortunately I have not been able to get gdb working so I don't know where the problem is. I suspect that I am not correctly initializing RTX in my gcc version. Does anybody have an idea of where I might have gone wrong? Another working Makefile/gcc based program using RTX would also be very helpful.
Thanks, Marc
Move the out.elf into a Keil project out.axf, and use the Keil Debugger to load/debug the GNU/GCC created executable.
I tried debugging with Keil as you suggested, but uVision crashed every time that I tried to start a debug session. It would successfully download the image to the target and then crash.
Since that didn't work, I took the plunge and got gdb working from the command line and was able to find the problem.
This function from rt_CMSIS.c starts at line 1175 in CMSIS 3.20.4:
// Timer Thread __NO_RETURN void osTimerThread (void const *argument) { osCallback cb; osEvent evt; for (;;) { evt = osMessageGet(osMessageQId_osTimerMessageQ, osWaitForever); if (evt.status == osEventMessage) { cb = osTimerCall(evt.value.p); if (cb.fp != NULL) { (*(os_ptimer)cb.fp)(cb.arg); <----- crashes here } } } }
The crash happens on the line that tries to invoke the callback function. Stepping through the disassembly revealed that the correct function pointer is in one register but the branch instruction is using a different register that holds the pointer to cb in RAM. I recompiled libRTX_CM4.a using the uvproj in C:\Keil\ARM\Pack\ARM\CMSIS\3.20.4\CMSIS_RTX\SRC\GCC with the toolchain set to my download of gcc-arm-none-eabi-4_8-2013q4-win32 from launchpad. If I turn optimization off, then everything works correctly. However, at O1, O2, or O3 my program crashes.
For gcc, osTimerCall is returning a special type (around line 149 of rt_CMSIS.c):
typedef uint32_t __attribute__((vector_size(8))) ret64; #define osCallback_type ret64 #define osCallback_ret (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg}
I don't quite understand what this doing, but it appears that the optimizer is getting confused about which register holds the function pointer. I don't know if this is a compiler optimization bug or a RTX implementation problem, but I am convinced that the optimized version of libRTX_CM4.a for gcc is broken.
A workaround for this is to disable optimization at line 1072 of rt_CMSIS.c
change: os_InRegs osCallback_type svcTimerCall (osTimerId timer_id) {
to: os_InRegs osCallback_type __attribute__((optimize("O0"))) svcTimerCall (osTimerId timer_id) {
I noticed that uVision debugger would crash when loading ELF files produced by gcc 4.8. It works fine with gcc 4.7.