1

I'm trying to use clang compiler and GNU Arm Embedded Toolchain assembler+linker+libraries to build a LED blinker for STM32F103. My host system is Debian x86_64. I use a Makefile project generated in STM32CubeMX (which is based on GCC) with some changes in makefile. However, the size of result binary file is 16KB, when the bin created using original Cube project is 5KB. What's more, I noticed that using sprintf() (for UART), increases the size to 51KB. I understand that dynamic memory allocation may consume a lot of space, but for the same code the size of bin created in Cube project is only 7KB.

How to decrease the binary size of clang+GNU toolchain configuration?

Compilation:

clang -c --target=armv7m-none-eabi -mcpu=cortex-m3 -mthumb $(INCLUDES) -O2 -fdata-sections -ffunction-sections file.c -o file.o
arm-none-eabi-as startup_stm32f103xb.S -o startup_stm32f103xb.o

Linking:

 clang -v -nostdlib --target=armv7m-none-eabi -mcpu=cortex-m3 \
    --ld-path=/path/to/gcc-arm-none-eabi-9-2020-q2-update/bin/arm-none-eabi-gcc \ 
    -TSTM32F103C8Tx_FLASH.ld \
    -L"/path/to/gcc-arm-none-eabi-9-2020-q2-update/lib/gcc/arm-none-eabi/9.3.1/thumb/v7-m/nofp" \
    -L"/path/to/gcc-arm-none-eabi-9-2020-q2-update/arm-none-eabi/lib/thumb/v7-m/nofp/" \
    $(OBJECTS) startup_stm32f103xb.o \ 
    -o out

Getting binary:

 arm-none-eabi-objcopy -O binary -S out out.bin

Some of the functions and objects are really space-consuming, mainly those related to dynamic memory management, e.g.:

$readelf -a out
...
775: 080049b9  6992 FUNC    GLOBAL DEFAULT    2 _svfprintf_r
964: 20000444  1032 OBJECT  GLOBAL DEFAULT    7 __malloc_av_
993: 08006709  3784 FUNC    GLOBAL DEFAULT    2 _dtoa_r
994: 080078e5  1372 FUNC    GLOBAL DEFAULT    2 _malloc_r
1032: 08008b29  2852 FUNC    GLOBAL DEFAULT    2 _svfiprintf_r
1073: 08009e41  3372 FUNC    GLOBAL DEFAULT    2 _vfiprintf_r
...
yogurt
  • 21
  • 2
  • C libraries are bulky, the printf flavors are massive. one C library implementation is not expected to match another. The real question is why use sfprintf and what can you do to avoid it in a bare metal application. Next is if you have a solution stick with it...why change tools. – old_timer Nov 10 '20 at 16:21
  • dont use any flavor of printf nor most of the C library is the primary way to control your binary sizes. – old_timer Nov 10 '20 at 16:21
  • 2
    use nano stdlib implementation. add -specs=nosys.specs -specs=nano.specs – 0___________ Nov 10 '20 at 17:34
  • I need to do some code transformation in LLVM IR and that's the reason to change to clang. I already have working LLVM project but the binary size increases dramatically even without using printf, malloc etc. so I thought that maybe there is something wrong with my solution. – yogurt Nov 10 '20 at 17:38
  • @P__JsupportswomeninPoland, added these flags, unfortunately there is no change in executable and binary file size – yogurt Nov 10 '20 at 17:50
  • I do not use clang. Use gcc instead. – 0___________ Nov 10 '20 at 17:51
  • You mean use arm-none-eabi-gcc directly instead of invoking it via clang in --ld-path option? I tried and got an error: /path/to/gcc-arm-none-eabi-9-2020-q2-update/arm-none-eabi/lib/thumb/v7-m/nofp/libc.a(lib_a-init.o): in function `__libc_init_array': init.c:(.text.__libc_init_array+0x1e): undefined reference to `_init' – yogurt Nov 10 '20 at 19:37
  • When I remove syscalls.c from sources, I also have undefined references to _sbrk, _exit, _kill, _getpid, _write, _close, _fstat, _isatty, _lseek, _read (even with -specs=nosys.specs) – yogurt Nov 10 '20 at 20:06

0 Answers0