cancel
Showing results for 
Search instead for 
Did you mean: 

Printing with GCC: printf() function never calls custom _write()

Spectramax
Associate II

Hello,

I've spent quite a bit of time scratching my head and I would appreciate any guidance in this matter.

I am using Segger's Embedded Studio with Segger's RTT printf library. Everything works fine with the Segger_RTT_printf() output. I can see the output it in the terminal, no issue.

Segger also provides a SEGGER_RTT_Syscalls.c which implements the following so I can overload printf() function:

#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM)
 
#include <reent.h>  // required for _write_r
#include "SEGGER_RTT.h"
 
struct _reent;
 
int _write(int file, char *ptr, int len);
int _write_r(struct _reent *r, int file, const void *ptr, size_t len);
 
int _write(int file, char *ptr, int len) {
  (void) file;  /* Not used, avoid warning */
  SEGGER_RTT_Write(0, ptr, len);
  return len;
}
 
int _write_r(struct _reent *r, int file, const void *ptr, size_t len) {
  (void) file;  /* Not used, avoid warning */
  (void) r;     /* Not used, avoid warning */
  SEGGER_RTT_Write(0, ptr, len);
  return len;
}
 
#endif

I can compile and link OK. But, when I debug, the printf() function never calls my custom _write() function.

Instead, the debugger jumps to the following disassembly:

<iprintf>
<printf>
    B40F        push {r0-r3}
    4B0A        ldr r3, =0x20000080 <_impure_ptr>
    B513        push {r0-r1, r4, lr}
    681C        ldr r4, [r3]
    B124        cbz r4, 0x0802E1EC
    69A3        ldr r3, [r4, #24]
    B913        cbnz r3, 0x0802E1EC
    4620        mov r0, r4
    F7FFFE00    bl 0x0802DDEC <__sinit>
    AB05        add r3, sp, #20
    9A04        ldr r2, [sp, #16]
    68A1        ldr r1, [r4, #8]
    9301        str r3, [sp, #4]
    4620        mov r0, r4
    F000FC4D    bl 0x0802EA94 <_vfiprintf_r>
    B002        add sp, sp, #8
    E8BD4010    pop.w {r4, lr}
    B004        add sp, sp, #16
    4770        bx lr
    20000080    .word 0x20000080

How can I can link it properly? I am using GCC ARM compiler version 8.0.

Thank you!

1 ACCEPTED SOLUTION

Accepted Solutions
Spectramax
Associate II

I have managed to fix this issue by changing the linker from arm-eabi-none-g++ to arm-eabi-none-gcc.

These options can be found in your Project Options > Code > External Build inside Segger Embedded Studio.

In retrospect, this was pretty obvious that the linker was not linking newlib/gcc stdlib and was not able to overload _write() and _write_r() custom functions inside of SEGGER_RTT_GCC_Syscalls.c

Hope this helps!

View solution in original post

2 REPLIES 2
Spectramax
Associate II

I have managed to fix this issue by changing the linker from arm-eabi-none-g++ to arm-eabi-none-gcc.

These options can be found in your Project Options > Code > External Build inside Segger Embedded Studio.

In retrospect, this was pretty obvious that the linker was not linking newlib/gcc stdlib and was not able to overload _write() and _write_r() custom functions inside of SEGGER_RTT_GCC_Syscalls.c

Hope this helps!

IShar.4
Associate

@Spectramax answer is incomplete.

If C compiler is used then declaration below would be sufficient

int _write(int file, char *ptr, int len) {
  (void) file;  /* Not used, avoid warning */
  SEGGER_RTT_Write(0, ptr, len);
  return len;
}

But when it comes to C++ compiler, then all names are mangled and linker is unable to match the symbol. So in essence extern "C" declaration needs to be used. Wrap it into proper #ifdefs or other fluff.

Minimal working version:

extern "C" int _write(int file, char *ptr, int len) {
  (void) file;  /* Not used, avoid warning */
  SEGGER_RTT_Write(0, ptr, len);
  return len;
}