HardFault from printf – freertos 9.0.0 / stm32f0 / gcc-arm-eabi 7.2.0

On my STM32F091 project I’m encountering a HardFault. Frequency of occurence is about weekly. I’m looking for some help debugging this issue as I haven’t been able to reveal the source yet. The program jumps to the hardfault handler during a printf call. This is evident from the serial port debug output. When the hardfault occurs, the code line sync_printf("State changed from %d -> %dn", cur_state, new_state); is interrupted halfway and prints State changed from HardFault_HandlerC(): For context, all my printf calls are surrounded with a mutex block so tasks’ debug output remains coherent: ~~~ int syncprintf(const char* format, …) { valist args; vastart(args, format); int v = 0; if (osMutexWait(pflock, osWaitForever) == osOK) { v += print(0, format, args); osMutexRelease(pflock); } vaend(args); return v; } ~~~ I don’t believe this to cause issues but figure it needs to be mentioned. Bunch of things I tried in order to reveal the root cause: – used a different, malloc-free, printf version (this one is printf-stdarg), but hardfault happens in exactly the same place with newlib-nano printf – configCHECKFORSTACKOVERFLOW=2, configUSEMALLOCFAILEDHOOK=1, configASSERT is defined – the vApplicationStackOverflowHook and vApplicationMallocFailedHook hooks are defined but not called – expanded my tasks’ stack sizes significantly to rule out stack overflowing issue – using heap scheme 4 so no malloc/free Here’s some info from the stack when the hardfault occurs. I’m unsure how to interpret this; my knowledge on the architecture is minimal. ~~~ stackedr0: 0x00000020 stackedr1: 0x20006fe3 stackedr2: 0x20004405 stackedr3: 0x20004401 stackedr12: 0x36c398e5 stackedlr: 0x08005fa1 stacked_pc: 0x08011a56

stacked_psr: 0x01000000

     CFSR: 0x00000000
     HFSR: 0x00000000
     DFSR: 0x00000000
     AFSR: 0x00000000
     MMAR: 0x00000000
     BFAR: 0x00000000
~~~ The stackedpc @ 0x08011a56 points inside the ‘print’ function in the disassembly: ~~~ if (*format == ‘d’) { 0x08011a48 BB 68 ldr r3, [r7, #8] 0x08011a4a 1B 78 ldrb r3, [r3, #0] 0x08011a4c 64 2B cmp r3, #100 ; 0x64 0x08011a4e 0F D1 bne.n 0x8011a70 <print+312> pc += printi(out, vaarg(args, int), 10, 1, width, pad, ‘a’); 0x08011a50 7B 68 ldr r3, [r7, #4] 0x08011a52 1A 1D adds r2, r3, #4 0x08011a54 7A 60 str r2, [r7, #4] 0x08011a56 19 68 ldr r1, [r3, #0] 0x08011a58 F8 68 ldr r0, [r7, #12] 0x08011a5a 61 23 movs r3, #97 ; 0x61 0x08011a5c 02 93 str r3, [sp, #8] 0x08011a5e 01 96 str r6, [sp, #4] 0x08011a60 00 95 str r5, [sp, #0] 0x08011a62 01 23 movs r3, #1 0x08011a64 0A 22 movs r2, #10 0x08011a66 FF F7 EB FE bl 0x8011840 0x08011a6a 03 00 movs r3, r0 0x08011a6c E4 18 adds r4, r4, r3 continue; 0x08011a6e 5F E0 b.n 0x8011b30 <print+504> } ~~~ The printing functions are taken from https://github.com/atgreen/FreeRTOS/blob/master/Demo/CORTEXSTM32F103Primer_GCC/printf-stdarg.c Any guidance on finding the root cause or obtaining more information in order to be able to do so is highly appreciated. Frank

HardFault from printf – freertos 9.0.0 / stm32f0 / gcc-arm-eabi 7.2.0

The instruction at the stored program counter, 0x08011a56, is (if that is the offending instruction – it might be the instruction prior to that that generates the fault):
ldr r1, [r3, #0]
This instruction is loading a 32-bit value from the address stored in r3. r3 in turn has an address loaded from a 4-byte offset from the start of the stack frame (instruction at 0x08011a50). That address is not aligned – is that expected? Not sure if that would cause the fault (can’t remember but the ARM V7-M manual will tell you) but it looks odd to load a 32-bit value from an odd (as opposed to even) address.

HardFault from printf – freertos 9.0.0 / stm32f0 / gcc-arm-eabi 7.2.0

LDR/STR instructions supports unaligned accesses (but can generate a bus fault if CCR.UNALIGN_TRP is set, which in my case it isn’t). In this case, the value that is to be printed is an enum value (C++ enum class, no forced type) with global scope. So the value being taken from the variadic arguments list is this one, unless that value was copied onto the stack during the printf call. Either way, location of that is dword aligned so I’m not sure if this could be the issue here.