Episode 21 STM32ボードを使ってみた

ブログ

皆さんこんにちは、グレキチです。
2025年の9月下旬に差し掛かりました。夏の暑さが緩和され、朝方は少し肌寒い位になってきていますが、だいぶ過ごしやすくなってきました。家庭菜園で、先週植えたダイコンの種がすぐに芽を出したので、植物も過ごしやすい季節なんですかね?

さて、今回の内容は、ベアメタル学習の続きになるのですが、STM32というまた違ったボードを手に入れたので、それを使って簡単なプログラムを実行したことについての紹介です。
STM32というボードは、STマイクロエレクトロニクスという会社の製品になるんですが、ARMのCPUコアを採用しているということで、目を付けました🧐
その中でも特に、初学者にとって使いやすいとのネット評判を鵜呑みにして、NUCLEO-F103RB(またの名をSTM32F103RB : ARM Cortex-M3搭載)という製品を購入してみました。詳しい仕様などはこちらのメーカーサイトに説明があります。

それでは、まずは開発環境の構築から説明していきます。

STM32開発環境の構築

ST社のボードを使った組み込み開発には主に、メーカーが配布しているSTM32CubeIDEという統合開発ソフトを使う、ということをエンジニア系ブロガーの方々が書いていました。
私の場合、実行プログラムの生成については、ARMのHPから入手できるクロスコンパイル用のパッケージを使えばいいので、特段このIDEを使わなくても問題ないんですが、困ったのは、ボードへのデータ転送をどうやって行うかでした。
そこで、このSTM32CubeIDEを使いたくなる所なんでしょうが、このソフトは私のメイン開発PCのM1mac(Arm64)には対応しておらず、またUTMで構築済みのLinux環境(こちらも当然Armベース)でも使えないようなので、一時茫然としました。(ARMのCPUを搭載しているボードをプログラミングするソフトなのに、ARMのCPUを搭載したPCで実行出来ないとは、何と理不尽なんでしょうか😫)

このまま負けを認めて!?、サブ機のWindowsPCを使うかと一瞬怯みましたが、何とか手はないか🤔・・・と、ネットでひたすら調査を行いました。
その結果、遂に!、突破口となるものが見つかりました‼️

見つけたのは、stlink-toolsというオープンソースのソフトウェアを使う方法です。このソフトはCPUのメーカー関係なしに、殆どのPC向けOSで使えるようでした。(何とも有難い🙏)
なお、このソフトのLinuxへのインストールは、下記コマンドで実施できます。なお、実際の使用方法については、後段で説明します。

sudo apt install stlink-tools

また、ハード的な事を言うと、STM32ボードへのプログラム転送には、ST-LINKと呼ばれる転送書き込みツール(ケーブル装置)が必要のようですが、今回購入したNUCLEO-F103RBには、標準でST-LINK機能が搭載されているとのことで、このST-LINKツールを改めて購入する必要はありませんでした。(まあ、事前に調べた上でボードを購入したんですけどね)
しかし、開発用PCとSTM32ボードとの接続には、USB TypeA ↔︎ mini USB TypeBのケーブルが必要なので、部屋のその辺に転がってない場合は、購入しないといけないですね。(Microではなく、miniってのがちょっと曲者ですが😏)
と言うことで、これで開発環境が整いました。

それでは次に、プログラムについて紹介します。

プログラム概要

実装したプログラムなんですが、実は今回も、前回、前々回のブログと同じくLチカなんですね〜。
実装内容がLチカばかりだと、ちょっと飽きちゃうかもしれないと思って、敢えてタイトルに文言を入れ込むのは止めました😄 目がチカチカして、疲れるかもしれませんからね🤣
また、今回作成したプログラムも、ラズパイPicoのLチカで参考にさせてもらったのと同じ制作者の方の、こちらのサイトから引用させて頂きました。この制作者の方のサイトには、ラズパイとSTM32のボード向けのサンプルプログラムがたくさんアップされているので、末長く活用させてもらえそうです👍

引用したプログラムは、同じSTM32F1系のSTM32F103C8ボード用のもので、ちょっと調べた感じだとそのままビルドして使えそうだったので、早々にビルド後データ転送して起動してみました。しかし、ボードからは何の反応もなく・・・🧐、原因分析で丸1日位立ち往生しました💦
何が問題なのか、プログラムに不具合がある?、データ転送がうまくいってない?などなど。
プログラムのビルドについては、エラー無くbinファイル出来てるし、データ転送も、ボードの中身を確認すると、きちんと書き込まれているようだしなー。そうすると、プログラム自体に問題があるのか?プログラムの記載内容は引用元のプログラムそのままなので、これは問題ないのだろう、云々・・・。
同じSTM32F1系のボードということで、プログラムがそのまま使えるのだと信じ切っていましたが❗️、何とそこに落とし穴がありました😱
(組み込み開発やっている人たちって、何度もこんなことに遭遇するのかなーって、勝手に想像しちゃいました)
で、結局のところは、LEDの点灯/消灯の信号を指示するPin番号が間違っていた、というオチでした😓 ざっくり経緯を説明すると、次の通りです。

LEDについて、引用元プログラムの説明文章には、下記の記述がありました。

赤下線部分を要約すると、“このボードのPC13にLEDがある” となってますよね。なので、プログラムは下記の通り書かれている。

ra=GET32(RCCBASE+0x18);
ra|=1<<4; //enable port c <-- ココ
PUT32(RCCBASE+0x18,ra);

//config
ra=GET32(GPIOCBASE+0x04);
ra&=~(3<<20);   //PC13    <-- ココ
ra|=1<<20;      //PC13    <-- ココ
ra&=~(3<<22);   //PC13    <-- ココ
ra|=0<<22;      //PC13    <-- ココ
PUT32(GPIOCBASE+0x04,ra);

