2021年4月30日金曜日

ESP32 Memo 〜 LED Blink 〜

■概要

今まででMicroPythonをDL、Buildして、ESP32で動かすことはできた。
( URL:MicroPython ESP32 Memo 〜Run Python Script〜 )
今度は、ESP32の電源をONして、どんな処理が行われて、MicroPythonが動くようになるのかを知りたい。

公式HPによると、MicroPythonは、4種類のモジュールに分けて作られているらしい。
(MicroPython libraries)

  • 標準的なPythonサブセットを実装しており、ユーザーによって拡張されることを想定していないモジュール
    (Modules which implement a subset of standard Python functionality and are not intended to be extended by the user. )
  • Pythonのサブセットを実装しており、ユーザーによって拡張されることを想定しているモジュール
    (Modules which implement a subset of Python functionality, with a provision for extension by the user (via Python code).)
  • Python標準ライブラリにMicroPython拡張機能を実装しているモジュール
    (Modules which implement MicroPython extensions to the Python standard libraries.)
  • 特定のMicroPythonポートに固有であり、移植生のないモジュール
    (Modules specific to a particular MicroPython port and thus not portable.)

上記のうち、4つ目の、移植性のないモジュールのところで、MicroPythonが動くまでの処理を知りたい。 この部分は、マイコンに固有の処理を行うところで、ここを知れば、他のマイコンにMicroPythonを移植することも可能だと思う。

最終的には、他のマイコンにMicroPythonを移植できるようになりたい。

現在、ESP32でMicroPythonを動かすことはできたものの、中身がどうなってるのかは不明。 というか、プログラムがどこから始まるのかもわかっていない。

そこで、まずはESP32の基本的な知識を学ぶ必要がある!
というわけで、プロジェクトを初めから作成して、Lチカまでできるようになるぞー!

■環境

  • PC : Mac OS Catalina
  • Board : ESP32-WROOM-32D 開発ボード ESP32-DevKitC-32
  • 開発環境 : ESP-IDF

■前提知識

なし?

■手順

ESP-IDF Programming Guide を参考に作業を行う。
また、LEDの接続は、MicroPython ESP32 Memo 〜Run Python Script〜 と同じにする(32番ピンにLEDを接続)。 まずは開発環境の構築から。 と思ったけど、すでにやってたので、こちらを参照。
(URL: MicroPython ESP32 Memo 〜Build MicroPython〜)
環境変数の設定からはやっていないので、そこから始める。 ちなみに、ファイル構成は以下の通り。

MicroPython
    |- project
        |- esp-idf         // esp-idfのコードをクローンしたところ
        |- esp32_practice  // ここにLチカのプロジェクトを作る
        |- micropython     // micropythonのコードをクローンしたところ(今回は関係ない)
  

terminalでは、最初にMicroPythonフォルダにいるものとする。 というわけで、環境変数を設定する。

  1. 環境変数を設定する。
    「. $HOME/・・・/Micropython/project/esp-idf/export.sh」
    (※・・・ は割愛)
  2. エイリアスを設定する。(よく使う人向け)
    「alias get_idf='. $HOME/・・・/Micropython/project/esp-idf/export.sh'」
    これをすることで、「get_idf」だけで、環境変数の設定(esp-idf/export.sh)を実行できるようになるため、 esp-idfの環境の設定やリセットを簡単にできるようになる。

次に、プロジェクトを作成してビルドする。
(プロジェクトを作成すると言っても、サンプルプロジェクトをコピーするだけ。)

  1. プロジェクトを作成する。
    (サンプルのプロジェクト(hello_world)をコピーする)
    「cd project/esp32_practice」
    「cp -r ../esp-idf/examples/get-started/hello_world .」
  2. プロジェクトフォルダに移動する。
    「cd hello_world」
  3. ターゲットCPUを設定する。
    「idf.py set-target esp32」
    (※ この操作は、プロジェクトを作成してから1回だけ実行すべきらしい。)
  4. コンフィグレーションを設定する。
    「idf.py menuconfig」
    このmenuconfigで、Wifiの名前やパスワードなどを設定できるらしい。
    ただ、今回のhello_worldではデフォルトのままでいいので、何もいじらなくていいため、即閉じる。 (※ ESP32-DevKitC の ESP32-SOLO-1 が載っているのを使用している場合は、CONFIG_FREERTOS_UNICORE のパラメータを変更して、シングルコアモードをEnableにしないといけないらしい。)
  5. プロジェクトをビルドする。
    「idf.py build」

