STM32F411 Lチカ【mac / openocd / raspberry pi】

STM32F411 Lチカ【mac / openocd / raspberry pi】
皆もすなるLチカといふものを、我もしてみむとてするなり。

# 概要
STM32F411 BlackPill のパチモン
(www.amazon.co.jp/dp/B0CR3WXS4G)
を使用して Lチカ を実装する

# 環境
コーディング、ビルド等は m1 mac 上で STM32cubeIDE を用いて行う
生成した .elf を Raspberry Pi 4 から openocd を用いて STM32F411 に書き込む

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/6ba676ea-d885-b40a-8b9e-7db7ecdb9538.png)
スケマを見ればわかるがこんな電源の使い方が正しいか私にはわからない
（まぁ動くからいいか。自己責任で）

## IDE : STM32CubeIDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/69dd6da5-125e-f6ef-16f3-45cb7fbb7dd6.png)

## Raspberry Pi 4
RAM : 8GB モデル （なんでもいい）
OS : Bookworm （なんでもいい）
```
$ cat /etc/debian_version
12.5
```
### openocd
#### install
```
$ sudo apt update; sudo apt upgrade -y; sudo apt install openocd -y
```
#### version
```
$ openocd -v
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
```

# プログラム作る (elf 作成)
## 1. project の作成とか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/114a3969-ccee-dc90-5ede-398c67fa7e2d.png)
[Start new STM32 project] をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/12d9ff90-caa4-9b13-1a15-bd2e10f41092.png)
[Commercial Part Number]　に "411ecu6"（なんでもいい） を入力し、
出てきた [STM32F411CEU6] をクリックし、 [Next >] をクリックする

Project Nme を入力する

## 2. Pin アサインを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/384fb2a2-64f3-5cb3-0b9e-3dc27f6097ee.png)
PA13 : SWDIO
PA14 : SWCLK
PB12-PB15 : GPIO_Output
PA8-PA12,PA15 : GPIO_Output
PB3-PB9 : GPIO_Output

保存する

## 3. プログラムを書く
main.c の main 関数内 while ループ付近
``` main.c
const int intvl = 10;
while (1)
{
  /* USER CODE END WHILE */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, 0);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, 0);
  HAL_Delay(440);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, 1);
  HAL_Delay(intvl);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, 1);
  HAL_Delay(220);
  /* USER CODE BEGIN 3 */
}
```
保存して Build する
これで .elf ファイルが生成される
（オプションで hex とか srec も作れるよ）

# ラズパイに転送して STM32 に書き込む
.elf は何もしないと以下に生成される
`workspaceディレクトリ/project名ディレクトリ/Debug/`

ので

## 4. .elf の転送
```
$ scp lchika1.elf raspi:~/
```
scp で .elf をラズパイに転送する

## 5. .cfg ファイルの準備
openocd で必要な .cfg を作っておく
（touch でも echo でも nano でも vi でもなんでもいい）
``` stm32f4.cfg
adapter driver bcm2835gpio
bcm2835gpio peripheral_base 0xFE000000
bcm2835gpio speed_coeffs 236181 60

# J8 PIN3
adapter gpio swdio 2
# J8 PIN5
adapter gpio swclk 3

transport select swd

source [find target/stm32f4x.cfg]
init
#exit

proc flash_elf {elf_file} {
	reset
	halt
	flash write_image erase $elf_file
	echo "done"
	reset
	exit
}
```

## 6. STM32 に書き込む
### ファイルとか
```
$ tree
.
├── lchika1.elf
└── stm32f4.cfg

1 directory, 2 files
```
（tree は `sudo apt install tree` で入手する）

### 書き込みコマンド
`openocd -f stm32f4.cfg -c "flash_elf lchika1.elf"`
```
$ openocd -f stm32f4.cfg -c "flash_elf lchika1.elf"
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 2001 kHz
Info : SWD DPIDR 0x2ba01477
Info : [stm32f4x.cpu] Cortex-M4 r0p1 processor detected
Info : [stm32f4x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f4x.cpu on 3333
Info : Listening on port 3333 for gdb connections
flash_elf
[stm32f4x.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x21000000 pc: 0x08000b3e msp: 0x2001ffd8
Info : device id = 0x10006431
Info : flash size = 512 KiB
done
```

# Appendix
### 書き込みはしたくないけど STM32 が接続できているか確認したい
`openocd -f stm32f4.cfg -c exit`

```
$ openocd -f stm32f4.cfg -c exit
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 2001 kHz
Info : SWD DPIDR 0x2ba01477
Info : [stm32f4x.cpu] Cortex-M4 r0p1 processor detected
Info : [stm32f4x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f4x.cpu on 3333
Info : Listening on port 3333 for gdb connections
flash_elf
```
`detected` でわかる