HardFault Issue with Clang Compilation for FreeRTOS on QEMU (MPS2 AN385 - Cortex-M3)

Hello FreeRTOS Community,
I’m currently encountering a recurring issue with task creation in FreeRTOS that leads to a HardFault, and I’m hoping to get some insights or suggestions from the community. Here’s a detailed description of my problem:
Environment:

  • Compiler: Clang
  • Platform: Ubuntu22.04
  • Target: ARM Cortex-M3
  • FreeRTOS Version: commit 022447b855880b3e618bdc6cf3030ec282d37fe2

Issue Description:
I have successfully compiled and run the demo using GCC following the instructions from the FreeRTOS website on the MPS2 AN385 model.

However, after switching the compiler to Clang in the makefile, I managed to compile successfully, but running the program results in a HardFault. I’m using the following command to run the program on QEMU:

qemu-system-arm -machine mps2-an385 -cpu cortex-m3 -kernel [path-to]/RTOSDemo.out -monitor none -nographic -serial stdio -s -S

Debugging Output: Here’s the call stack when the HardFault occurs:

(gdb) bt
#0  HardFault_Handler () at startup_gcc.c:188
#1  <signal handler called>
#2  0x00001b90 in prvCreateTask (pxTaskCode=0x7621 <prvSendFrontAndBackTest>, pcName=<optimized out>,
    uxStackDepth=<optimized out>, pvParameters=<optimized out>, uxPriority=0, pxCreatedTask=0x0 <isr_vector>)
    at ./../../../..//Source/tasks.c:1682
#3  xTaskCreate (pxTaskCode=0x7621 <prvSendFrontAndBackTest>, pcName=0xcf3 "GenQ", uxStackDepth=80,
    pvParameters=0x20000b40 <ucHeap+8>, uxPriority=0, pxCreatedTask=0x0 <isr_vector>)
    at ./../../../..//Source/tasks.c:1730
#4  0x00007588 in vStartGenericQueueTasks (uxPriority=0) at ./../../../..//Demo/Common/Minimal/GenQTest.c:169
#5  0x0000ddc4 in main_full () at ./../../../..//Demo/CORTEX_MPS2_QEMU_IAR_GCC/main_full.c:149
#6  0xfffffffe in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Additionally, the CFSR register is set to 0x10000 , indicating an UNDEFINSTR error; the HFSR is 0x40000000 , with the FORCED bit set.

Execution Flow:

  • The program starts at main() and proceeds to vStartGenericQueueTasks in /Demo/Common/Minimal/GenQTest.c.
  • It successfully creates a queue using xQueueCreate.
  • Upon successful queue creation, it calls xTaskCreate in /Source/tasks.c line 1731, which in turn calls prvCreateTask in /Source/tasks.c:1670.
  • The crash occurs at a memset after successfully allocating stack space with pvPortMallocStack and allocating the TCB with pvPortMalloc.

The program does not reach vTaskStartScheduler() in the execution flow.

Request for Suggestions: I am at a loss on how to proceed with debugging this issue. Does anyone have experience with similar issues when using Clang for FreeRTOS, or any suggestions on potential causes or further debugging steps I should take?

Thank you in advance for any help or insights!

I presume other tasks have already been created successfully. Can you look at the parameters of memset() to ensure they point to valid RAM memory. That would help determine if the err was inside memset, or already occurred before memset gets called.

1 Like

Thank you for your prompt response and assistance.
I went back to the memset() statement ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );and printed the corresponding values for debugging.
The value of pxNewTCB is (TCB_t *) 0x20000940 <ucHeap+444> , and sizeof(TCB_t) is 92, which should not cause any overflow.
However, I then encountered a HardFault, so I’m puzzled about where the issue might be.

Debugging Output:

