STM32に搭載されているブートローダーにUSART経由でアクセスするC#ライブラリを公開しました。本記事では、その使い方をご紹介します。
STM32のファームウェアのアップデートはどうしていますか?
開発環境ではデバッガ(ST Link)があるので簡単ですが、ユーザ先にデバッガを用意してください、と言うのは無理のあるお願いです。
そこで便利なのがSTM32のシステムメモリーに搭載されているブートローダーです。これを使うとUSART経由でファームウェアのアップデートが可能となり、デバッガを必要としません。
このUSARTをC#から操作するためのライブラリを作成しましたので、その使い方をご紹介します。このライブラリを使うことで、パソコンからUSB(USARTに変換して)を経由してSTM32のファームウェアをアップデートするアプリケーションを作ることができます。
なお、本記事では、このブートローダーのことをSTM32ブートローダーと表記することにします。
1.STM32ブートローダーとは
まずは、STM32ブートローダーについて解説します。すでにご存知の方は読み飛ばしてください。
1-1.STM32ブートローダーの概要
STM32ブートローダーはROMのシステムメモリー領域に格納されており、通常は使われておりません。BOOTピンをLoに落とす等してから電源を入れると、STM32ブートローダーで起動します。
STM32ブートローダーはUSARTやSPIといった通信を使うことができ、通信経由でFLASHの消去や書込みが行えるものです。デバッガが不要なので、ユーザ環境でのファームウェアアップデートに便利です。
1-2.STM32ブートローダーで使えるプロトコル
本記事ではUSARTのみを対象としていますが、STM32ブートローダーは他にも次のプロトコルを使うこともできます。
- USART
- CAN
- I2C
- SPI
- USB DFU
機種によって対応しているプロトコルが違うので確認が必要です。なお、USARTはどの機種でも必ず使えます。
確認はST公式のアプリケーションノート:AN2606を参照してください。
例えば、STM32F103RBを確認してみると、USARTのみが使えることがわかります。
引用:AN2606
1-3.STM32ブートローダーの起動方法
機種によって起動方法が異なりますが、だいたいBOOTピンをHi/Loにすると、STM32ブートローダーで起動します。
こちらも正確にはAN2602を参照してください。
例えば、STM32F103RBの場合は、先ほど引用したところに”pattern 1”と書いてあります。patternについてはTable 2に記載があるので確認すると、”pattern 1”はBOOT0を1、Boot0を0にすればよいことがわかります。
引用:AN2606
1-4.USARTとPCの接続方法
USARTを使うとして、PCとどう接続するかですが、これはFTDI社のFT232Rを使っている方が多いと思います。これを使うとSTM32→USART→FT232R→USB→PCという繋ぎになり、PCからは単にシリアルポートとして認識されます。
シリアルポートと認識してくれれば、C#のSerialPortクラスが使えるのでとても便利です。
2.USARTBootloaderの使い方
それでは本題です。STM32ブートローダーのUSARTと通信するためのC#ライブラリを作りました。名前はUSARTBootloaderとしました。
2-1.USARTBootloaderのソースコードの取得
ソースコードはGitHubに公開してありますので、ご自由にお使いください。
https://github.com/yuksblog/stm32_usart_bootloader_c_sharp
2-2.USARTBootloaderの使い方
2-2-1.使い方の手順の概要
まずは使い方の概要を掴んでください。おおよそ下記の手順になります。
- SerialPortの生成
- USARTBootloaderの初期化
- FLASHの消去
- ファームウェアの書き込み
- USARTBootloaderの破棄
では、順番に見ていきましょう。
2-2-2.SerialPortの生成
まずはSerialPortを生成します。
SerialPort port = new SerialPort(); port.PortName = ”COM3”; port.BaudRate = 115200; port.DataBits = 8; port.StopBits = StopBits.One; port.Parity = Parity.Even; port.ReadTimeout = 250; port.WriteTimeout = 250;
PortNameでシリアルポートの名前を指定します。
Baudrateは通信速度で、マニュアルでは115200が最大とあります。ちなみに、230400でも試したら動きました。
DataBits、StopBits、Parityは固定です。
ReadTimeoutとWriteTimeoutは250くらいでよいと思います。
2-2-3.USARTBootloaderの初期化
先ほど作ったSerialPortを使ってUSARTBootloaderを初期化します。
USARTBootloader loader = new USARTBootloader(port); loader.Open(); loader.Init();
2-2-4.FLASHの消去
ファームウェアを書き込む前に該当ページを消去しておく必要があります。FLASHの消去は1ページ毎に行います。ですので、ファームウェアのサイズを考慮して何ページ消去するか計算する必要があります。
この時に注意が必要で、STM32の機種によって1ページのサイズが異なります。FLASHのサイズが128KB以下だと1KBで、それを超えると2KBとなることが多いようです。正確には公式のリファレンスマニュアルを参照してください。
下記のコードは、ファームウェアのバイナリ(byte[] bin)からページサイズ(int count)を計算し、その回数だけFLASHの消去を行っています。
int count = bin.Length / FLASH_BLOCK_SIZE; if (count % FLASH_BLOCK_SIZE != 0) { count++; } for (byte i = 0; i < count; i++) { loader.EraseMemory(i); }
2-2-5.ファームウェアの書き込み
消去が終わったら書込みです。書き込みは1~256バイトのブロック単位で書き込むことができます。ブロックサイズは大きい方が効率的なので256固定で良いと思います。
count = bin.Length / READ_WRITE_BLOCK_SIZE; int reminder = bin.Length % READ_WRITE_BLOCK_SIZE; if (reminder != 0) { count++; } for (byte i = 0; i < count; i++) { int offset = i * READ_WRITE_BLOCK_SIZE; int buffersize = READ_WRITE_BLOCK_SIZE; if (i == count - 1) { buffersize = reminder; } byte[] tmp = new byte[buffersize]; Buffer.BlockCopy(bin, offset, tmp, 0, buffersize); loader.WriteMemory((uint)(BASE_ADDRESS + offset), tmp); }
2-2-6.USARTBootloaderの破棄
最後はリソースを解放して終了です。
loader.Close();
3.USARTBootloaderのデモ
実際に動かしてみないとイメージがわかない方もいると思いますので、ハードウェアの準備から、デモアプリの動作確認まで行いましたので、ご紹介します。
3-1.ハードウェアの準備
ハードウェアとしては下記を用意しました。適時変えてもらって構いません。
- NUCLEO-F103RB
- UB232R
3-2.配線
まずは、STM32とUB232Rを下表のように繋げましょう。TX/RXはクロスするので注意してください。
NUCLEO-F103RB | UB232R | ||
ピン | 機能 | ピン | 機能 |
GND(CN10 9) | GND | 1 | GND |
PA9(CN10 21) | USART1_TX | 7 | RX |
PA10(CN10 33) | USART1_RX | 8 | TX |
次に、STM32ブートローダーを起動するために、BOOT1ピンを0に落とします。マニュアルを読むと、CN7の5番と7番をジャンパーピンで繋げば良いとあります。使っていないCN11からジャンパーピンを拝借して、CN7に装着します。
最後に、PCとUSBケーブルで接続します。USBケーブルは2本必要で、1本は電源供給用、1本はUSARTによる書込み用です。
3-3.デモアプリの実行
GitHubからチェックアウトした中にあるUSARTBootloaderDemoをビルド・実行してください。下記の画面が起動します。
(ダサっ)
後はポート番号とファームウェアのバイナリファイルを指定して、Writeボタンをクリックすれば、ファームウェアの書き込みが行われます。
以上です。お疲れ様でした!