GitHub - glegrain:STM32-with-macOS
GitHub - glegrain:STM32-with-macOS
com/glegrain/STM32-with-macOS
glegrain / STM32-with-macOS
Dismiss
Join GitHub today
GitHub is home to over 40 million developers working together to host
and review code, manage projects, and build software together.
Sign up
README.md
Although this tutorial has been written with macOS in mind, similar steps can be applied to Linux or Windows machines.
1 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
Restarting/reset:
Looking at the code (useful when TUI mode is disabled):
Show next assembly instructions:
Getting help:
Other/Advanced GDB:
Editing your Makefile
Adding source files:
Adding Includes:
Adding Preprocessor defines:
Changing optimization options:
Understanding compiler options and flags:
Serial console:
Using semihosting:
Using UART:
Option 1 - GNU Screen
Option 2 - Minicom
Using ITM messages over SWO:
Other Resources:
Issues:
Debugging tips (Part 2?)
Requirements:
STM32CubeMX to generate project templates
STM32CubeProgrammer to easily program STM32 products using a GUI
A hardware development board (e.g. a NUCLEO-L476RG board)
macOS Command Line Tools (CLT)
Homebrew package manager (recommended to install gcc-arm-embedded, openOCD and stlink)
GNU ARM Embedded Toolchain (arm-none-eabi) for compiler and other tools
OpenOCD (>= 0.10.0) or texane/stlink for programming and running a GDB server
1. Install Xcode Command Line Tools (CLT). This will install Make and other UNIX goodies:
$ xcode-select --install
After the Command Line Tools were successfully installed, the remaining toolchain requirements can be installed using
Homebrew.
4. Install OpenOCD:
2 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
http://openocd.org/doc/doxygen/bugs.html
6. Install STM32CubeMX. After Downloading the installer, extract the archieve and try to run the macOS installer. If the
macOS installer doesn't work, use the following command to manually launch the install. The procedure is described
in the STM32CubeMX User Manual UM1718.
$ cd ~/Downloads/
$ unzip en.stm32cubemx.zip -d en.stm32cubemx
$ cd en.stm32cubemx
$ java -jar SetupSTM32CubeMX-4.26.1.exe
If the above command does not work, you could try installing java8 :
And Java 8 will be installed at /Library/Java/JavaVirtualMachines/jdk1.8.xxx.jdk/ . You can then use the full java
path to use version 1.8 to launch the STM32CubeProgrammer setup.
$ /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/bin/java -jar
SetupSTM32CubeProgrammer-1.0.0.exe
Pro Tip: Create a symbolic link to one of the binary directory searched by your $PATH variable:
$ ln -sv /Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/STM32CubeProgrammer.app
/Contents/MacOs/bin/STM32_Programmer_CLI /usr/local/bin/
Then, STM32_Programmer_CLI can be invoked diectly without having to specify the full path:
$ STM32_Programmer_CLI
-------------------------------------------------------------------
STM32CubeProgrammer v1.1.0
-------------------------------------------------------------------
Usage :
STM32_Programmer_CLI.exe [command_1] [Arguments_1][[command_2] [Arguments_2]...]
If you are also using an NUCLEO-L476RG, you can use the example "blinky" project by cloning the following repo:
1. Create a New Project, and select your part number or development board
3 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
For more information, refer to the STM32CubeMX User Manual available on st.com. Usefull sections include:
Unfortunately, Makefiles generated by CubeMX do not work out-of-the-box. You need to edit the file and set your
compiler path. Luckily, this step only has to be done once. Later on, if you want to add source, header files or simply
change your compiler options, refer to the [Editing your Makefile] section for more details.
$ which arm-none-eabi-gcc
/usr/local/bin/arm-none-eabi-gcc
2. Open up the Makefile with your favorite text editor to set the BINPATH variable to the location of your compiler
returned above:
#######################################
# binaries
#######################################
BINPATH = /usr/local/bin
PREFIX = arm-none-eabi-
CC = $(BINPATH)/$(PREFIX)gcc
AS = $(BINPATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(BINPATH)/$(PREFIX)objcopy
AR = $(BINPATH)/$(PREFIX)ar
SZ = $(BINPATH)/$(PREFIX)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
Pro Tip: To make the Makefile more portable between different users and environment, you can remove the BINPATH
variable and edit the CC , AS , CP , AR , SZ as shown bellow. This way, make will look for binaries in your environment
(i.e. executables located in your $PATH setting):
#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
AR = $(PREFIX)ar
SZ = $(PREFIX)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
4 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
In a Terminal, navigate to your project's root directory (or Makefile location). Then use the make command to invoke the
Makefile to compile your project:
$ cd ~/path/to/Example_Project
$ make
Pro Tip: for faster build time, make can be invoked using parallel build with the -j option:
$ make -j 4
If all goes well, you should see a result without any errors or warning:
$ make
...
arm-none-eabi-size build/Example_Project.elf
text data bss dec hex filename
8880 24 1688 10592 2960 build/Example_Project.elf
arm-none-eabi-objcopy -O ihex build/Example_Project.elf build/Example_Project.hex
arm-none-eabi-objcopy -O binary -S build/Example_Project.elf build/Example_Project.bin
Pro Tip: The Makefile generated by CubeMX comes with a predefined rule called clean to delete all generated files
during the build process (object files, binaries, ... in the build/ directory). This rule is very useful to force rebuild all or
to cleanup the project directory before packaging your project for archiving.
$ make clean
rm -fR .dep build
5 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
Note: Because STM32CubeProgrammer is still relatively new, chances are you will have to upgrade your ST-Link
firmware.
For more information, you can refer to the STM32CubeProgrammer User Manual
/Applications/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/MacOs/bin/STM32_Programmer_CLI -c
port=SWD -e all
/Applications/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/MacOs/bin/STM32_Programmer_CLI -c
port=SWD mode=UR reset=HWrst -e all # hold reset button then release when connecting
/Applications/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/MacOs/bin/STM32_Programmer_CLI -c
port=SWD -w build/Example_Project.elf
$ st-util
$ ls /usr/local/Cellar/open-ocd/0.10.0/share/openocd/scripts/board/
$ ls /usr/local/Cellar/open-ocd/0.10.0/share/openocd/scripts/interface/
$ ls /usr/local/Cellar/open-ocd/0.10.0/share/openocd/scripts/target/
6 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
For example, you could the following command to program and verify using elf/hex/s19 files. Verify, reset and exit are
optional parameters. Binary files need the flash address passing.
5 - Debugging
Because you will be debugging a remote target device, GDB needs to connect to a gdbserver compliant debugger.
Before launching GDB, you need to start a GDB server using your debugger to act as an interface between GDB and your
device.
$ st-util
$ st-util --no-reset # to attach while running
$ st-util -p 3333 # for OpenOCD version of .gdbinit compatibility
Here is my .gdbinit . Place this file in your project's root directory, next to your Makefile:
file "./build/Example_Project.elf"
2. Launch GDB. GDB will execute commands from the .gdbinit script when launched
$ arm-none-eabi-gdb
...
Loading section .isr_vector, size 0x188 lma 0x8000000
Loading section .text, size 0x1708 lma 0x8000188
Loading section .rodata, size 0x50 lma 0x8001890
7 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
Pro Tip: Launch GDB in GDB in Text User Interface (TUI) mode to show the source file and GDB commands in separate
windows:
$ arm-none-eabi-gdb -tui
Program stepping/execution:
https://sourceware.org/gdb/onlinedocs/gdb/Continuing-and-Stepping.html
Step over (step to next line of C code without going into functions):
(gdb) next
90 SystemClock_Config();
(gdb) n
97 MX_GPIO_Init();
(gdb)
(gdb) step
SystemClock_Config () at ./Src/main.c:124
124 {
(gdb) finish
Run till exit from #0 SystemClock_Config () at ./Src/main.c:124
main () at ./Src/main.c:97
97 MX_GPIO_Init();
(gdb) continue
Continuing.
Pro Tip: for most command, you can simply type in the first letter. e.g. n for next .
Pro Tip: Press enter to repeat the previous command. Very usefull to quickly step trough a program.
Pro Tip: gdb also supports TAB completion. e.g cont + TAB will result in continue .
Setting a breakpoint:
https://sourceware.org/gdb/onlinedocs/gdb/Breakpoints.html#Breakpoints http://www.unknownroad.com/rtfm/gdbtut
/gdbbreak.html
From there, you can add breakpoints using any of the following methods in the GDB command:
8 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
Break on function:
List breakpoints:
Remove a breakpoint:
(gdb) delete 2
(gdb) disable 3
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0800207e in main at ./Src/main.c:83
breakpoint already hit 1 time
3 breakpoint keep n 0x08001fd0 in SystemClock_Config at ./Src/main.c:132
Manipulating registers:
https://community.st.com/s/question/0D50X00009XkeAmSAJ/reading-io-register-values-with-command-line-gdb
https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/Debugging-Options.html
Include additional debug information, such as all the macro definitions that can be used to inspect I/O registers:
9 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
1. Edit you Makefile to add the -g3 option to the compiler flags
CFLAGS += -g3
Level 3 includes extra information, such as all the macro definitions present in the program. Some debuggers support
macro expansion when you use -g3.
2. In GDB, type:
(gdb) p /x *GPIOA
$4 = {MODER = 0xabfff7ff, OTYPER = 0x0, OSPEEDR = 0xc000000, PUPDR = 0x64000000,
IDR = 0xc020, ODR = 0x20, BSRR = 0x0, LCKR = 0x0, AFR = {0x0, 0x0}, BRR = 0x0,
ASCR = 0x0}
(gdb) set GPIOA->ODR ^= 0x20
(gdb) p /x TIM3->CCMR1
(gdb) backtrace
#0 HAL_RCC_OscConfig (RCC_OscInitStruct=RCC_OscInitStruct@entry=0x20017fac)
at ./Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c:409
#1 0x08001ff4 in SystemClock_Config () at ./Src/main.c:141
#2 0x08002086 in main () at ./Src/main.c:90
Restarting/reset:
(gdb) n
107 HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
(gdb) list
102
103 /* Infinite loop */
104 /* USER CODE BEGIN WHILE */
105 while (1)
106 {
107 HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
108 HAL_Delay(200);
109
110 /* USER CODE END WHILE */
111
(gdb) n
108 HAL_Delay(200);
(gdb) tui enable
10 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
Getting help:
Other/Advanced GDB:
Using gdb-dashboard (do not use TUI mode) to get more complex window configuration (similarly to an IDE):
$ arm-none-eabi-gdb-py
######################################
# source
######################################
# C sources
C_SOURCES = \
./Src/main.c \
./Src/new_file.c \
./Src/stm32l4xx_it.c \
./Src/syscalls.c \
./Src/system_stm32l4xx.c \
# ASM sources
ASM_SOURCES = \
./startup_stm32l476xx.s
Pro Tip: I prefixed my paths with ./ to help vim trigger file path completion.
Adding Includes:
# C includes
C_INCLUDES = \
-IInc \
-IDrivers/STM32L4xx_HAL_Driver/Inc \
-IDrivers/STM32L4xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32L4xx/Include \
-IDrivers/CMSIS/Include
Pro Tip: if the compiler complains about a missing header file for example:
use find . -name "usbd_msc.h" to get the path and add it to Makefile:
11 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
# C defines
C_DEFS = \
-DUSE_HAL_DRIVER \
-DSTM32L476xx \
-D__DEBUG__
# optimization
OPT = -Os
Serial console:
On embedded devices, printf statements can become very useful for debugging. Retargeting the C printf function
is generally done is one of three ways:
Using semihosting:
Semihosting is relatively easy to setup but it is one of the slowest methods for printing debug messages. Enable
semihosting (see example .gdbinit )
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471m/pge1358787046598.html
Using UART:
Note: With GCC, add syscalls.c
$ ls /dev/tty.usbmodem*
/dev/tty.usbmodem413
8 bit, no parity, one stop bit, translate input new line carriage return, newline performs a carriage return, local echo
12 of 13 12/12/2019 20:11
GitHub - glegrain/STM32-with-macOS https://github.com/glegrain/STM32-with-macOS
Option 2 - Minicom
https://mcuoneclipse.com/2016/10/17/tutorial-using-single-wire-output-swo-with-arm-cortex-m-and-eclipse/
http://blog.japaric.io/itm/
Other Resources:
Issues:
When creating a brand new project (example NUCLEO-L476RG), C source files under Src/ are defined multiple times.
mdw
flash program
flash mass_erase
viewing registers and SFRs
reg
mdw
semihosting
Linker file
13 of 13 12/12/2019 20:11