prvCreateTask (pxTaskCode=0xb2c1 <prvSendFrontAndBackTest>, pcName=0xd2b "GenQ", uxStackDepth=80, 
    pvParameters=0x20000790 <ucHeap+12>, uxPriority=0, pxCreatedTask=0x0 <isr_vector>)
    at ./../../../..//Source/tasks.c:1680
1680                    if( pxNewTCB != NULL )
(gdb) 
1682                        ( void ) memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
(gdb) p sizeof(TCB_t)
$1 = 92
(gdb) p pxNewTCB
$2 = (TCB_t *) 0x20000940 <ucHeap+444>
(gdb)  x/92b 0x20000940
0x20000940 <ucHeap+444>:        0       0       0       0       0       0       0       0
0x20000948 <ucHeap+452>:        0       0       0       0       0       0       0       0
0x20000950 <ucHeap+460>:        0       0       0       0       0       0       0       0
0x20000958 <ucHeap+468>:        0       0       0       0       0       0       0       0
0x20000960 <ucHeap+476>:        0       0       0       0       0       0       0       0
0x20000968 <ucHeap+484>:        0       0       0       0       0       0       0       0
0x20000970 <ucHeap+492>:        0       0       0       0       0       0       0       0
0x20000978 <ucHeap+500>:        0       0       0       0       0       0       0       0
0x20000980 <ucHeap+508>:        0       0       0       0       0       0       0       0
0x20000988 <ucHeap+516>:        0       0       0       0       0       0       0       0
0x20000990 <ucHeap+524>:        0       0       0       0       0       0       0       0
0x20000998 <ucHeap+532>:        0       0       0       0
(gdb) info symbol 0x200009a0
ucHeap + 540 in section .bss.ucHeap
(gdb) s
HardFault_Handler () at startup_gcc.c:188
188         __asm volatile

which memory manager do you use? Does your linker command file map the heap section correctly?

1 Like

heap_4.c
I made modifications based on the existing FreeRTOS/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC without changing the memory management scheme.
The linker script is also the default one, located at Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/GCC/mps2_m3.ld. The version is FreeRTOS V202212.00. For convenience, I have attached the content.

MEMORY
{
    FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 4M /* to 0x00003FFF = 0x007FFFFF*/
    RAM (rw)  : ORIGIN = 0x20000000, LENGTH = 4M /* to 0x21FFFFFF = 0xFFFFFF */
}
ENTRY(Reset_Handler)

_Min_Heap_Size = 0x8 ;        /* Not used as building heap_4.c */
_Min_Stack_Size = 0x400 ;       /* Required amount of stack.  Used by main(), then re-used as the interrupt stack after the kernel starts. */
_estack = ORIGIN(RAM) + LENGTH(RAM);


SECTIONS
{
    .isr_vector :
    {
        __vector_table = .;
        KEEP(*(.isr_vector))
        . = ALIGN(4);
    } > FLASH

    .text :
    {
        *(.text)
        *(.rodata*)
        *(.constdata*)
        _etext = .;
        _sidata = .;
    } > FLASH

    .data :
    {
        . = ALIGN(8);
        _data = .;
        _sdata = .;
        *(vtable)
        *(.data)
        _edata = .;
    } > RAM

    .bss :
    {
        . = ALIGN(8);
        _bss = .;
        _sbss = .;
        *(.bss)
        _ebss = .;
    } > RAM
    
    .heap :
    {
        . = ALIGN(8);
        PROVIDE ( end = . );
        PROVIDE ( _end = . );
        _heap_bottom = .;
        . = . + _Min_Heap_Size;
        _heap_top = .;
        . = . + _Min_Stack_Size;
        . = ALIGN(8);
   } >RAM
   
   /* Set stack top to end of RAM, and stack limit move down by
    * size of stack_dummy section */
   __StackTop = ORIGIN(RAM) + LENGTH(RAM);
   __StackLimit = __StackTop - _Min_Stack_Size;
   PROVIDE(__stack = __StackTop);
     
  /* Check if data + heap + stack exceeds RAM limit */
  ASSERT(__StackLimit >= _heap_top, "region RAM overflowed with stack")
  
}

