0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RX72N Envision Kit で 学習する。(Queue on FreeRTOS)

0
Posted at

本投稿では

FreeRTOSQueue を使って、

  • ボタン状態取得タスク
  • LED 表示タスク

の間でタスク間通信を行い、ボタンを押下でON、解放でOFFするようなファームウェアを作成してみる。

環境

  • IDE:e2studio
  • ボード:RX72N Envision Kit
  • コンパイラ:CC-RX(ツールチェーン Renesas CC-RX v3.07.00)

作業開始

まず、前回の作業を参考に、プロジェクト作成までは完成させておく。
https://qiita.com/yt1114/items/07f08d55bebd5efc71bf

1. Queue の追加

下図のように、FreeRTOS_Object の Queue タブを開き+を押下する。
すると、queue_handle_1という名前のハンドラができる。作成したときはキューの長さが100になっているが今回は気にしなくてよい。(正直言って、今回は1にしても動く)

2. タスクの作成

冒頭でお話しした、ボタン状態取得タスク(BTN_TASK)とLED表示タスク(LED_TASK)を追加する。

タスクを追加したら、コード生成を行う。すると、下記のように.cファイルができる。

image.png

3. 各タスク内の処理

BTN_TASK (送信側)

ボタンの状態を取得するタスク。
5msの周期で実行するように、vTaskDelayUntilを入れる。
また、キューに5ms周期で状態を毎回送るのはあまり気持ちとして良くないので、ボタンの状態が変わった時だけ送るようにした。

void button_task(void * pvParameters)
{
/* Start user code for function. Do not edit comment generated here */
    TickType_t xLastWakeTime; // 最後にタスクが実行された時刻を記録する変数
    const TickType_t xPeriod = pdMS_TO_TICKS(5); // 周期を500ミリ秒に設定
    uint8_t current_state, previous_state = 1;
    xLastWakeTime = xTaskGetTickCount();
    extern QueueHandle_t queue_handle_1;

    while(1)
    {
        // xPeriodの間隔でタスクが実行されるように待機
        vTaskDelayUntil( &xLastWakeTime, xPeriod );

        // ボタン状態を読み取る
        current_state = PORT0.PIDR.BIT.B7;

        // 状態が変化した場合、キューに送信
        if (current_state != previous_state)
        {
        	// 第1引数:キューハンドル
        	// 第2引数:キューに入れたい値
        	// 第3引数:キューが満タンの時に空きができるまで待機する時間(ブロッキング)
        	if (pdPASS == xQueueSend(queue_handle_1, &current_state, 0)) {
                // もしキューが満タンでタイムアウトすれば、戻り値はpdFAIL
                previous_state = current_state; // 現在の状態を保存
        	}            
        }
    }
/* End user code. Do not edit comment generated here */
}

LED_TASK (受信側)

BTN_TASK から送られてきたボタンの状態をキューから取り出し、押下されているときはLEDをONにする。離されているときはLEDをOFFにする。

void led_task(void * pvParameters)
{
/* Start user code for function. Do not edit comment generated here */
    uint8_t button_state;
    extern QueueHandle_t queue_handle_1;

    while (1)
    {
        // キューにメッセージが届くまでタスクをブロックする
       	// 第1引数:キューハンドル
      	// 第2引数:キューから取り出した値を入れる変数。
       	// 第3引数:キューからデータを取り出せるようになるまで待機する時間(ブロッキング)
        if (xQueueReceive(queue_handle_1, &button_state, portMAX_DELAY) == pdPASS)
        {
            // メッセージ受信成功
            if (button_state == 1) // ボタンが押された
            {
                // LEDを点灯
            	PORT4.PODR.BIT.B0 = 1;
            }
            else // ボタンが離された
            {
                // LEDを消灯
            	PORT4.PODR.BIT.B0 = 0;
            }
        }
    }
/* End user code. Do not edit comment generated here */
}

結果

押しているときに光って、離すと消えた!
無題のビデオ ‐ Clipchampで作成.gif

このように1つのモジュールに対して1つのタスク、というふうにコードを作っていけば、
タスク間通信もでき、簡単にできていきそうな気もする。
が、タスクが乱立するとそれはそれで、設計上よくないはず…これから勉強していくなかでより良い設計とは何ぞやというものを習得していこうと思う。

次回

RX72NとPCで通信を行い、メッセージでLEDをチカチカさせたい。
メッセージを受け取るのは、FITのSCIモジュール(ASYNCモード)で行う。受け取った情報(バイト列)はSCIモジュールのFIFO(R_BYTEQ)に格納される。
これを処理するために、「UART受信割込み」と「通信制御タスク」の2つ通信を行い、「LEDタスク」に情報を伝えて、点滅などさせるようにしたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?