STM32で始めるFreeRTOSとLwIP


以前に組み込み開発におけるネットワークに関する仕事を行っていたのですが、FreeRTOSやLwIPなどのオープンソースを使う機会がなく、どうせなら使いこなせるようになっておきたいと思いこの記事を書くことにいたしました。

# 目次

サンプルの中身を確認していくと文字数が多くなったので、複数の記事に分けております。

1. CubeIDEで行うFreeRTOS+LwIPハンズオン(この記事)
1. [サンプルソースにおけるLwIPの初期化処理の解説](https://qiita.com/tom_S/items/c1b1bfc030a67fe7977a)
1. [サンプルソースにおけるLwIPのDHCP Clientの解説](https://qiita.com/tom_S/items/f4552357336bdc1d8fc0)
1. [サンプルソースにおけるHTTP Serverの解説](https://qiita.com/tom_S/items/9d0343c07acbe107c628)


# 使用する環境

使用するボードは「NUCLEO-F429ZI」です。参考に私が購入したサイトを下記に示します。
https://jp.rs-online.com/web/p/microcontroller-development-tools/9173775
このボードを使う理由としましては、
組み込み開発ではICEと呼ばれるデバッグ用の機材が必要になることが多いのですが、このボードはICEが内蔵されており初心者でも扱いやすいからというのがあります。また、Ethernetの接続口とコントローラがついており、ネットワークの通信ができそうなのもあります。
IoTの事を考えると、Ethernetではなく無線のWiFiやBluetoothを使った方がいいかもしれませんが、デバッグや設定が難しくなるのと、FreeRTOSとLWIPにフォーカスしたいので、敢えてEthernetを今回は使用しています。

また、今回は開発環境として、CubeIDEとCubeMXを使用します。これらのツールは、GUIからFreeRTOSとLwIPのボード設定を行うことができるため、使用しています。
CubeMX等のツールを使わなくても良いのですが、ツールを使わない場合は評価ボードのマニュアルを隅々まで読むことになるのと、LwIPやFreeRTOS以外の説明が増えてしまうので、今回はツールの恩恵を受けることにしました。

# CubeMXとCubeIDEの環境構築

CubeIDEと、CubeMXは下記から入手します。

CubeMX(コード生成ツール)
https://www.st.com/ja/development-tools/stm32cubemx.html

CubeIDE(eclipseベースの開発環境)
https://www.st.com/ja/development-tools/stm32cubeide.htm

現在(2024/5)確認したところ、[MyST](https://www.st.com/cas/login?lang=en&service=https%3A%2F%2Fwww.st.com%2Fcontent%2Fst_com%2Fen.html)のアカウント登録をしていないとCubeMXでソースコードの生成ができないようです。こちらは無料で登録できるので登録しておきます。

MySTの登録が終わりましたら、CubeIDEを起動します。起動すると、下記のような画面が出るかと思います。ここには任意のフォルダを選択してください。デフォルトで設定されているフォルダがあるようならそのままにするのをお勧めします。

![起動画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/8675b462-caec-91e7-f8d7-aefb6cc934de.png)

上記の画面から、「Launch」をクリックすると、ボードの設定画面が開かれます。
ここでは、下記の画像のように、「Board Selector」のタブを選択し、「NUCLEO-F429ZI」を選択状態にしてください。これによりボードの設定はほぼ完了になります。

![cubeIDEボード選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/3ab2bf69-8a69-8583-2ef9-7658c4bc28d2.png)

次に、FreeRTOSとLwIPの設定を行います。FreeRTOSとLwIPもさきほどのボードの設定画面から可能です。
FreeRTOSとLwIPの設定に関しては、「Example Selector」のタブを選択し、FreeRTOSと、LwIPにチェックを入れます。

![FreeRTOS選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/d2981204-5741-e895-70c9-d8771f18d229.png)


すると、下記の画像のようにボードのサンプルがあることがわかりました。これを使っていきましょう。選択状態にして右下の「Next」を押します。

![sample選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/d6778001-31e7-19c7-bbe3-c1d5cc04488e.png)


そのあと確認用のダイアログが出ますが、これは特に設定できる所もないので、「Finish」を押します。これによりサンプルプロジェクトが生成されます。

# ビルドとファームの実行

生成されたプロジェクトが使用できるかを確認しておきましょう。下記のようにプロジェクトを選択状態にして、「Project」→「Buiild」でサンプルプロジェクトのファームウェアをビルドします。

![ビルドやり方.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/f1addcd1-ffbf-1301-3bb7-786a894947d4.png)


ビルドは、CubeIDEのConsoleに下記のようにメッセージが表示されていれば、成功です。これで「NUCLEO-F429ZI」に書き込むファームウェアが完成しました。

![ビルド成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/93cd3bf1-6f0a-0efa-5042-62bb3276d842.png)


次に、このファームウェアをデバッグ実行します。「NUCLEO-F429ZI」の「CN1」のUSBの接続口(Ethernetの接続口と反対側の接続口)とPCをUSBケーブルで接続します。
デバッグ実行は、左上にあるプロジェクト「LwIP～」を右クリックし「Debug As」→「STM32 C/C++ Application」を選択します。

![デバッグ実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/8e6ee269-5ccd-b8a6-d9ab-6b309cf0ae3e.png)


途中で下記のメッセージが表示されることがありますが、「Switch」を押してください。

![debug時メッセージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/d9eb632a-51fb-70eb-41bb-4dd3b198a242.png)


下記のような画面になるので、赤枠内の再生ボタンみたいな形のボタンをクリックしてください。これでデバッグ実行することができます。

![デバッグ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/7b3aeb7a-10a1-b47a-7473-d7a956be981f.png)


デバッグ実行ができることが確認できたので、HTTP serverとして機能しているかを確認していきます。
次の項目の動作確認のため、一度停止ボタン(再生ボタンの二つ隣の赤い四角形のボタン)を押してください。これでデバッグ実行を一時的に止めておきます。

# HTTP serverの動作確認

上記までの手順でサンプルを起動させることはできましたが、HTTP serverが動作しているのかわからないので、動作確認をしていきます。
まず、HTTPサーバーとして利用するには「NUCLEO-F429ZI」とルータ(もしくはルータ付きアクセスポイント)とcubeIDEを起動しているPCを下記の図のように接続します。

![接続図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/8c517f93-959e-ad56-88d6-bce99b3cd206.png)


このように設定するのは、使用しているサンプルはDHCPクライアントが動作するようになっており、「NUCLEO-F429ZI」のIPアドレスをルータから取得する仕様だからです。
サンプルを改変すれば、任意のIPアドレスを設定して実行できるかとは思いますが、修正量が多いので今回はDHCPを使ってIPアドレスを取得する方法で動作確認を行います。

先ほど示した画像のようにPCとルータとボードを接続したら、先ほどデバッグ実行を行ったように、プロジェクト「LwIP～」を右クリックし「Debug As」→「STM32 C/C++ Application」を選択します。これでまたCubeIDEの画面が切り替わります。
ただ、動作確認にはDHCPで設定したIPアドレスがわからないといけないので、IPアドレスを取得後の箇所にブレークポイントを設定し、デバッガからIPアドレスを取得します。
ブレークポイントは「app_ethernet.c」の下記の場所をダブルクリックすれば設定できます。

![ブレークポイント位置.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/a26b4016-b27c-1b60-efda-f724dc09e8ff.png)


ブレークポイントを設定できたら、先ほどと同様に再生ボタンのような形のアイコンをクリックして実行します。すると、先ほどブレークポイントを設定した箇所でブレークします。

ここで、現在設定されているIPアドレスを調べます。下記の画像のようにCubeIDEに使用している変数の値が表示されますので、「netif」→「ip_addr」→「addr」を選択してください。この変数「addr」にIPアドレスが格納されています。

![IPアドレス取得方法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/9b162014-1093-7c65-5a8f-f0ab2fa10829.png)


ただし、ここで設定されているIPアドレスはリトルエンディアン表記になっています。よって、左からではなく、右から1byteずつ読むことになります。
例えば、「addr」の値が16進数表記で「0a0ba8c0」ならば、IPアドレスは「192.168.11.10」となります。「0b64a8c0」ならば、IPアドレスは「192.168.100.11」となります。10進数表記から16進数表記への変更は、「addr」の値を右クリックして表示されるメニューから変更可能です。

このIPアドレスの値をどこかにメモしたら、再生ボタンのような形のアイコンをクリックして再度実行させます。

最後に、ルータとつながっているPCのwebブラウザのアドレス欄に先ほど取得したIPアドレスを入力し、Enterを押すと下記のような画面が出ます。

![HTTPserverページ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/55af854b-08e4-e4d5-68f1-525c9257ed01.png)


これで、「NUCLEO-F429ZI」で有効になっているHTTP serverに、下記のような流れでアクセスできることを確認できました。

![サンプル動作.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266944/36512ce9-8417-7f66-c5ba-717350748dcc.png)


次の[記事](https://qiita.com/tom_S/items/c1b1bfc030a67fe7977a)では、サンプルのソースコードの実装を見ていきたいと思います。