I am not very familiar with the specific technical details in this area. Could you please let me know if there is anything I need to pay attention to?
Thank you for your help!

to which data section of RAM is your heap array in heap_4.c mapped? Can you share your map file output?

1 Like

I found the RTOSDemo.map file in the output folder, but I’m not sure if it’s the correct information:

20000000 20000000        0     1 .bss
20000000 20000000        0     1         . = ALIGN ( 8 )
20000000 20000000        0     1         _bss = .
20000000 20000000        0     1         _sbss = .
20000000 20000000        0     1         _ebss = .
20000000 20000000      408     1 .heap
20000000 20000000        0     1         . = ALIGN ( 8 )
20000000 20000000        0     1         _heap_bottom = .
20000000 20000000        8     1         . = . + _Min_Heap_Size
20000008 20000008        0     1         _heap_top = .
20000008 20000008      400     1         . = . + _Min_Stack_Size
20000408 20000408        0     1         . = ALIGN ( 8 )
20000408 20000408        0     1 __StackTop = ORIGIN ( RAM ) + LENGTH ( RAM )
20000408 20000408        0     1 __StackLimit = __StackTop - _Min_Stack_Size
...
20000784 20000784    19000     1 .bss.ucHeap
20000784 20000784    19000     1         ./output/heap_4.o:(.bss.ucHeap)
20000784 20000784    19000     1                 ucHeap

If you need any further information, please let me know. Thank you very much for your help.

is it possible for you to publish your complete map file?

1 Like

Of course! Since the content is quite long, I have pasted it in the link :https://pastebin.com/LKYdV0EK
If you need any additional information, please feel free to let me know. I truly appreciate your time and assistance!

looks ok from my side. Have you enabled task stack checking?

1 Like

Yes, I have enabled task stack checking. Here is the relevant configuration in FreeRTOSConfig.h :

#define configCHECK_FOR_STACK_OVERFLOW           2

And the vApplicationStackOverflowHook function have been implementationed as follows:

void vApplicationStackOverflowHook( TaskHandle_t pxTask,
                                    char * pcTaskName )
{
    ( void ) pcTaskName;
    ( void ) pxTask;

    /* Run time stack overflow checking is performed if
     * configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
     * function is called if a stack overflow is detected. */
    printf( "\r\n\r\nStack overflow in %s\r\n", pcTaskName );
    portDISABLE_INTERRUPTS();

    for( ; ; )
    {
    }
}

The vApplicationStackOverflowHook function is originally included in the demo, but it is present in main and not in main_full . My call stack shows main_full . Could this be related to the bug I am encountering?

UNDEFINSTR in the CFSR the code is trying to execute an incorrect instruction. Can you check the assembly at the memset address? Perhaps you can singlestep into memset? If the incorrect memset function was linked in you may have instructions that are not supported by your CPU.

This cannot be caused by the FreeRTOS scheduler as the vTaskStartScheduler() has not happened yet. This cannot be a task stack overflow because tasks are not running yet.

1 Like

As an experiment, can you try to create a bare metal application without FreeRTOS and see if it works? This will help us in narrowing down if the problem is with FreeRTOS or with compiler or compiler options.

1 Like

Thank you very much for your help.
I checked the assembly code for memset and it seems there is an issue. Here is the content:

