libopencm3を使ってSTM32に接続したLEDをチカチカをしてみました。
libopencm3は、Cortex Mシリーズ向けの LGPLv3なライブラリです。
使用ハードウェア
- NUCLEO-F103RB
- STM32F103RBT6が載っている。
- ボードのバージョンはMB1136 C-03
- ST-LINKが内蔵されている。 ST-LINKのFWを最新版に上げてから使いました。
- LEDはPA5に接続されている。
ソフトのインストール
- MAC homebrewを使っている前提です。
- 下記のコマンドでstlinkとコンパイラをインストールします。
$ brew install stlink
$ brew tap PX4/homebrew-px4
$ brew update
$ brew install gcc-arm-none-eabi
サンプルコード
- LEDチカチカのサンプルは https://github.com/dword1511/stm32-vserprog を元に作りました。
- コードの説明
- GPIOを使うためにに、rcc_periph_clock_enable()でポートのクロックを有効にする。
- gpio_set_mode()で、GPIOの出力モードに設定する。
- gpio_set()で、GPIOをHigh出力する。
lchika.c
# include <stdio.h>
# include <libopencm3/stm32/rcc.h>
# include <libopencm3/stm32/gpio.h>
# include "board.h"
# define LED_ENABLE() gpio_set_mode(BOARD_PORT_LED, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, BOARD_PIN_LED)
# define LED_DISABLE() gpio_set_mode(BOARD_PORT_LED, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, BOARD_PIN_LED)
# define LED_BUSY() gpio_set(BOARD_PORT_LED, BOARD_PIN_LED)
# define LED_IDLE() gpio_clear(BOARD_PORT_LED, BOARD_PIN_LED)
int main(void) {
uint32_t i;
rcc_periph_clock_enable(BOARD_RCC_LED);
LED_ENABLE();
LED_BUSY();
while (1) {
LED_DISABLE();
for (i = 0; i < rcc_ahb_frequency / 5; i ++) {
asm("nop");
}
LED_ENABLE();
LED_BUSY();
for (i = 0; i < rcc_ahb_frequency / 5; i ++) {
asm("nop");
}
}
return 0;
}
board.h
# ifndef __BOARD_H__
# define __BOARD_H__
# include <libopencm3/stm32/rcc.h>
# include <libopencm3/stm32/gpio.h>
# define BOARD_RCC_LED RCC_GPIOA
# define BOARD_PORT_LED GPIOA
# define BOARD_PIN_LED GPIO5
# endif /* __BOARD_H__ */
コンパイル
- libopencm3をgitで持ってくる。
$ git clone https://github.com/libopencm3/libopencm3.git
- stm32-vserprog のMakefileを元にMakefileを作った。
# Makefile
###############################################################################
PROGRAM = stm32-lchika
CROSS ?= arm-none-eabi
OBJS = lchika.o
###############################################################################
ARCH_FLAGS = -DSTM32F1 -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd
LDSCRIPT = libopencm3/lib/stm32/f1/stm32f103xb.ld
LIBOPENCM3 = libopencm3/lib/libopencm3_stm32f1.a
OPENCM3_MK = lib/stm32/f1
###############################################################################
CC = $(CROSS)-gcc
LD = $(CROSS)-ld
OBJCOPY = $(CROSS)-objcopy
OBJDUMP = $(CROSS)-objdump
SIZE = $(CROSS)-size
ELF = $(PROGRAM).elf
BIN = $(PROGRAM).bin
MAP = $(PROGRAM).map
DMP = $(PROGRAM).out
all:
@make firmware
CFLAGS += -O3 -Wall -g
CFLAGS += -fno-common -ffunction-sections -fdata-sections
CFLAGS += $(ARCH_FLAGS) -Ilibopencm3/include/ $(EXTRA_CFLAGS)
LIBC = $(shell $(CC) $(CFLAGS) --print-file-name=libc.a)
LIBNOSYS = $(shell $(CC) $(CFLAGS) --print-file-name=libnosys.a)
LIBGCC = $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
# LDPATH is required for libopencm3 ld scripts to work.
LDPATH = libopencm3/lib/
LDFLAGS += -L$(LDPATH) -T$(LDSCRIPT) -Map $(MAP) --gc-sections
LDLIBS += $(LIBOPENCM3) $(LIBC) $(LIBNOSYS) $(LIBGCC)
firmware: $(LIBOPENCM3) $(BIN) $(DMP) size
$(ELF): $(LDSCRIPT) $(OBJS)
$(LD) -o $@ $(LDFLAGS) $(OBJS) $(LDLIBS)
$(DMP): $(ELF)
$(OBJDUMP) -d $< > $@
%.bin: %.elf
$(OBJCOPY) -S -O binary $< $@
%.o: %.c board.h
$(CC) $(CFLAGS) -c $< -o $@
$(LIBOPENCM3):
CFLAGS="$(CFLAGS)" make -C libopencm3 $(OPENCM3_MK) V=1
.PHONY: clean size
clean:
rm -f $(OBJS) $(ELF) $(BIN) $(MAP) $(DMP)
size: $(PROGRAM).elf
@echo ""
@$(SIZE) $(PROGRAM).elf
@echo ""
- makeする。 (makeするとlibopencm3もコンパイルするが、ログは割愛)
$ make
arm-none-eabi-gcc -O3 -Wall -g -fno-common -ffunction-sections -fdata-sections -DSTM32F1 -mthumb -mcpu=cortex-m3 -msoft-float -mfix-cortex-m3-ldrd -Ilibopencm3/include/ -c lchika.c -o lchika.o
arm-none-eabi-ld -o stm32-lchika.elf -Llibopencm3/lib/ -Tlibopencm3/lib/stm32/f1/stm32f103xb.ld -Map stm32-lchika.map --gc-sections lchika.o libopencm3/lib/libopencm3_stm32f1.a /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m/libc.a /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m/libnosys.a /usr/local/Cellar/gcc-arm-none-eabi-49/20150609/bin/../lib/gcc/arm-none-eabi/4.9.3/armv7-m/libgcc.a
arm-none-eabi-objcopy -S -O binary stm32-lchika.elf stm32-lchika.bin
arm-none-eabi-objdump -d stm32-lchika.elf > stm32-lchika.out
text data bss dec hex filename
808 4 0 812 32c stm32-lchika.elf
ダウンロード
- st-flashを使ってstm32-lchika.binをflashのある0x8000000に書き込む。
- st-flashはeraseも自動的に行ってくれるので、openocdより楽です。
$ st-flash write stm32-lchika.bin 0x8000000
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Loading device parameters....
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Device connected is: F1 Medium-density device, id 0x20036410
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x20000 bytes (128 KiB) in pages of 1024 bytes
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Attempting to write 816 (0x330) bytes to stm32 address: 134217728 (0x8000000)
Flash page at addr: 0x08000000 erased
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Finished erasing 1 pages of 1024 (0x400) bytes
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Starting Flash write for VL/F0/F3 core id
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Successfully loaded flash loader in sram
0/0 pages written
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Starting verification of write complete
2016-10-26T08:16:20 INFO /tmp/stlink-20160608-18806-p6zk82/stlink-1.2.0/src/stlink-common.c: Flash written and verified! jolly good!
結果
- STM32 Nucleo Board STMF32F103 で LEDがチカチカしました。
- STのライブラリを用意するのが面倒なので、libopencm3を使ってみました。
- libopencm3は、githubから持ってきて、すぐコンパイルができるのが良いです。