1
0
mirror of https://github.com/rfivet/stm32bringup.git synced 2025-02-21 05:37:09 -05:00
stm32bringup/docs/36_update.html

180 lines
5.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.6 Toolchain Update</title>
<link type="text/css" rel="stylesheet" href="style.css">
</head>
<body>
<h1>3.6 Toolchain Update</h1>
When a new release of GNU ARM Embedded Toolchain comes out, I have to do some
adaptations when switching to it.
<p>
By example, to switch from release 9 update to release 10 major, I made three
changes to <b>Makefile</b>.
<p>
● Update the Linux base directory location:
<pre>
#GCCDIR = $(HOME)/Packages/gcc-arm-none-eabi-9-2020-q2-update
GCCDIR = $(HOME)/Packages/gcc-arm-none-eabi-10-2020-q4-major
</pre>
● Update the Windows base directory location:
<pre>
#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
</pre>
● Update the library subdirectory location:
<pre>
#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/nofp
</pre>
In 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
<code>memset()</code> from the distribution libraries.
<pre>
$ 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 1
</pre>
So I had to add <b>libc.a</b> and its location on top of <b>libgcc.a</b>
to the list of libraries.
<pre>
LIBS = -l$(LIBSTEM) -lc -lgcc
LIB_PATHS = -L. -L$(GCCDIR)/arm-none-eabi/lib/thumb/v6-m/nofp -L$(LIBDIR)
</pre>
with <b>libc.a</b> the link phase complete successfully.
<pre>
f030f4.elf from startup.txeie.o adc.o adcmain.o
text data bss dec hex filename
2644 0 16 2660 a64 f030f4.elf
</pre>
<p>
As I dont want to turn off size optimization and I am not willing to
always pay the full 180 bytes for a production ready <code>memset()</code>
when it is called only once at startup to clear a few bytes, I ended up adding
my own version of <code>memset()</code> to my local library.
<pre>
#include &lt;string.h>
void *memset( void *s, int c, size_t n) {
char *p = s ;
while( n--)
*p++ = c ;
return s ;
}
</pre>
<pre>
LIBOBJS = printf.o putchar.o puts.o memset.o
</pre>
Link succeed with a reduction of 152 bytes of code.
<pre>
f030f4.elf from startup.txeie.o adc.o adcmain.o
text data bss dec hex filename
2492 0 16 2508 9cc f030f4.elf
</pre>
<h2>GCC front end handling the libraries selection</h2>
As I was investigating the compilation flags to find if there was a
better way to solve this issue, I figure out I could let <b>gcc</b> handle
the distribution libraries selection and their location based on the CPU
type. So I changed the linker invocation accordingly and got rid of LD,
LIBDIR and LIB_PATHS definitions.
<pre>
# $(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)
</pre>
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.
<pre>
OBJS = $(SRCS:.c=.o)
LIBOBJS = printf.o putchar.o puts.o # memset.o
CPU = -mthumb -mcpu=cortex-m0 --specs=nano.specs
</pre>
<code>memset()</code> included in the nano version of libc occupies the same
space as my own implementation.
<pre>
f030f4.elf from startup.txeie.o adc.o adcmain.o
text data bss dec hex filename
2492 0 16 2508 9cc f030f4.elf
</pre>
<h2>PATH based command selection</h2>
Finally, I revised the way I specify the commands location by updating the
PATH environment variable in the Makefile instead of giving the full path of
each command.<br>
On Windows, I make sure that drive specification matches the development
environment in use (Cygwin, MSYS2 and other).
<pre>
### 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-14.2.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-14.2.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)size
</pre>
Switching 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
<code>memset()</code> has been skipped by the compiler.
<pre>
f030f4.elf from startup.txeie.o adc.o adcmain.o
text data bss dec hex filename
2464 0 16 2480 9b0 f030f4.elf
</pre>
<h2>Checkpoint</h2>
Invoking the compiler instead of the linker gives more flexibility in
case the toolchain directory structure changes or if I target a
different core. The compiler is aware of the location of the toolchain
libraries while the linker need explicit parameters to handle those
changes.
<p>
<a href="37_inram.html">Next</a>, I will (re)build to execute code in RAM
instead of FLASH.
<hr>© 2020-2025 Renaud Fivet
</body>
</html>