ESP32でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 7タスク目 [ESP32]
現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf
しかし、FreeRTOSにはまだ400頁もあるドキュメントが2つも有るのか、、、
https://www.freertos.org/Documentation/RTOS_book.html
ESP32はRTOSができるらしい、、、
タスク間通信のデータキューについて、、、
μiTRONにも「同期・通信機能」としてデータキューがある。
※FreeRTOSが提供する関数のうちいくつかは、割り込みの中で使用できない。割り込みの中で同等の機能を実現する為には、割り込み専用の関数を利用することとなる。μiTRONならxxx_yyy形式の関数(サービスコール)名の先頭にiを付けて、割り込み専用としてixxx_yyy形式の関数(サービスコール)が提供されている。関数(サービスコール)の命名規則は色々有るだろうけれど、μiTRONの命名規則は簡潔でわかりやすい。
それぞれ個別に個別のコンテキストで動いているタスクが、お互いに協調動作を目的として同期を取ったり通信するいくつかの機能が提供されている。
その1つがデータキューと言う、まさにタスク間でデータの送受をする為の機能となる。
この機能は無ければ無いでなんとかなる。FIFOを使えば大域変数経由でタスク間通信が可能だから。※FreeRTOSのスレッドモデルでは、メモリ空間を共有している為。
とはいえ、有るものは使った方が楽だし、同期機能も同時にサポートされる。
データキューのデータを蓄える機能はほぼFIFOなので、扱うデータ型のサイズと、データ数を指定してデータキューを生成する事となる。
データキューはデータを書く側と、それを読む側の2者がいるが、実は書く側も、読む側も複数でも構わない。つまり1対1の通信だけでなく、n対1でも、1対nでも、n対nも可能である。
もし読む側がデータキューからデータを読もうとして有効なデータが存在しなかった時は、その読む側のタスクは待ち状態(BLOCKED)に遷移させられる。
書く側のタスクが有効なデータをデータキューに書き込めば、そのデータキューで待たされているいくつかのタスクの中からもっとも優先度の高いタスクが待ち状態から実行可能状態(READY)に遷移されてデータを読む事ができる。
タスクの優先度が同一の場合、もっとも長く待っているタスクが読む事ができる。
もし書く側がデータキューにデータを書こうとしてもデータキューがいっぱいであったら、そのタスクは待ち状態(BLOCKED)に遷移させられる。
読む側のタスクがデータキューからデータを読み出せば、書く側で待たされているいくつかのタスクの中でもっとも優先度の高いタスクが実行可能状態(READY)に遷移されてデータを書く事ができる。
タスクの優先度が同一の場合、もっとも長く待っているタスクが書く事ができる。
〇データキューの生成
xQueueCreate関数を使用してデータキューを生成する。プロトタイプは以下となる。
(1) uxQueueLengthはデータを最大いくつ格納するかを示す。
(2) uxItemSizeはデータのサイズを示す。単位はbyteとなる。
格納するデータは、int型とかdouble型等の一般的な型に限らず、たとえば構造体も格納する事ができる。
(3) 戻り値:もしNULLが返って来たなら、データキューの生成に失敗している。NULL以外が返って来たら、その値はデータキューにアクセスする為のハンドルとして利用される。
〇データキューにデータを書く
この関数は2種類ある。1つはxQueueSendToBackと言うデータキューの最後にデータを追加するもの。もう1つはxQueueSendToFrontと言うデータキューの先頭にデータを追加するもの。データキューをFIFOと見れば、xQueueSendToBackが今までのイメージに近いと思う。ちなみにxQueueSendToBackとxQueueSendは同じものらしい。
※xQueueSendToFrontの意義
おそらくデータそのものに優先度が有る時、FIFOの中で順番待ちをするのではなく、相手側に可能な限り早く届けたい。そんな要求に応えるものだと思われる。μiTRONにも同様の機能が存在する。
関数のプロトタイプは以下となる。
(1) xQueueは生成した時に受け取ったハンドル。
(2) pvItemToQueueは書き込むデータのポインタ。
渡したデータは関数内部でコピーしてキューに格納される。
(3) xTicksToWaitは待ちタイムティック。もしデータキューがいっぱいであったら、その後タスクはBLOCKEDに遷移させられるのだが、その最大時間(タイムティック数)を引数として渡す。
xTicksToWait が0であったら、即座に関数から戻ってくる。
xTicksToWait がportMAX_DELAYであったら、書き込めるまで永久待ちとなる。条件としてFreeRTOSConnfig.hの中のINCLUDE_vTaskSuspendが1であること。ESP32の場合は1となっている。
#define INCLUDE_vTaskSuspend 1
(4) 戻り値:成功すればpdPASSが返ってくる。失敗時はerrQUEUE_FULLが返る。失敗する原因はタイムアウトが発生している。
※タスク間通信でコピーが行われる、行われないは知っておくべき重要な情報である。
※待ち時間を設定するのは、もしなんらかの問題で書き込みが行われない時、問題発生を検出する1つの方法としてタイムアウトを設定する事はよくある。と言うか組み込みでは設定しないと危なくて、、、
※上記2つの関数は割り込みの中では使えない。割り込みの中から使う為には xQueueSendToFrontFromISRや xQueueSendToBackFromISRを使用する。
〇データキューからデータを読み出す
この関数は読み出すデータの扱いによってxQueueReceiveとxQueuePeekの2つの関数がある。xQueueReceiveはデータキューからデータを読み出した時、そのデータをキューから削除してしまう。逆にxQueuePeekは削除は行われない。
関数のプロトタイプは以下となる。
(1) xQueueは生成した時に受け取ったハンドル。
(2) pvBufferはデータを格納する領域のポインター。この領域にデータがコピーされる。なので領域サイズはこのデータを受け取るのに十分なサイズが必要。
(3) xTicksToWaitは待ちタイムティック。もしデータキューが空であったら、その後タスクはBLOCKEDに遷移させられるのだが、その最大時間(タイムティック数)を引数として渡す。
xTicksToWait が0であったら、即座に関数から戻ってくる。
xTicksToWait がportMAX_DELAYであったら、読み出せるまで永久待ちとなる。条件としてFreeRTOSConnfig.hの中のINCLUDE_vTaskSuspendが1であること。ESP32の場合は1となっている。
#define INCLUDE_vTaskSuspend 1
(4) 戻り値:成功すればpdPASSが返ってくる。失敗時はerrQUEUE_EMPTYが返る。失敗する原因はタイムアウトが発生している。
※タスク間通信でコピーが行われる、行われないは知っておくべき重要な情報である。
※待ち時間を設定するのは、もしなんらかの問題で読み込みが行われない時、問題発生を検出する1つの方法としてタイムアウトを設定する事はよくある。と言うか組み込みでは設定しないと危なくて、、、
※上記2つの関数は割り込みの中では使えない。割り込みの中から使う為には xQueueReceiveFromISR()を使用する。
〇データキューに格納されているデータの数を知る
関数のプロトタイプは以下となる。
(1) xQueueは生成した時に受け取ったハンドル。
(2) 戻り値:成功すればデータの数が返ってくる。0が返ってきたときは空である。
※この関数は割り込みの中では使えない。割り込みの中から使う為には uxQueueMessagesWaitingFromISR()を使用する。
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf
しかし、FreeRTOSにはまだ400頁もあるドキュメントが2つも有るのか、、、
https://www.freertos.org/Documentation/RTOS_book.html
ESP32はRTOSができるらしい、、、
タスク間通信のデータキューについて、、、
μiTRONにも「同期・通信機能」としてデータキューがある。
※FreeRTOSが提供する関数のうちいくつかは、割り込みの中で使用できない。割り込みの中で同等の機能を実現する為には、割り込み専用の関数を利用することとなる。μiTRONならxxx_yyy形式の関数(サービスコール)名の先頭にiを付けて、割り込み専用としてixxx_yyy形式の関数(サービスコール)が提供されている。関数(サービスコール)の命名規則は色々有るだろうけれど、μiTRONの命名規則は簡潔でわかりやすい。
それぞれ個別に個別のコンテキストで動いているタスクが、お互いに協調動作を目的として同期を取ったり通信するいくつかの機能が提供されている。
その1つがデータキューと言う、まさにタスク間でデータの送受をする為の機能となる。
この機能は無ければ無いでなんとかなる。FIFOを使えば大域変数経由でタスク間通信が可能だから。※FreeRTOSのスレッドモデルでは、メモリ空間を共有している為。
とはいえ、有るものは使った方が楽だし、同期機能も同時にサポートされる。
データキューのデータを蓄える機能はほぼFIFOなので、扱うデータ型のサイズと、データ数を指定してデータキューを生成する事となる。
データキューはデータを書く側と、それを読む側の2者がいるが、実は書く側も、読む側も複数でも構わない。つまり1対1の通信だけでなく、n対1でも、1対nでも、n対nも可能である。
もし読む側がデータキューからデータを読もうとして有効なデータが存在しなかった時は、その読む側のタスクは待ち状態(BLOCKED)に遷移させられる。
書く側のタスクが有効なデータをデータキューに書き込めば、そのデータキューで待たされているいくつかのタスクの中からもっとも優先度の高いタスクが待ち状態から実行可能状態(READY)に遷移されてデータを読む事ができる。
タスクの優先度が同一の場合、もっとも長く待っているタスクが読む事ができる。
もし書く側がデータキューにデータを書こうとしてもデータキューがいっぱいであったら、そのタスクは待ち状態(BLOCKED)に遷移させられる。
読む側のタスクがデータキューからデータを読み出せば、書く側で待たされているいくつかのタスクの中でもっとも優先度の高いタスクが実行可能状態(READY)に遷移されてデータを書く事ができる。
タスクの優先度が同一の場合、もっとも長く待っているタスクが書く事ができる。
〇データキューの生成
xQueueCreate関数を使用してデータキューを生成する。プロトタイプは以下となる。
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
(1) uxQueueLengthはデータを最大いくつ格納するかを示す。
(2) uxItemSizeはデータのサイズを示す。単位はbyteとなる。
格納するデータは、int型とかdouble型等の一般的な型に限らず、たとえば構造体も格納する事ができる。
(3) 戻り値:もしNULLが返って来たなら、データキューの生成に失敗している。NULL以外が返って来たら、その値はデータキューにアクセスする為のハンドルとして利用される。
〇データキューにデータを書く
この関数は2種類ある。1つはxQueueSendToBackと言うデータキューの最後にデータを追加するもの。もう1つはxQueueSendToFrontと言うデータキューの先頭にデータを追加するもの。データキューをFIFOと見れば、xQueueSendToBackが今までのイメージに近いと思う。ちなみにxQueueSendToBackとxQueueSendは同じものらしい。
※xQueueSendToFrontの意義
おそらくデータそのものに優先度が有る時、FIFOの中で順番待ちをするのではなく、相手側に可能な限り早く届けたい。そんな要求に応えるものだと思われる。μiTRONにも同様の機能が存在する。
関数のプロトタイプは以下となる。
portBASE_TYPE xQueueSendToFront( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait ); portBASE_TYPE xQueueSendToBack( xQueueHandle xQueue, const void * pvItemToQueue, portTickType xTicksToWait );
(1) xQueueは生成した時に受け取ったハンドル。
(2) pvItemToQueueは書き込むデータのポインタ。
渡したデータは関数内部でコピーしてキューに格納される。
(3) xTicksToWaitは待ちタイムティック。もしデータキューがいっぱいであったら、その後タスクはBLOCKEDに遷移させられるのだが、その最大時間(タイムティック数)を引数として渡す。
xTicksToWait が0であったら、即座に関数から戻ってくる。
xTicksToWait がportMAX_DELAYであったら、書き込めるまで永久待ちとなる。条件としてFreeRTOSConnfig.hの中のINCLUDE_vTaskSuspendが1であること。ESP32の場合は1となっている。
#define INCLUDE_vTaskSuspend 1
(4) 戻り値:成功すればpdPASSが返ってくる。失敗時はerrQUEUE_FULLが返る。失敗する原因はタイムアウトが発生している。
※タスク間通信でコピーが行われる、行われないは知っておくべき重要な情報である。
※待ち時間を設定するのは、もしなんらかの問題で書き込みが行われない時、問題発生を検出する1つの方法としてタイムアウトを設定する事はよくある。と言うか組み込みでは設定しないと危なくて、、、
※上記2つの関数は割り込みの中では使えない。割り込みの中から使う為には xQueueSendToFrontFromISRや xQueueSendToBackFromISRを使用する。
〇データキューからデータを読み出す
この関数は読み出すデータの扱いによってxQueueReceiveとxQueuePeekの2つの関数がある。xQueueReceiveはデータキューからデータを読み出した時、そのデータをキューから削除してしまう。逆にxQueuePeekは削除は行われない。
関数のプロトタイプは以下となる。
portBASE_TYPE xQueueReceive( xQueueHandle xQueue, const void * pvBuffer, portTickType xTicksToWait ); portBASE_TYPE xQueuePeek( xQueueHandle xQueue, const void * pvBuffer, portTickType xTicksToWait );
(1) xQueueは生成した時に受け取ったハンドル。
(2) pvBufferはデータを格納する領域のポインター。この領域にデータがコピーされる。なので領域サイズはこのデータを受け取るのに十分なサイズが必要。
(3) xTicksToWaitは待ちタイムティック。もしデータキューが空であったら、その後タスクはBLOCKEDに遷移させられるのだが、その最大時間(タイムティック数)を引数として渡す。
xTicksToWait が0であったら、即座に関数から戻ってくる。
xTicksToWait がportMAX_DELAYであったら、読み出せるまで永久待ちとなる。条件としてFreeRTOSConnfig.hの中のINCLUDE_vTaskSuspendが1であること。ESP32の場合は1となっている。
#define INCLUDE_vTaskSuspend 1
(4) 戻り値:成功すればpdPASSが返ってくる。失敗時はerrQUEUE_EMPTYが返る。失敗する原因はタイムアウトが発生している。
※タスク間通信でコピーが行われる、行われないは知っておくべき重要な情報である。
※待ち時間を設定するのは、もしなんらかの問題で読み込みが行われない時、問題発生を検出する1つの方法としてタイムアウトを設定する事はよくある。と言うか組み込みでは設定しないと危なくて、、、
※上記2つの関数は割り込みの中では使えない。割り込みの中から使う為には xQueueReceiveFromISR()を使用する。
〇データキューに格納されているデータの数を知る
関数のプロトタイプは以下となる。
unsigned portBASE_TYPE uxQueueMessagesWaiting( xQueueHandle xQueue );
(1) xQueueは生成した時に受け取ったハンドル。
(2) 戻り値:成功すればデータの数が返ってくる。0が返ってきたときは空である。
※この関数は割り込みの中では使えない。割り込みの中から使う為には uxQueueMessagesWaitingFromISR()を使用する。
ITRONプログラミング入門 H8マイコンとHOSで始める組み込み開発
- 出版社/メーカー: オーム社
- 発売日: 2005/04/23
- メディア: Kindle版
リアルタイムOSと組み込み技術の基礎―実践μITRONプログラミング (TECHI (Vol.17))
- 作者: 高田 広章
- 出版社/メーカー: CQ出版
- 発売日: 2004/02
- メディア: 単行本
2018-02-19 16:54
nice!(0)
コメント(0)
コメント 0