(gdb) info address memset
Symbol "memset" is at 0x18fa4 in a file compiled without debugging.
(gdb) disassemble memset
Dump of assembler code for function memset:
   0x00018fa4 <+0>:     movs    r3, r0
   0x00018fa6 <+2>:     b.n     0x195ca
   0x00018fa8 <+4>:     lsls    r0, r0, #1
   0x00018faa <+6>:     lsrs    r0, r0, #8
   0x00018fac <+8>:     movs    r0, r0
   0x00018fae <+10>:    b.n     0x19656
   0x00018fb0 <+12>:    movs    r0, #1
   0x00018fb2 <+14>:    b.n     0x1943a
   0x00018fb4 <+16>:    vrhadd.u16      d0, d14, d31
   0x00018fb8 <+20>:    adds    r0, #0
   0x00018fba <+22>:    b.n     0x192fe
   0x00018fbc <+24>:    stmia   r0!, {r0, r1, r2, r3, r4, r5, r6, r7}
   0x00018fbe <+26>:    b.n     0x193c4
   0x00018fc0 <+28>:    movs    r2, r0
   0x00018fc2 <+30>:    and.w   r0, r0, r1, lsl #8
   0x00018fc6 <+34>:    b.n     0x1944e
   0x00018fc8 <+36>:    movs    r1, r0