最後に、ビルドしたイメージをボードにダウンロード、動作を確認する。

  1. ボードをPCと接続する。
  2. ビルドしたイメージをボードにダウンロードする。
    「ls /dev/tty.usb*」
    (接続されたポートをチェックする。
     /dev/tty.usbserial-xxxx につながっていたと仮定する)
    「idf.py -p /dev/tty.usbserial-xxxx -b 460800 flash」
  3. 動作確認する。screenコマンドでシリアルをモニタする。
    カウントダウンと「Hello world!」が表示されれば成功!
    「screen /dev/tty.usbserial-xxxx 115200」

というわけで、プロジェクト作成(サンプルをコピーしただけ)とビルド、書き込みまではできたが、、、
LED、光らせてない。。。
というか知りたい情報はこれじゃない感。。。
とりあえず、LEDを光らせるまではやろうと思う。

サンプルの中に、LEDを点滅させるプロジェクトが実は用意されているので、これを利用する。

  1. LED点滅のプロジェクトをコピーする。 「cd ../」
    ( MicroPython/project/esp32_practice ディレクトリに移動)
    「cp -r ../esp-idf/examples/get-started/blink .」
  2. blinkプロジェクトフォルダに移動。
    「cd blink」
  3. ターゲットCPUを設定。 「idf.py set-target esp32」
  4. コンフィグレーションを設定する。
    今回は、LEDを点滅させるポートを変更するため、menuconfigを開く。
    「idf.py menuconfig」
  5. menuconfigが開いたら、LEDを点滅させるポートを変更する。 menuconfigの「Example Configuration」->「Blink GPIO number」を選択してEnter。
    LEDを接続しているポート(32番ピン)を入力してEnter。
    「S」を押して、Saveして、「Q」を押してQuit。
    menuconfigが閉じる。
  6. プロジェクトをビルドする。
    「idf.py build」
  7. ビルドしたイメージをボードにダウンロードする。
    「idf.py -p /dev/tty.usbserial-xxxx -b 460800 flash」
  8. LEDが1秒おきに点滅したら成功!
LEDの点滅までできた。
が、これではESP32の起動とか、どんなコード書いたらこうなるとか、全くわからん。

LED点滅のblink.cをみたが、void app_main(void) 関数のみが書いてあり、 その中で、FreeRTOSの vTaskDelay(1000 / portTICK_PERIOD_MS); を使って、1秒おきにGPIOのHigh/Lowを切り替えているだけだった。
一般的に、Bootloaderの実行が終わったら、main()関数が実行されるが、ESP32は、void app_main(void) 関数が実行されるようになっているらしい。
しかも、vTaskDelay()関数が実行されているということは、app_main()関数が実行されるまでに、 FreeRTOSの初期化関数等の実行もすでに完了されている。

知りたいのは、MicroPythonの実行のされ方。
ESP32の場合、MicroPythonは、FreeRTOSの上で動いているらしい。
つまり、FreeRTOSの初期設定が終わって、app_main()が実行されてから、MicroPythonの初期化を行って、REPLなどが実行されるようになっている?

とりあえず、ESP32は、bootloader実行後、app_main()関数が実行されることは分かったので、 MicroPythonのソースコードでapp_main()があるかどうかをみて、それを起点にMicroPythonのコードの中身を見ていきたい。
ちなみに、bootloaderで、ドライバやFreeRTOSなど、どんな設定をしているのかも知りたい。
・・・気が向いたら・・・。

0 件のコメント:

コメントを投稿