【C#】STM32のUSARTブートローダーを操作するライブラリを公開

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のみが使えることがわかります。

 

STM32F1xxのブートローダー

引用:AN2606

 

1-3.STM32ブートローダーの起動方法

機種によって起動方法が異なりますが、だいたいBOOTピンをHi/Loにすると、STM32ブートローダーで起動します。

 

こちらも正確にはAN2602を参照してください。

例えば、STM32F103RBの場合は、先ほど引用したところに”pattern 1”と書いてあります。patternについてはTable 2に記載があるので確認すると、”pattern 1”はBOOT0を1、Boot0を0にすればよいことがわかります。

 

STM32Bootloaderのブートパターン

引用: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.使い方の手順の概要

まずは使い方の概要を掴んでください。おおよそ下記の手順になります。

 

  1. SerialPortの生成
  2. USARTBootloaderの初期化
  3. FLASHの消去
  4. ファームウェアの書き込み
  5. 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.ハードウェアの準備

ハードウェアとしては下記を用意しました。適時変えてもらって構いません。

 

 

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

 

FT232とSTM32

FT232とSTM32の配線

 

次に、STM32ブートローダーを起動するために、BOOT1ピンを0に落とします。マニュアルを読むと、CN7の5番と7番をジャンパーピンで繋げば良いとあります。使っていないCN11からジャンパーピンを拝借して、CN7に装着します。

 

STM32のブートを落とす

 

最後に、PCとUSBケーブルで接続します。USBケーブルは2本必要で、1本は電源供給用、1本はUSARTによる書込み用です。

 

FT232とSTM32にUSBを接続

 

3-3.デモアプリの実行

GitHubからチェックアウトした中にあるUSARTBootloaderDemoをビルド・実行してください。下記の画面が起動します。

 

USARTBootloaderDemo

(ダサっ)

 

後はポート番号とファームウェアのバイナリファイルを指定して、Writeボタンをクリックすれば、ファームウェアの書き込みが行われます。

 

以上です。お疲れ様でした!