--Type <RET> for more, q to quit, c to continue without paging--c
   0x00018fca <+38>:    b.n     0x196b2
   0x00018fcc <+40>:    vrhadd.u16      d0, d14, d31
   0x00018fd0 <+44>:    stmia   r0!, {r0}
   0x00018fd2 <+46>:    b.n     0x1895c <_fclose_r+356>
   0x00018fd4 <+48>:    movs    r3, r0
   0x00018fd6 <+50>:    b.n     0x19600
   0x00018fd8 <+52>:                    ; <UNDEFINED> instruction: 0xfff91aff
   0x00018fdc <+56>:    movs    r3, r0
   0x00018fde <+58>:    b.n     0x19686
   0x00018fe0 <+60>:    movs    r0, r5
   0x00018fe2 <+62>:    ldr     r2, [sp, #0]
   0x00018fe4 <+64>:    ands    r0, r6
   0x00018fe6 <+66>:    stmdb   sp!, {r0, r1, r2, r3, r4, r5, r6, r7, sp, lr, pc}
   0x00018fea <+70>:    b.n     0x193f0
   0x00018fec <+72>:    b.n     0x1880c <_fclose_r+20>
   0x00018fee <+74>:    b.n     0x1930e
   0x00018ff0 <+76>:    movs    r7, r1
   0x00018ff2 <+78>:    b.n     0x1969a
   0x00018ff4 <+80>:                    ; <UNDEFINED> instruction: 0xe80ee18e
   0x00018ff8 <+84>:    movs    r6, r5
   0x00018ffa <+86>:    ldr     r2, [sp, #0]
   0x00018ffc <+88>:    stmia   r0!, {r4}
   0x00018ffe <+90>:    b.n     0x19486
   0x00019000 <+92>:    ands    r7, r1
   0x00019002 <+94>:    b.n     0x1979e
   0x00019004 <+96>:    str     r0, [r4, r0]
   0x00019006 <+98>:    b.n     0x19510
   0x00019008 <+100>:   str     r4, [r0, r0]
   0x0001900a <+102>:   b.n     0x19118 <__sread+40>
   0x0001900c <+104>:   tst     r4, r5
   0x0001900e <+106>:   b.n     0x19352
   0x00019010 <+108>:   stmia   r0!, {r4}
   0x00019012 <+110>:   b.n     0x1951c
   0x00019014 <+112>:   b.n     0x19038 <memset+148>
   0x00019016 <+114>:   b.n     0x18a32 <_malloc_trim_r+206>
   0x00019018 <+116>:   b.n     0x19034 <memset+144>
   0x0001901a <+118>:   b.n     0x18a36 <_malloc_trim_r+210>
   0x0001901c <+120>:   b.n     0x19030 <memset+140>
   0x0001901e <+122>:   b.n     0x18a3a <_malloc_trim_r+214>
   0x00019020 <+124>:   b.n     0x1902c <memset+136>
   0x00019022 <+126>:   b.n     0x18a3e <_malloc_trim_r+218>
   0x00019024 <+128>:   stmia   r0!, {r4}
   0x00019026 <+130>:   b.n     0x19542
   0x00019028 <+132>:   movs    r5, r0
   0x0001902a <+134>:   b.n     0x192e6
   0x0001902c <+136>:                   ; <UNDEFINED> instruction: 0xfff81aff
   0x00019030 <+140>:   stmia   r0!, {r0}
   0x00019032 <+142>:   b.n     0x1953e
   0x00019034 <+144>:   movs    r4, r1
   0x00019036 <+146>:   b.n     0x1965e
   0x00019038 <+148>:   stmia   r2!, {r2, r3}
   0x0001903a <+150>:   b.n     0x19144 <__swrite+32>
   0x0001903c <+152>:   movs    r0, #15
   0x0001903e <+154>:   b.n     0x19446
   0x00019040 <+156>:   movs    r0, r3
   0x00019042 <+158>:   lsrs    r0, r0, #8
   0x00019044 <+160>:   adds    r0, #4
   0x00019046 <+162>:   b.n     0x194ce
   0x00019048 <+164>:   adds    r0, #3
   0x0001904a <+166>:   b.n     0x197d4
   0x0001904c <+168>:   adds    r0, #4
   0x0001904e <+170>:   b.n     0x19558
   0x00019050 <+172>:   adds    r0, #3
   0x00019052 <+174>:   b.n     0x1916e <__swrite+74>
   0x00019054 <+176>:   b.n     0x19060 <memset+188>
   0x00019056 <+178>:   b.n     0x18972 <_malloc_trim_r+14>
   0x00019058 <+180>:   movs    r4, r1
   0x0001905a <+182>:   b.n     0x19304
   0x0001905c <+184>:                   ; <UNDEFINED> instruction: 0xfffc1aff
   0x00019060 <+188>:   movs    r0, #3
   0x00019062 <+190>:   b.n     0x1946a
   0x00019064 <+192>:   movs    r0, r0
   0x00019066 <+194>:   b.n     0x1970e
   0x00019068 <+196>:   movs    r4, r0
   0x0001906a <+198>:   lsrs    r0, r0, #8
   0x0001906c <+200>:   asrs    r7, r7, #3
   0x0001906e <+202>:   b.n     0x19474
   0x00019070 <+204>:   movs    r0, #2
   0x00019072 <+206>:   b.n     0x1917c <__swrite+88>
   0x00019074 <+208>:   asrs    r1, r0, #32
   0x00019076 <+210>:   b.n     0x18a00 <_malloc_trim_r+156>
   0x00019078 <+212>:   movs    r3, r0
   0x0001907a <+214>:   b.n     0x19322
   0x0001907c <+216>:                   ; <UNDEFINED> instruction: 0xfffc1aff
   0x00019080 <+220>:   ands    r0, r6
   0x00019082 <+222>:   ldmia.w sp!, {r1, r2, r3, r4, r8, r9, r10, r11, r12, sp, lr, pc}
   0x00019086 <+226>:   b.n     0x192e8
   0x00019088 <+228>:   movs    r0, r0
   0x0001908a <+230>:   b.n     0x19732
   0x0001908c <+232>:   vrhadd.u16      d0, d14, d31
   0x00019090 <+236>:   asrs    r7, r7, #3
   0x00019092 <+238>:   b.n     0x19498
   0x00019094 <+240>:   movs    r0, #2
   0x00019096 <+242>:   b.n     0x191a0 <__sseek+32>
   0x00019098 <+244>:   asrs    r1, r0, #32
   0x0001909a <+246>:   b.n     0x18a24 <_malloc_trim_r+192>
   0x0001909c <+248>:   movs    r3, r0
   0x0001909e <+250>:   b.n     0x19346
   0x000190a0 <+252>:                   ; <UNDEFINED> instruction: 0xfffc1aff
   0x000190a4 <+256>:   vrhadd.u16      d14, d14, d31
   0x000190a8 <+260>:   adds    r0, #12
   0x000190aa <+262>:   b.n     0x193ee
   0x000190ac <+264>:                   ; <UNDEFINED> instruction: 0xffeceaff
   0x000190b0 <+268>:   adds    r0, #0
   0x000190b2 <+270>:   b.n     0x193f6
   0x000190b4 <+272>:                   ; <UNDEFINED> instruction: 0xffc8eaff
   0x000190b8 <+276>:   stmia   r0!, {r0, r1}
   0x000190ba <+278>:   b.n     0x193fe
   0x000190bc <+280>:                   ; <UNDEFINED> instruction: 0xffe0eaff
End of assembler dump.

This reminded me that initially, to avoid compilation errors, I manually added the following functions in main.c:

int _write_r(int file, char *ptr, int len) {
    return len;
}

int _close_r(int file) {
    // return -1;
    return 0;
}

int _lseek_r(int file, int ptr, int dir) {
    return 0;
}

int _read_r(int file, char *ptr, int len) {
    return 0;
}

Without these functions, the compilation error message is as follows:

ld.lld: error: undefined symbol: _read
>>> referenced by readr.c
>>>               lib_a-readr.o:(_read_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _lseek
>>> referenced by lseekr.c
>>>               lib_a-lseekr.o:(_lseek_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _close
>>> referenced by closer.c
>>>               lib_a-closer.o:(_close_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _write
>>> referenced by writer.c
>>>               lib_a-writer.o:(_write_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a
clang: error: ld.lld command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:108:output/RTOSDemo.out]

It seems like the issue might be caused by not properly resolving the compilation errors.
How should I address this? Thank you very much for your assistance.

Hello, I have used this Clang compilation commands to compile a regular program and encountered compilation errors. The compilation commands and error messages are as follows:

clang --target=arm-none-eabi --sysroot=/home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none
-eabi -mcpu=cortex-m3 -mthumb  -L/usr/lib/gcc/arm-none-eabi/10.3.1 -lc -lm -lgcc -o test hello.c
ld.lld: error: undefined symbol: _sbrk
>>> referenced by sbrkr.c
>>>               lib_a-sbrkr.o:(_sbrk_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _read
>>> referenced by readr.c
>>>               lib_a-readr.o:(_read_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _write
>>> referenced by writer.c
>>>               lib_a-writer.o:(_write_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _lseek
>>> referenced by lseekr.c
>>>               lib_a-lseekr.o:(_lseek_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _close
>>> referenced by closer.c
>>>               lib_a-closer.o:(_close_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _fstat
>>> referenced by fstatr.c
>>>               lib_a-fstatr.o:(_fstat_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _isatty
>>> referenced by isattyr.c
>>>               lib_a-isattyr.o:(_isatty_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _exit
>>> referenced by abort.c
>>>               lib_a-abort.o:(abort) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _kill
>>> referenced by signalr.c
>>>               lib_a-signalr.o:(_kill_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a

ld.lld: error: undefined symbol: _getpid
>>> referenced by signalr.c
>>>               lib_a-signalr.o:(_getpid_r) in archive /home/mdd/gcc-arm-none-eabi-10.3-2021.10/arm-none-eabi/lib/libc.a
clang: error: ld.lld command failed with exit code 1 (use -v to see invocation)

These errors are very similar to the ones I encountered when compiling FreeRTOS.
After adding functions in main.c, the compilation was successful, but unfortunately, it seems this did not fundamentally resolve the issue.
Do you have any suggestions? Thank you very much!

Those functions are required by your libc i.e. standard C-library coming with the compiler toolchain and are unrelated to FreeRTOS and most likely to your hard fault problem.
Try google how this is usually solved/implemented. Often a dedicated syscalls.c file with the (dummy)) implementations is added.

Looks like you need to review your toolchain and make sure the correct files are installed.