コの字のお陰で、やる気が出ないだけでなく、夢見も悪いです。毎日、毎日「カンセンカクダイ」のニュースばかり見ているためかも。まあ、ボチボチ慣れていかねばね。前回動かしたサンプルプログラムを読みながら、ESP-IDF上のFreeRTOS環境でのESP-32の使い方を学んでいきたいと思います。
※「モダンOSのお砂場」投稿順Indexはこちら
さて、サンプルプログラムの処理の先頭
app_main()
から読み進めていきたいと思います。しかし、ESP32とESP-IDFのAPIなどにも不慣れなので、引っかかるところが出てきたら随時「脱線」して調べてないとなりません。だいたいこの app_main()自体、FreeRTOS内のどこかで呼び出されている筈なので、その呼び出し元を遡りたい気も多いにするのです。が、まずは呼び出される側の概要を把握してから、ということにいたしました。本日読み進める部分のコードを引用させていただきます。たったこれだけ。
コードどころか、最初のコメントで引っかかってしまったからであります。「NVS」の初期化。NVSとは何ぞや、これはESP32の機能っぽいということで調べてみると説明がありました。NVSを使うためのAPIを解説しているページは下のリンクから。
勝手にNVSの特徴を掻い摘んで列挙するならば
- キー、バリュー型の不揮発なストレージとして使用できる領域
- 物理的にはESP32チップの「外」に置かれたFlashメモリ上に確保される(ESP32のシールドを被ったモジュールから見ればFlashメモリは「内側」にある)
- 各種フォーマットの整数、文字列、バイナリ(Blob)を格納できる。
- ネームスペースという概念あり、複数の「アプリ」で共用してもキーがぶつからないようにもできる
Flashメモリを書き換えるのは結構面倒な(ロウ・レベルの)作業なので、その辺をAPIの中に隠して、アプリプログラムからはキー、バリュー型のストレージに見えるというのは、なかなか便利な機能じゃないかと思います。NVSの意図としては、コンフィギュレーション情報などを記憶させておく領域だということです。後に述べるパーティションテーブルを書き換えてビルドすれば、使える領域を増やせるようですが、本来的にはコンフィギュレーション情報を保持する程度の小さなストレージとして使うものらしい。古典的なマイコンなどではシリアル接続の外付けE2PROMをこういう目的によく使いました(しょぼいFlashプロセスのMCUだとFlashの書き換え回数が心配なので、E2PROMのが安心だったりする)が、外付けのFlashメモリの一部をそういう目的に使えるのであれば、それに越したことはありません。今回使用しているESP32 DevkitCの場合は4Mバイトもあります。
しかし気になるのは、Flashメモリのどの辺をどう使っているの?という問題です。NVSも、プログラムで使う領域も物理的には同じメモリの一部なのでそれらの領域をどう設定しているの?という疑問と言い換えても良いです。調べてみると以下のテーブルで領域を設定しているようです。
VS Code上で動作しているPlatformIOがインストールするESP-IDFフレームワークの場合、ユーザーフォルダの下の以下のところに設定用のテーブルとツールが格納されていました。
.platformio/packages/framework-espidf/components/partition_table
基本、0x1000番地単位(サイズとしては4Kバイト)で割り当てるようでした。パーティションテーブルそのものもFlashの特定番地に書き込まれるようです。デフォルト設定では、パーティションテーブルそのもののオフセットが0x8000番地スタートの0x1000バイト。そして、nvsは、0x9000番地スタートで、サイズとしては0x6000バイト(24Kバイト)分確保されているようです。
さて、NVSというものが少し理解できたところで、順次APIを見て行きたいと思います。しかし、いちいち先ほどのAPIページを参照しなくても VS Codeのお陰でカーソルを持っていくだけで、概要は分かってしまう。こんな感じ。
まずは、イニシャライズしてみる、そして返ってきた戻り値を確かめる。戻り値で「書き込めるページがありません」エラーが返ってきたら(Flashメモリなので、バイトのような小さな単位では書き込めず、ある塊の「ページ」単位で書き込みする必要があるのだと思います。その辺見ないでもキー、バリューで管理できるのがAPIの御利益)、使われているページを一気に削除と(そうしないとサンプルソフトが動かないから)。その削除APIの戻り値もまたチェック。
チェック用のマクロの中身と、展開したところもVS Codeはしっかり見せてくれるので、このマクロは何?などと調べ回らなくても済みます、楽ちん。なお、C言語に慣れている人は、上のマクロで使われている以下の「イデオム」はよくお分かりのことだろうと想像します。
do { } while(0)
これだけ見たら意味無のシーケンスですが、この{}の中に複数の文を入れておくことで、安全に展開できる、と。
内部で呼ばれているNVSの消去用APIについてもポップアップを見ればOK。
書くのも、読むのもVS Code、便利です。つづきはまたそのうち。次は、FreeRTOSらしいAPIに入れるかな?