皆さんはMCUにどんなチップを使いますか?AVRマイコンかもしれませんし、ARMマイコンかもしれませんね。
私は昨今の半導体の品薄を見て様々なチップを使えた方がいいなということで、色々手を出しているのですが、選択肢が豊富なのでARMマイコンを使っています。その中でも、STM32Fシリーズは種類が豊富なので非常に助かります。必要に合わせてスペックも選べますし、半導体の品薄が叫ばれるこのご時世でも選べば在庫があるものを選べたりとメリットが大きいです。
なので、私が作製しているデバイスではSTM32Fのデバイスを使っているのですが、試作で使っていたのがSTM32F303CBT6という製品でした。しかし、私が利用していた時は数千個単位で在庫があったのですが、突然業者が買い占めたようで利用できない状態に…
私のデバイスはそんな高性能さを求めるようなものではない(具体的にはキーボードです)なのでそこまでSTM32F303シリーズが良いというわけでもなかったので、似たような製品を使ってみようということで他のSTM32Fシリーズを選ぶことにしました。
そこで市場に在庫があるSTM32F103シリーズを選ぶことにしたのですが、ここにはちょっとした落とし穴がありました。
STM32F303に限らずSTM32F103以外のSM32Fシリーズには変更や削除のできないブートローダーが標準で書き込まれています。
今回使用するSTM32F103シリーズのみがブートローダーが標準で書き込まれておらず、ブートローダを別途書き込んでやる必要があるのです。
私が試作していたデバイスは元はSTM32F303を使用することを前提に設計していたため、ブートローダを書き込む前提でデバイスを作製していなかったこと、そもそもブートローダってどうやって書き込むの?ということで色々難儀したので、実際にブートローダを書き込むまでのその備忘録と紹介を兼ねた記事になります。
リード文が長くなってしまったので、紹介を始めます。
目次
STM32F103について
STM32F103はArduino互換のブートローダが存在しているため、Arduinoの互換品として利用されることが多いかと思います。有名どころの開発ボードだと日本ではMaple miniのコピー品であるBule Pillあたりが有名でその利用方法を示したページが検索でよく引っかかります。
STM32F103はSTM32Fシリーズの中の種類の一つで、STM32F030、STM32F072、STM32F103等、多くの類似製品が存在します。基本的にはSTM32F以降に続く3桁の数字が基本的なグレードで、例えば搭載されているCPUのアーキテクチャや、動作周波数、機能などが異なります。
今回利用しているチップはSTM32F103C8T6というものなのですが、この103以降に続くC8T6の部分は以下のように識別されます。
文字 | 項目 |
C | ピン数 |
8 | ROM容量 |
T | パッケージ |
6 | 動作温度 |
ここら辺の細かいことは省略しますが、実際に使って見て違うチップが欲しいと思ったときに細かく調べたら良いと思います。私の場合は元々STM32F303CBT6という製品を使っていたので、この表記に従うと、STM32F103C8T6はCPUの部分とROM容量のみが違う製品だということになります。ピン数やパッケージ自体は一緒なので、とりあえずそのまま載せること自体は可能です。
ここらへんはデータシートを確認して、データ的には問題ないかぐらいは当然確かめます。「(製品名) データシート」あたりで検索をかければ公式のデータシートを見つけることができます。
データシートのピン配置を見た限り、電源入力のピンや、USBのデータ通信に使うピン自体は一緒だったのでとりあえずプログラム的な差異は多少あるにせよ、何とか正しく動くだろうということが確認できます。
ですが、後々気づくのですが、実はここに大きな落とし穴があります。それが純正のブートローダです。おそらくデータシートにきっちり目を通せばどこかには書いていると思うのですが、何も考えずにさらっと目を通しただけだったため、その問題に気づいていませんでした。
STM32F303とのブートローダの違い
ブートローダにどのような違いがあるかというと、STM32F系の製品はBOOT0のピンを+3.3Vの部分と短絡させた状態で電源を入れるとメーカ純正のブートローダが呼び出されます。
基本的にはSTM32F103以外(全てかどうかまでは知りません。例外があるかも)のUSB機能を搭載した製品の場合、USBデバイスとなった状態でWindows上から見えるようになります。
この状態で、Arduino IDEなり、私ならQMK ToolBoxからスケッチを書き込んだりとWindows上からスケッチを送り込み実行ができるようになります。これがSTM32F303等のSTM32F103以外の製品の話です。私はこの挙動ができると踏んで実際に購入して試したわけですが、実際には違いました。
では、STM32F103だとどのような挙動をするのかというと、BOOT0と+3.3Vのピンを接続する部分は同じで、そこからブートローダが立ち上がるという動作も同じです。ですが、決定的に異なるのは、Windows上から人気できないことです。実際に接続するとこのようになります。
USBデバイスが認識されませんということでWindows上から正しく認識できていません。デバイスマネージャー上ではこんな感じです。
この表記はただ単にデバイスドライバが正しく読み込まれていない場合でも発生しますが、それが原因というわけではありません。
これはブートローダの仕様の違いで、理由はわかりませんが、何故かSTM32F103系だけ、ブートローダがUSBデバイスとして動作しないようになっています。Windowsから何かしらの操作ができるということは、正しいUSBデバイスとして動作している必要があり、そもそも正しいUSBデバイスとしてふるまっていないため、何をやっても認識しようがありません。
そのため、純正のブートローダではWindowsからスケッチを送り込んで簡単に実行できるわけではなかったのです。
では、このブートローダはどのような動作をしているのかというと、シリアル通信によってデバイスの書き込みができる状態になっています。つまり、純正のブートローダを使う場合はシリアル通信変換ボードをかませて書き込む必要があります。
毎回シリアル変換するのは面倒ですよね。どう頑張ってもSTM32F303のようにWindows上からスケッチを書き込めないかというとそういうわけではありません。データシートを見ると、しっかりUSBによる通信をサポートしていることがわかります。
これを実現するには、ブートローダとして動作するスケッチを書き込めば解決ができます。それがSTM32duino-bootloaderです。
ただ、初回のスケッチの書き込みにはUSBシリアル変換を行う必要があるので、USBシリアル変換(USB-TTL変換)のデバイスを用意する必要があります。
書き込みに利用するピン
そもそもSTM32F303を利用するつもりでボードを設計していたので、シリアル通信で書き込みするためのピンがどれかや、それ用の端子を作っていません。大丈夫か不安です。これも公式データシートを調べてみます。
PA9とPA10のピンがそれぞれTXとRXに対応していることが書かれています。それ以外にもUSARTx_RX等の表記があるピンが2組ほどあったので、どれか引き出せていれば書き込みができそうです(他のピンでは確認はしていません)。私はPA9とPA10を書き込める位置まで引き出していたので、それを利用することにしました。
書き込みに必要なもの
書き込みに必要なものは以下の様になっています。
- USBシリアル変換(USB-TTL)ボード
- ボード用のドライバ
- 変換ボードと接続するワイヤー4本
- TX
- RX
- +3.3V
- GND
- stm32fash(公式からダウンロード)
- ブートローダ(STM32duino-boootloader)
これだけで大丈夫です、USBシリアル変換に使えるボードはCP2102やCH340等様々なチップのものがありますが、特定の種類だと使えないなどがあるため、新規でボードを買われる場合は、今回使ったものと同じCP2102搭載の製品が良いかと思います。デバイスドライバは検索したら出てくるので、入れておいてください。
USBシリアル変換用のボードは私も買ったのですが、とりあえずお試ししたい場合は他にお持ちののデバイスを利用する方法があるかもしれません。私の場合はESP32 DevkitC V4にCP2102が搭載されていて、ピンも引き出されていたのでそれを使いました。こういういデバイスが好きなのであれば何かしらはお持ちかもしれませんね。
また、そもそも自作基板自体はこんな使い方を想定していなかったため、端子が1mmのスルーホールだったり、他のデバイスをはんだ付けする部分だったりしたのでワイヤーも自作する必要がありました。そのときの記事がこちら。
BluePillのような開発ボードだと無縁の話になると思いますが、特殊な場合は何かしら参考になることがあるかもしれません。気になった方は是非。
そのほかのものはインターネットを探せば出てくるソフトウェア等なので省略しますが、ブートローダのSTM32duino-bootloderのレポジトリのbinariesかbootloader_only_binariesの中身は使うのでダウンロードしておいてください。
実際に書き込んでみる
というわけで実際に書き込んでみます。まずはソフトウェア周りから準備しますが、他の方のサイトにも書いているようにバッチファイルを事前に作っておくのが楽で良いと思います。
まずは使うブートローダ(私は「generic_none_bootloader.bin」を選びました。詳しくは後述)と「stm32flash.exe」を置き、バッチファイルを作成します。これらを全て同じ階層に置いておきます。
バッチファイルの中身は以下のようにします。
@echo off
SET COM_PORT=COM1
stm32flash.exe -f -v -w generic_none_bootloader.bin %COM_PORT%
COM1の部分は表記の通りUSBシリアル変換デバイスのCOMポートの指定なのでデバイスマネージャで調べます。
COM4と表示されているのでさきほどの部分はCOM4に変更しておきます。
次に、一度USBポートからUSBシリアル変換デバイスを取り外した状態で配線します。接続した状態から後で配線すると、COMポートが開けませんみたいなエラーが出てstm32flashが正しく動作しなくなるからです。
writebootloader.cmd
stm32flash 0.7
http://stm32flash.sourceforge.net/
Using Parser : Raw BINARY
Size : 6960
File not found: COM4
Error probing interface "serial_w32"
Cannot handle device "COM4"
Failed to open port: COM4
もしかしたら環境依存かもしれませんがそこらへんはわかりません。
無用なトラブルを防ぐため、STM32F103のボードにはUSBから給電しないようにしましょう。
配線を行ったらBOOT0のピンと+3.3Vのピンを接続しておきます。ジャンパピンなら簡単だと思います。私はタクトスイッチで実装していたため、USBシリアル変換デバイスを接続するタイミングで押しっぱなしすることで純正のブートローダーを立ち上げます。
その状態でバッチファイルを実行します。他のサイトに倣って「writebootloader.bat」という名前にしていますが、名前はなんでもかまいません。
>writebootloader.cmd
stm32flash 0.7
http://stm32flash.sourceforge.net/
Using Parser : Raw BINARY
Size : 6960
Interface serial_w32: 57600 8E1
Version : 0x22
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0410 (STM32F10xxx Medium-density)
- RAM : Up to 20KiB (512b reserved by bootloader)
- Flash : Up to 128KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB
Write to memory
Erasing memory
Wrote and verified address 0x08001b30 (100.00%) Done.
これでブートローダーが書き込めました。書き込めないときはこのようなエラーが出ると思います。
>writebootloader.cmd
stm32flash 0.7
http://stm32flash.sourceforge.net/
Using Parser : Raw BINARY
Size : 6960
Interface serial_w32: 57600 8E1
Failed to init device, timeout.
このときは一旦配線や、BOOT0が+3.3Vに接続されていることを確認してもう一度flashすれば書き込めると思います。
さて、最初に書いたどのブートローダーのバイナリを選ぶかですが、ファイル名の後ろにpa13みたいな文字がついていると思いますが、これがステータス用のLEDが接続されているピンを表すものらいしいので、お持ちのボードに合わせて選べば大丈夫です。今回のように自作基板でLEDを実装していない場合は同じものを選べばよいと思います。
これが関係あるかは不明ですが、今回の自作基板ではBlue Pillなどに書きこむ「generic_boot20_pc13.bin」を書き込み、スケッチを書き込むと、高確率で書き込んだブートローダが立ち上がってしまうことがあります。LEDが実装されていないことが原因になっている可能性があるので、自分の基板に合ったものを選ぶようにしてください。
後はArduino IDEでも、QMKでも構いませんが、使いたいプラットフォームでドライバをインストールして、WIndows側からブートローダが見えれば大丈夫です。
QMK ToolBoxで書き込むとエラーが出ているのですが問題なく使えているので気にしていません。もしかしたら、他の環境でも何かしらのエラーが起きるかもしれません。
また、一度ブートローダを書き込むと、次に電源を接続したときに自動的にスケッチが実行されてしまいます。書き込んだSTM32duino-bootloaderを立ち上げたいと思った場合に、BOOT0ピンを+3.3Vと接続すると純正のブートローダが立ち上がってしいます。次からの書き込みはどうすれば?となると思います。仕様的には一度リセットした後、0.5秒間だけ書き込みができるみたいなので書き込みタイミングが相当シビアみたいです。
そのため、書き込みをしばらく待ってくれる機能があります。PB2がBOOT1という機能のピンがありそれを+3.3Vと接続することでスケッチの書き込み待機モードにできます。今回の基板では端子として用意していなかったため、SMDの部分に強引に配線をして確かめましたが、BOOT1ピンを利用すれば書き込みモードにできました。もし基板を作製される場合はBOOT0とBOOT1の両方を引き出して利用できるようにしておくと良いと思いました。
結果的にSTM32F303と同じような使い方ができるようになったので満足しています。BOOT1ピンを利用するという点では結構違ったのですが、何とかなる範囲なので、もしSTM32Fシリーズで同じチップが利用できない困ってもなんとかなることがわかりました。物理的なデバイスとして違うのはSTM32F103の部分だけで基盤は全く同じもので問題ないことも確認できました。
まとめ
STM32F103C8T6を使ってみした。ブートローダの違いをよく見ていなかったため、面倒に感じましたが、違いを理解して使えればSTM32F303と同じ基板実装で使うことができました。
ただし、初回のブートローダの書き込みにはUSBシリアル変換デバイスが必ず必要になる点には気を付けなければいけないと感じました。
同じようなことを考える方は少ないと思いますが、半導体の品薄が叫ばれる今だからこそこんな工夫で助かる方がいれば幸いです。
以上です。お読みいただきありがとうございました。