By example, to switch from release 9 update to release 10 major, I made three changes to Makefile.
● Update the Linux base directory location:
#GCCDIR = $(HOME)/Packages/gcc-arm-none-eabi-9-2020-q2-update GCCDIR = $(HOME)/Packages/gcc-arm-none-eabi-10-2020-q4-major● Update the Windows base directory location:
#GCCDIR = D:/Program Files (x86)/GNU Arm Embedded Toolchain/9 2020-q2-update GCCDIR = D:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2020-q4-major● Update the library subdirectory location:
#LIBDIR = $(GCCDIR)/lib/gcc/arm-none-eabi/9.3.1/thumb/v6-m/nofp LIBDIR = $(GCCDIR)/lib/gcc/arm-none-eabi/10.2.1/thumb/v6-m/nofpIn the case of release 10 major, unfortunately while doing some regression testing by recompiling the projects so far, I found that the new release optimizes further the C startup clearing of BSS data by calling
memset()
from the distribution libraries.
$ make f030f4.elf from startup.txeie.o adc.o adcmain.o D:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2020-q4-major\bin\arm-none- eabi-ld.exe: startup.txeie.o: in function `Reset_Handler': D:\Renau\Documents\Projects\stm32bringup\docs/startup.txeie.c:126: undefined ref erence to `memset' make: *** [mk8:61: f030f4.elf] Error 1So I had to add libc.a and its location on top of libgcc.a to the list of libraries.
LIBS = -l$(LIBSTEM) -lc -lgcc LIB_PATHS = -L. -L$(GCCDIR)/arm-none-eabi/lib/thumb/v6-m/nofp -L$(LIBDIR)with libc.a the link phase complete successfully.
f030f4.elf from startup.txeie.o adc.o adcmain.o text data bss dec hex filename 2644 0 16 2660 a64 f030f4.elf
As I don’t want to turn off size optimization and I am not willing to
always pay the full 180 bytes for a production ready memset()
when it is called only once at startup to clear a few bytes, I ended up adding
my own version of memset()
to my local library.
#include <string.h> void *memset( void *s, int c, size_t n) { char *p = s ; while( n--) *p++ = c ; return s ; }
LIBOBJS = printf.o putchar.o puts.o memset.oLink succeed with a reduction of 152 bytes of code.
f030f4.elf from startup.txeie.o adc.o adcmain.o text data bss dec hex filename 2492 0 16 2508 9cc f030f4.elf
# $(LD) -T$(LD_SCRIPT) $(LIB_PATHS) -Map=$(PROJECT).map -cref -o $@ $(OBJS) $(LIBS) $(CC) $(CPU) -T$(LD_SCRIPT) -L. -Wl,-Map=$(PROJECT).map,-cref \ -nostartfiles -o $@ $(OBJS) -l$(LIBSTEM)As the compiler front end is now controlling the libraries selection it is possible to give it a hint how to select a better optimized memset(). The libc library comes in two flavors: regular and nano.
OBJS = $(SRCS:.c=.o) LIBOBJS = printf.o putchar.o puts.o # memset.o CPU = -mthumb -mcpu=cortex-m0 --specs=nano.specs
memset()
included in the nano version of libc occupies the same
space as my own implementation.
f030f4.elf from startup.txeie.o adc.o adcmain.o text data bss dec hex filename 2492 0 16 2508 9cc f030f4.elf
### Build environment selection ifeq (linux, $(findstring linux, $(MAKE_HOST))) INSTALLDIR = $(HOME)/Packages #REVDIR = gcc-arm-none-eabi-10-2020-q4-major REVDIR = arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi else DRIVE = d ifeq (cygwin, $(findstring cygwin, $(MAKE_HOST))) OSDRIVE = /cygdrive/$(DRIVE) else ifeq (msys, $(findstring msys, $(MAKE_HOST))) OSDRIVE = /$(DRIVE) else OSDRIVE = $(DRIVE): endif INSTALLDIR = $(OSDRIVE)/Program Files (x86) #REVDIR = GNU Arm Embedded Toolchain/10 2020-q4-major REVDIR = GNU Arm Embedded Toolchain/arm-gnu-toolchain-13.3.rel1-mingw-w64-i686-arm-none-eabi endif GCCDIR = $(INSTALLDIR)/$(REVDIR) export PATH := $(GCCDIR)/bin:$(PATH) BINPFX = @arm-none-eabi- AR = $(BINPFX)ar CC = $(BINPFX)gcc OBJCOPY = $(BINPFX)objcopy OBJDUMP = $(BINPFX)objdump SIZE = $(BINPFX)sizeSwitching back to latest version of the toolchain at the time of writing this, the link shows further improvement of the code size. The optimization via
memset()
has been skipped by the compiler.
f030f4.elf from startup.txeie.o adc.o adcmain.o text data bss dec hex filename 2464 0 16 2480 9b0 f030f4.elf
Next, I will (re)build to execute code in RAM instead of FLASH.