STM32 Nucleo Board実行ファイル作成

#STM32 Nucleo Board実行ファイル作成
[RaspberryPiでSTM32開発環境の構築](https://qiita.com/mitazet/items/bfa944c0583b88cf486f)でプログラム作成について省略したため、
ここで実行ファイルの作成を行う。
##開発ターゲット
STM32 Nucleo Board STM32F303K8
[startup]: https://qiita.com/mitazet/items/54713ec4e89f0b57ac6e
[linker]: https://qiita.com/mitazet/items/83ddd6cdffc43dd42f21
##実行ファイル作成に必要なもの
実行ファイル作成は次のような流れになる。
![design.png](https://qiita-image-store.s3.amazonaws.com/0/140055/8b09c0d0-18b8-197b-53f4-96b65bb3e0c7.png)
以上から実行ファイル作成にはスタートアップルーチン、メインプログラム、リンカスクリプト、Makefileが必要になる。
###スタートアップルーチン
スタートアップルーチンは[STM32 Nucleo Boardスタートアップルーチン][startup]のstartup_stm32f303x8.sを使用する。
###リンカスクリプト
リンカスクリプトは[STM32 Nucleo Boardリンカスクリプト][linker]のSTM32F303K8Tx_FLASH.ldを使用する。
環境へ取り込むにあたってSTM32F303K8.ldとファイル名を変更。
###メインプログラム
このプログラムはLEDを点滅させる(Lチカ)プログラム。
詳細はこの記事では省略するが、GPIO B3が本体のLEDとつながっており、
GPIO B3出力のHigh/Lowを繰り返すことで点滅させる。

```c:main.c
#include "stm32f303x8.h"

void ConfigureTIM6(void)
{
    RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;
    TIM6->PSC = 9999;
    TIM6->ARR = 4200 * 2;
    TIM6->CNT = 0;
    TIM6->CR1 |= TIM_CR1_CEN;
}

void ConfigureGPIOB3(void)
{
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;

    GPIOB->MODER = GPIO_MODER_MODER3_0;
    GPIOB->OTYPER = 0x0000;
    GPIOB->PUPDR = 0x000000000;
}

// Main -----------------------------------------------------------------------
int main(void)
{
    ConfigureTIM6();
    ConfigureGPIOB3();
    
    int i = 0;

    // Loop forever
    while(1){
        if(TIM6->SR){
            TIM6->SR = 0;
            if(GPIOB->ODR & GPIO_ODR_3){
                GPIOB->ODR &= ~GPIO_ODR_3;
            }else{
                GPIOB->ODR |= GPIO_ODR_3;
            }
            i++;
        }
	}
	return 0;
}
```

###Makefile
Makefileは[ソフトウェアまわりの備忘録](http://gmaj7sus4.hatenablog.com/entry/2013/12/18/165224)を参考に作成。

```make:Makefile
# Minimal makefile for STM32F3 Neucleo board.
TARGET := arm-none-eabi

# devtools
CC := $(TARGET)-gcc
LD := $(TARGET)-ld
AS := $(TARGET)-as
OBJCOPY := $(TARGET)-objcopy
STFLASH := st-flash
PORT := /dev/ttyACM0

CFLAGS = -g3 -mcpu=cortex-m4 -mthumb -nostdlib -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -std=c99
INCLUDE = -I./include

#オブジェクトファイルが出力されるディレクトリ
OBJDIR = obj

#Cソースの検索とオブジェクトファイルを出力するディレクトリの設定
SOURCES = $(shell find * -name "*.c")
SRCDIR = $(dir $(SOURCES))
BINDIR = $(addprefix $(OBJDIR)/, $(SRCDIR))

#アセンブラソースの検索とオブジェクトファイルを出力するディレクトリの設定
ASMS = $(shell find * -name "*.s")
ASMDIR = $(dir $(ASMS))
ASMBIN = $(addprefix $(OBJDIR)/, $(ASMDIR))

#オブジェクトファイル群
OBJECTS = $(addprefix $(OBJDIR)/, $(patsubst %.c, %.o, $(SOURCES))) $(addprefix $(OBJDIR)/, $(patsubst %.s, %.o, $(ASMS))) 
DEPENDS = $(OBJECTS:.o=.d)

ifeq "$(strip $(OBJDIR))" ""
	OBJDIR = .
endif

#リンカスクリプト指定
MEMORYMAP = STM32F303K8.ld
#実行ファイル名指定
OBJECTNAME = STM

#サフィックスルール
default :
	@[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
	@[ -d "$(BINDIR)" ] || mkdir -p $(BINDIR)
	@[ -d "$(ASMBIN)" ] || mkdir -p $(ASMBIN)
	@make all --no-print-directory

all: $(OBJECTS) $(OBJECTNAME).out $(OBJECTNAME).bin

$(OBJECTNAME).bin: $(OBJECTNAME).out
	$(OBJCOPY) $(OBJECTNAME).out -I ihex -O binary $(OBJECTNAME).bin

$(OBJECTNAME).out: $(OBJECTS)
	$(LD) -T $(MEMORYMAP) $(OBJECTS) -o $(OBJECTNAME).out

$(OBJDIR)/%.o: %.c
	$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

$(OBJDIR)/%.o: %.s
	$(AS) -g $< -o $@

.PHONY: clean flash

st-flash: $(OBJECTNAME).bin
	$(STFLASH) write $(OBJECTNAME).bin 0x8000000

clean:
	rm -rf $(OBJDIR) *.out *.bin
```
##実行ファイル作成
makeを実行する。

```
$ make
```
上記のMakefileだとSTM.outとSTM.binが作成される。
STM.outは実行ファイル。
STM.binは書き込み用ファイル。

##実行
現状、STM.binをツールで書き込んで動かすには至っていない。
STM.outを用いてgdbからloadする。
実行するとLEDが点滅した!!

![4A1F4CAA-6A7E-4665-AFC6-44CFB6E41063.jpeg](https://qiita-image-store.s3.amazonaws.com/0/140055/6451600c-36f3-8cbd-bfc1-c0af6c341446.jpeg)

##ソースコード
開発をするにあたってGithubにソースをおいてみた。
[mitazet/stm32/v01](https://github.com/mitazet/stm32/tree/master/v01)
##参考サイト
[yuki-sato.com](http://yuki-sato.com/wordpress/%e9%9b%bb%e5%ad%90%e5%b7%a5%e4%bd%9c%ef%bc%9a%e3%83%9e%e3%82%a4%e3%82%b3%e3%83%b3/stm32/)