ブートローダ
目的のプログラム(ユーザプログラム,アプリケーションプログラムと呼ぶ)を起動するための前段階のプログラムをそう呼ぶ. ここでは主に,マイコンに対して任意の通信を行い,その通信によって受信したバイナリデータを自身のフラッシュROMに書き込むプログラムを対象として記載する.
stm32の内蔵ブートローダ
stm32マイコンの場合,システムメモリ領域にブートローダが内蔵されている. 市販のマイコンボードで2つボタンが有るものの場合,1つがリセット,もう1つBOOTピンに接続されいてることが多く,このスイッチによってシステムメモリのブートローダを起動する. リセット時,BOOTピンの電圧レベルによってブートローダorフラッシュROM内のプログラムを実行するかを選択する. ブートローダを使わず,リセット後はフラッシュROMからしか起動しない場合はBOTTピンは抵抗でプルダウンして0にしておく.
STM32も,製品によってBOOTピンが1つのものもあれば2つのものもある.
また,ブートローダの書き込まれいてるシステムメモリの先頭アドレスも微妙に異なっているので使いたいデバイスに合わせて適宜確認する.
USB接続対応のSTM32マイコンにて,ブートローダがUSB通信でプログラムの更新するものがある.この際USBでデータを通信するプロトコルのことをDFU(Device firmware upgrade)プロトコルと呼ぶ.記事によっては「DFUモートでプログラムを書き込む」と言った表現をしているが,これは「STM32内のブートローダを実行し,USB経由でプログラムを更新する」と同義とと思われる.
メリット
- STM32には標準で書き込まれているのですぐにブートローダを使える.
- インターネット上に動作サンプルが多い
デメリット
- STM32の種類によって書き込まれているブートローダをバージョンが異なる(内蔵なので世代の新しいデバイスほどバージョンが新しい(高機能)なのは当然とえば当然)
- 内蔵のブートローダと通信できるペリフェラル及びピンに制約がある
S内蔵ブートローダの詳細については「AN2606 STM32 マイクロコントローラ システム・メモリ・ブート・モード」を参照
自作ブートローダ
場合によっては内蔵のブートローダを使わずに(BOOTピンを0に落としたまま,内蔵ブートローダ対応のピンが割り当てられない)かつJTAG,SWDといったデバッグプローブ使わずに(ユーザ)プログラムを書き換えたい場面がある.その場合はブートローダを自作する必要がある.
フラッシュROM上に,ユーザプログラムとは別領域を設け,そこにブートローダのプログラムを書き込んでおく.
ユーザプログラム上で,特定のコマンドを受け取ったら,そのブートローダのプログラムへ飛んで,自作ブートローダを起動する.
ブートローダのプログラム内部で,更新するユーザプログラムのバイナリを受信するためのペリフェラルを有効にし,受信したバイナリをフラッシュROM上に書き込んでいくことでユーザプログラムの更新ができるようになる.
このように,ユーザプログラムが実行中にそこからブートローダへ飛んでユーザプログラムを更新する流れをSTではin-application programming (IAP) と呼んでいる.
実装の際は,ブートローダのメモリに飛ぶようにスタックポインタや関数ポインタの登録だけでなく,あらゆる割り込みの無効化,クリアをしておく必要がありそう.HALドライバを動かしてる場合はHALもDeInitしておく必要がある模様(確かにHALの中で1msのSysTickタイマ使っているので)
How to jump to system bootloader from application code on STM32 microcontrollers
ST公式にYoutubeビデオリストがある。
How to Create a Super Simple Bootloader
各種ペリフェラルでのプロトコル
システムブートローダについてはstm32の種類によって対応しているペリフェラルが異なったりする。
CAN AN3154 Application note CAN protocol used in the STM32 bootloader
FDCAN AN5405 Application noteHow to use FDCAN bootloader protocol on STM32 MCUs
ST公式ブートローダ
STはブートローダをオープンソースとしてGitHub上で公開している(Middleware Open Bootloader MCU Component).
内蔵ブートローダと同じように動くので,これを実装したらCubeProgでブートローダが正常に認識されるかテストできる.
ブートローダを自作する際は,これを参考に作るのが良さそう.UARTのプログラムを書き込んで,CubeProgrammerでUARTブートローダの動作は確認できた.
How to use the ST Open Bootloader for STM32 Microcontrollers
ここまで書いといてあれだが、オプションバイトの設定でBOOTピンを見に行かない設定にできる。ここでBOOTピンの設定をいじっておく。 そうすれば実行プログラムの中でブートローダを起動させることができそう。 ソースコードからもいじれるがプロテクトがかかってるので、CubeProgからいじったほうが楽かも 先頭はスタックのアドレスを入れて、その次(4バイトアライン)にResetハンドラがあるのでこのリセットハンドラを呼ばせるという認識でよいのだろうか。
AN2606に詳しく書いてある stm32に割り当てられている「システムメモリ」という場所にブートローダのファームウェアが入っている。 リファレンスマニュアルには「システムメモリがブート領域として選択」を記載されている。
メモリの割当
自作ブートローダを書き込むメモリ領域を配置する.このとき,アプリケーションプログラムを書き込む領域とは分けておく必要がある.
リンカスクリプトを編集し,アプリケーションプログラム側のベクターテーブルオフセットレジスタをいじっておく必要がある.
フラッシュROMを一部EEPROM化して,変数を記録しておくテクニックのときはみんなセクタ0は使わずにセクタ1以降にEEPROM化した領域を持つような実装にしている.
これは,ベクターテーブルオフセットをいじらない場合にやる話ではないのだろうか?ブートローダやEEPROMを保存した領域を前の方(セクタ0)に持ってきて,ベクターテーブルオフセットごと後ろにずらしたほうがいいのではないだろうか?
↑のようなこと考えたけど,これだと電源入れた直後にブートローダが起動する。IAPの趣旨として「電源入れてのリセットは普通にアプリケーションプログラムが動作,アプリケーションプログラムの動作中に特定のコマンドを受け取るとブートローダのプログラムを起動する」という流れなのでやっぱりベクターテーブルは先頭に置かないとダメそう.
CANブートローダ
stm32-mw-openblはCAN FDでの実装である。
ST-LinkV3はCANブートローダの実装であり、互換性は無い。そもそもST-LinkV3に使っているのがstm32F723なのでFDCANは未対応である。
ST-Linkの新型でFDCAN対応のstm32じゃない限りCubeProgからFDCANを扱うことはできない。
Are there plans for CAN support in open bootloader?
STM32 CAN bootloader
How to connect to the STM32 CAN Bootloader interface?
F446REで検証
CANブートローダ対応してるstm32で実際に通信できるかのテストしてみる。Nucleo F446REで検証。
STLinkV3のCAN_RX ↔ PB5(CAN2_RX), CAN_TX ↔ PB13(CAN2_TX), CAN_VDD ↔ VDD(3.3V), GNDを接続
システムブートローダを起動するため、BOOT0ピンを隣のVDDと接続し、High状態にしておく。
アプリケーションノートに従い、F446REでCANブートローダの動作確認できた。
システムブートローダを起動するために、BOOT0ピンの電圧を変更してリセットボタンを押す必要あり
参考文献
Jump to Bootloader in STM32 through application i.e using Boot 0 and Boot 1 Pins in Boot mode from User flash
STM32CubeProgでUARTを使ったフラッシュ書き換えを試す
MSPとリセットハンドラをいじるのがミソの感じ?
STM32 Custom Bootloader Jump to Application
Source code for STM32 bootloader?
フラッシュローダーとは? (3/3)
STM32シリーズでSWDから操作できなくなった時の対処法
マイコン(STM32)の開発でドハマりする話
ARM Cortex STM32
STM32 Jump to System Memory Bootloader
STM32CubeIDEでブートローダ+アプリをデバッグする