しかし、よくよく調べると、F103RBボードの方は、PA5からの出力でLEDが点灯/消灯することがわかりました😅
下図がF103RBボードの回路図です。(見つけるのに苦労した😮‍💨)


ということで、Cファイル内のその部分に関する箇所の書き換えを行いました。
各ポートやレジスタのアドレスは、ボードのリファレンスマニュアル (※リンク先下方のRM0008)で確認の上、記入しました。
先ほど示した同コード箇所で、書き換え後のコードは、以下の通りです。
(レジスタを C→A へ、ポート番号を 13→5 へ各々変更)

ra = GET32(RCCBASE + 0x18);    // RCC_APB2ENR(APB2 ペリフェラルクロック有効レジスタ) set
ra |= 1 << 2;                  // enable port A
PUT32(RCCBASE + 0x18, ra);

// config
ra = GET32(GPIOABASE + 0x00);  // GPIOA_CRL(ポート設定下位レジスタ) set
ra &= ~(3 << 20);              // PA5モードビット 00設定 -> 入力モード(*一旦リセット)
ra |= 1 << 20;                 // PA5モードビット 01設定 -> 出力モード最大速度10MHz
ra &= ~(3 << 22);              // PA5設定ビット 00設定 -> 汎用出力プッシュプル
ra |= 0 << 22;                 // PA5設定ビット 00設定 -> 同上
PUT32(GPIOABASE + 0x00, ra);

なお、上記以外にも変更した箇所はあり、プログラム全文は、こちらのGithubにアップしてます。

プログラムが出来たら、起動データ生成のため、Makefileを使ってビルドします。すると、同じフォルダ内にbinファイルが作成されるので、これが起動データになります。

次は、開発PCから対象ボードへの起動データの転送方法について、stlink-toolsの使い方として説明していきます。

stlink-toolsの使い方

ここでは、stlink-toolsの使い方について、ちょっと触れておきます。まだ使い始めたばかりなので、今回はデータ転送方法と書き込み出来たかどうかの確認方法ぐらいの内容です。
なお、ツールでの操作前に、開発PCと対象ボードをUSBケーブルで繋いでおきます。

書き込み前に、まずはボード内のデータ有無の確認です。
書き込み先のボードに、すでに何かのデータが書き込まれていると、不具合の原因になるので、データを消す作業が必要になります。
stlink-toolsは基本的にはCLIで操作しますが、一部の機能はGUIでも使うことが出来ます。データ有無のチェックはGUIで表示させた方がわかりやすいので、GUIを起動させて行います。GUIの起動コマンドは、下記の通りです。

stlink-gui

ターミナルでコマンドを打ち込んだら、下記のウィンドウが立ち上がります。

そして、左上の緑丸✔️を押すと、現在USBでPCと繋げているボードの中身の状態が確認出来ます。(下図参照)

上図のように、アドレス0x080000に何か書き込みがあるので、この場合は何かが書き込まれているということです。このような状態になっていたら、下記コマンドでデータを消去します。
(※stlink-guiからはデータ消去出来ないので、一旦赤丸✖︎ボタンでPCとボードの接続を切った後、別途ターミナルを起動するなどで、CLIで実施しないといけない。これがちょっと不便😢)

st-flash erase

PCとボードを再接続した後、ボード内容をチェックして、下記の通り、“0xFFFFFFFF”となっていたら、消去出来ています。

データが空になっているのを確認できたら、いよいよデータの書き込みに移行します。
書き込みには、データ消去と同じコマンドを使いますが、オプションコードなどが異なります。基本的には、下記の通りです。

st-flash write stm_blinker01.bin 0x8000000

書き込みなので、st-flashコマンドの次に “write” を使っているのは納得できると思います。
その次には、書き込み対象のファイル名を記載します。stlink-toolsでのデータ書き込み可能ファイルは、binファイルとhexファイルの2種類を扱えるようです。通常はbinファイルを生成するので、今回もbinファイルを記載しています。なお、デフォルトはbinとなっていて、hexファイルを書き込みする場合は、オプションコード “–format ihex”の追記が必要なようです。
最後に、書き込みを開始するアドレスを指定します。デフォルトでは、0x08000000になっているので、今回もそれで指示しています。但し、記入する桁数に注意したいですね。上のコマンドラインでは、0x8と、xの次に8から始まっていますが、その後ろの0の数は6個なので、これを8桁で記述すると0x08000000となりますよ☺️

それで、書き込みが成功したら、下記のように指定したアドレスから順に、プログラムが配置されます。

これで、無事に書き込みが完了しました。
今回紹介したstlink-toolsのコマンドは、こちらのソフトウェア製作者のGithubに記載されています。もっと様々な使い方については、別途探さないといけないみたいでした。

それではいよいよ、書き込んだプログラムを実行してみましょう。

実行結果

書き込みが完了すると自動的にプログラムが実行されますが、念の為、一度ボードのリセットボタン(ボード中央左にある青丸ボタン)を押しておいた方が良いと思います。

実行状態は下の動画の通りです。緑色のLD2が点滅していますね。

まとめ

今回は、STMボードを扱ってみました。これまでラズパイしか扱っていなかったので、違うメーカーのボードを使ってみると、また違った知識やツールが必要になったり、ボード毎のメリット・デメリットなども把握できて、今回もとても良い勉強になりました。まあ今のところ、Armコア搭載モデル限定なんですけどね😏
今後もしばらくは、ベアメタル(極力アセンブリファイルでプログラミングする)での実装トライを続けていきたいと思っていますので、また何か進捗があったら紹介したいと考えています。

ということで、今回はこれまでです。最後まで読んで頂いてありがとうございました。

それでは、また🖐️