libopencm3
Installation
create a new folder and cd it with a terminal
load the LibOpenCM3 source code from github with
git clone https://github.com/libopencm3/libopencm3.git (blocks with with git://github.com/libopencm3/libopencm3.git)
or download and extract the zip file libopencm3-master.zip
The 3 following files are missing:
./include/libopencm3/stm32/l4/nvic.h
./include/libopencmsis/stm32/l4/irqhandlers.h
./lib/stm32/l4/vector_nvic.c
Create the missing files with a python script:
irq2nvic_h: generate an nvic.h header from a small JSON file describing the interrupt numbers
$python3 ./scripts/irq2nvic_h ./include/libopencm3/stm32/l4/irq.json
with:
irq_json
{
"irqs": [
"wwdg",
"pvd_pvm",
"tamp_stamp",
"rtc_wkup",
"flash",
"rcc",
"exti0",
...
"exti4",
"dma1_channel1",
...
"dma1_channel7",
"adc1_2",
"can1_tx",
"can1_rx0",
"can1_rx1",
"can1_sce",
"exti9_5",
"tim1_brk_tim15",
"tim1_up_tim16",
"tim1_trg_com_tim17",
"tim1_cc",
"tim2",
"tim3",
"tim4",
"i2c1_ev",
"i2c1_er",
"i2c2_ev",
"i2c2_er",
"spi1",
"spi2",
"usart1",
"usart2",
"usart3",
"exti15_10",
"rtc_alarm",
"dfsdm3",
"tim8_brk",
"tim8_up",
"tim8_trg_com",
"tim8_cc",
"adc3",
"fmc",
"sdmmc1",
"tim5",
"spi3",
"uart4",
"uart5",
"tim6_dacunder",
"tim7",
"dma2_channel1",
...
"dma2_channel5",
"dfsdm0",
"dfsdm1",
"dfsdm2",
"comp",
"lptim1",
"lptim2",
"otg_fs",
"dma2_channel6",
"dma2_channel7",
"lpuart1",
"quadspi",
"i2c3_ev",
"i2c3_er",
"sai1",
"sai2",
"swpmi1",
"tsc",
"lcd",
"aes",
"rng",
"fpu",
"hash_crs",
"i2c4_ev",
"i2c4_er",
"dcmi",
"can2_tx",
"can2_rx0",
"can2_rx1",
"can2_sce",
"dma2d"
],
"partname_humanreadable": "STM32 L4 series",
"partname_doxygen": "STM32L4",
"includeguard": "LIBOPENCM3_STM32_L4_NVIC_H"
}
Compile the STM32L4 library with:
$make V=1 TARGETS='stm32/l4 stm32/h7'
The first line is
./scripts/irq2nvic_h ./include/libopencm3/stm32/h7/irq.json;
So, the last command with python seems to be obsolete.
This “make” create all the necessary object files.
$make TARGETS='stm32/l4 stm32/h7'
BUILD lib/stm32/l4
CC adc.c
.
.
AR libopencm3_stm32l4.a
BUILD lib/stm32/h7
CC dac_common_all.c
.
.
CC dwt.c
AR libopencm3_stm32h7.a
It also create the equivalent of zip files for libraries: libopencm3_stm32l4.a and libopencm3_stm32h7.a
The AR program (arm-none-eabi-ar) can create, modify and extract from archives.
Makefile for ‘c’ programs using libopencm3
create, modify, and extract from archives Let’s have a small c program:
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#define LED_PORT GPIOA
#define LED_RED GPIO5
// function prototype
int foo (int a);
extern int foo (int a)
{
a=rcc_system_clock_source();
rcc_periph_clock_enable(RCC_GPIOA);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_RED);
gpio_set_output_options(LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_LOW, LED_RED);
gpio_set(LED_PORT, LED_RED);
return a;
}
In the Makefile, we need to add the following operations:
tell the linker the location and the name of the opencm3 library
define the stm32 family
specify the floating point method
Location and name of the opencm3 library
OPENCM3_DIR := ../../libopencm3
CFLAGS = -mcpu=cortex-m4 -Wall -Wextra -Werror -g3 -O0 -fstack-usage
CFLAGS += -Wundef -Wshadow -Wimplicit-function-declaration -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
CFLAGS += -fno-common -ffunction-sections -fdata-sections -MD
CFLAGS += --specs=nosys.specs -save-temps -fverbose-asm -I$(OPENCM3_DIR)/include/
CFLAGS += -v -D STM32L4 -mfloat-abi=hard -mthumb
The I flag shows the header path (.h):
-I$(OPENCM3_DIR)/include/
To get out of the source c directory to be able to reach the opencm3 library, we need to do 2 cd ..: it explains “../../libopencm3” in OPENCM3_DIR.
Define the stm32 family
The -D STM32L4 flag for the c compiler loader specifies the MCU in use. This flag will prevents an error in a number of header files (gpio.h, rcc.h, …) of the libopencm3 library when the STM32 device is unknown:
#if defined(STM32F0)
# include <libopencm3/stm32/f0/gpio.h>
...
#elif defined(STM32L4)
# include <libopencm3/stm32/l4/rcc.h>
...
#elif defined(STM32H7)
# include <libopencm3/stm32/h7/rcc.h>
...
#else
# error "stm32 family not defined."
#endif
Specify the floating point method
The ‘-mfloat-abi=hard’ flag prevents the following error:
arm-none-eabi-ld: failed to merge target specific data of file libopencm3_stm32l4.a(gpio_common_f0234.o)
arm-none-eabi-ld: error: libopencm3_stm32l4.a(rcc.o) uses VFP register arguments, gpio.elf does not
The M4 has a hardware floating point unit (FPU) with Virtual Floating Point (VFP) registers.
# Used libraries #LDFLAGS += -L$(OPENCM3_DIR)/lib #LDLIBS += -l$(LIBNAME)
# all: gpio.elf LIBNAME = opencm3_stm32l4
# Used libraries #LDLIBS += -l$(LIBNAME) #LDLIBS := -Wl,–start-group -lc -lgcc -lnosys -Wl,–end-group LDLIBS := -lc -lnosys
# $(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(*).elf
# —————————————————————————- gpio.elf: gpio.o clockGPIO.o config_GPIO.o lab.o
arm-none-eabi-ld -Ttext 0x8000000 -Tdata=0x20000000 $(LDLIBS) gpio.o config_GPIO.o clockGPIO.o lab.o libopencm3_stm32l4.a -g -o gpio.elf
- gpio.o: gpio.s
arm-none-eabi-as -mthumb -g gpio.s -o gpio.o
- clockGPIO.o: sub1.s
arm-none-eabi-as -mthumb -g sub1.s -o clockGPIO.o
- config_GPIO.o: sub2.s
arm-none-eabi-as -mthumb -g sub2.s -o config_GPIO.o
- lab.o: lab.c $(OPENCM3_DIR)/lib/libopencm3_stm32l4.a
arm-none-eabi-gcc -c $(CFLAGS) lab.c -o lab.o