STM32でlibopencm3を使ってLチカ

libopencm3を使ってSTM32に接続したLEDをチカチカをしてみました。

[libopencm3](http://www.libopencm3.org/)は、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出力する。

```c: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;
}

```

```c: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から持ってきて、すぐコンパイルができるのが良いです。