Newer
Older
m5stickcplus / week2.rst
@Motoki Miura Motoki Miura on 12 Apr 2022 7 KB faq
2週目
========================

1週目で学んだことを活かして、組み合わせてみましょう。

.. note::  一部古い記述がふくまれています。Arduino IDE → arduino-cli におきかえてください。


複数人で書いたプログラムを統合する
------------------------------------------------------------------------------

- Arduino IDEでは、プログラムを複数のファイル(たとえば、main.ino / sub.ino / hoge.cpp / hoge.h ) に分割して記述することができます。複数ファイルに分割することで、関数定義を機能別にまとめることができ、管理しやすくなります。
- Arduino IDEでは、プログラムを構成する、複数のファイル(スケッチブック)を、1つのフォルダに入れて管理します。(スケッチブックのことを、他のIDEでは「プロジェクト」と呼ぶ場合もある)
- スケッチブックに別のファイル(hogehoge.ino) を追加するには、右上にあるシリアルモニタをひらくアイコンの、下の「▼」ボタンからメニューをひらき、「新規タブ」を選択し、ファイル名(拡張子.ino をのぞいた、hogehogeの部分のみ)を入力します。
- スケッチブックをコピーしたいときは、内包するフォルダごとコピーしてください。**その際、フォルダ名と、メインのソースコードファイル名(拡張子以外の部分)は、一致している必要があります。**
- 複数のファイルを置いたときの挙動について: ``***.ino`` ファイルの内容は、単純にメインのタブ(フォルダ名と同じinoファイル)にマージされます。``***.cpp`` や ``***.c`` という拡張子でファイルを作成した場合は、``***.h`` を作成する必要があります。`参考:Properly using separate tabs with Arduino IDE <https://arduino.stackexchange.com/questions/50210/properly-using-separate-tabs-with-arduino-ide>`_ 
- Git を利用すると、複数人で作業したファイルを統合しやすいです。

タスク
--------------------------------------------------

複数の機能を1つの ``loop()`` にまとめようとすると、プログラムが複雑になります。タスクを用いると、 ``loop()`` に相当する関数を複数定義し、並列に動作させることができます。

:numref:`task01` に、タスクを利用する例を示します。3つの異なるタスクを作成し、それぞれの関数内部で ``setup()`` と ``loop()`` に相当する処理を記述しています。
引数の詳細については、`非公式日本語リファレンス <https://lang-ship.com/reference/unofficial/M5StickC/Functions/freertos/task>`_ を参照してください。
ここの例では、1つのファイルに記述していますが、タスクごとに別のファイルにすることもできます。 以下の例ではタスク生成時に、タスクハンドル ``TaskHandle_t`` を設定しています。タスクハンドルは、タスクの一時停止(サスペンド)や、再開(レジューム)、削除のときにタスクを特定するために必要となります。

.. literalinclude:: src/task01.ino
  :caption: 
  :name: task01
  :language: arduino
  :linenos:
  :emphasize-lines: 4,63-65

.. note:: 参考:  `FreeRTOSでマルチタスク (on ESP32) <https://qiita.com/hideakitai/items/bd95d0db63097b8808f9>`_

タスク生成時に、引数を渡すこともできます。:numref:`task02` に、引数を渡す例を示します。(次で述べるミューテックスを使って、排他制御もしています。)

.. literalinclude:: src/task02.ino
  :caption: 
  :name: task02
  :language: arduino
  :linenos:
  :emphasize-lines: 1,6,8,20,21,33,41

.. warning:: 引数をアドレスで渡すとき、関数内で宣言したローカル変数は使えません。グローバルな変数を使用する必要があります。

ミューテックスとセマフォ
----------------------------------------------------------

複数のタスクを並列動作させると、リソース(入出力や、メモリ)に複数のタスクが同時アクセスすることで意図しない動作を引き起こすことがあります。
ミューテックス(mutex: mutual exclusion)を用いると、リソースに同時にアクセスするタスクを1つに限定することができます。これを「排他制御」と呼びます。

:numref:`task02` の例では、ミューテックスをつかって、1つのタスクの動作(シリアルコンソールへの書き込み)が終わるまで、他のタスクが待つ例です。
このように、常時動いているタスクに対して、一時停止したり、処理を制限したりするのがミューテックスの使い方です。
(参考:`ESP32のFreeRTOS入門 その6 セマフォとミューテックス <https://lang-ship.com/blog/work/esp32-freertos-l06-semaphore-mutex>`_ )

これに対して、セマフォは、基本的には待機・一時停止状態にあるタスクに対して、動作許可を与える用途で使用されます。
動作許可を与える主体・タイミングとしては、他のタスクや、「割り込み(ISR: interrupt service routine)」からになります。
ただし、バイナリセマフォを用いるより、`RTOS Task Notifications <https://www.freertos.org/RTOS_Task_Notification_As_Binary_Semaphore.html>`_
を用いたほうが、高速かつメモリ使用量を削減できるようです。

- バイナリセマフォは、タスク間またはタスクと割り込み間の同期に適しています。
- バイナリセマフォとミューテックスは似ていますが、いくつか本質的な違いがあります。ミューテックスは優先度を継承する機構が備わっていますが、バイナリセマフォには備わっていません。

.. note:: 参考: `RTOS binary semaphore API <https://www.freertos.org/xSemaphoreCreateBinary.html>`_ 

キュー
--------------------------------------

参考:`ESP32のFreeRTOS入門 その5 キュー <https://lang-ship.com/blog/work/esp32-freertos-l05-queue>`_ 



FreeRTOSと、その他のRTOS
----------------------------------

今回の実験では、Arduino IDEでのM5StickCPlusプログラミングを行ってきました。これまでArduino IDEでM5StickCPlusに書き込んできたプログラムは、FreeRTOS (RealTime OS) というRTOSの仕組みをつかって動作しています。
いいかえると、ESP32プロセッサ上で、FreeRTOS プログラミングをしていたことになります。ちなみに、M5StickCPlusのような画面やブザー、センサがついていない `ESP32プロセッサ開発ボード <https://akizukidenshi.com/catalog/g/gM-15673>`_ も販売されています。

- MCU RTOS習得(2020年版) http://happytech.jp/bRTOS.html

その他のRTOSには、T-Kernel や ThreadX があります。こちらも、限られた資源(メモリやプロセッサ)で、厳密な処理時間管理が行える仕組みが備わっています。

- 参考:`2020年度 情報通信工学実験1 リアルタイムプログラミング【RTP】 <https://cit.istlab.info/ex1>`_