FSP + FreeRTOSでタイマ割り込み10us

FreeRTOSでタイマーを使いたいときに

ソフトウェアタイマが使えるようですが

Tick Rate Hzがデフォルトだと1000で

xTimerCreateの引数を最小の1にしても1msタイマが最小になるかと思います。

今回10usタイマを作りたいのですが、

Tick Rate Hzを100000にすると、全く動作しなくなりました(何が起こってるのかすら分かってない)

//Tick Rate Hz = 1000 (default) // 1 = 1ms; // 10 = 10ms; // 100 = 100ms; // 1000 = 1000ms; //Tick Rate Hz = 10000 // 1 = 0.1ms; // 10 = 1ms; // 100 = 10ms; // 1000 = 100ms; xTimer = xTimerCreate("timer", 1, pdTRUE, (void*)0, vTimerCallback);

いろいろネットで検索していると

ソフトウェアタイマで10usは厳しいようなので

ハードウェアタイマを使うべきとあります。

そこで、今作成しているスレッドにE2StudioのStackのところでタイマを追加してやってみました。

結果ですが、

10usタイマのcallbackが呼ばれて、カウント動作はしているのですが

なぜか不定期にタイマー値が戻ってしまいます。

現在CAN の通信モニタを作っており、CANで受信したデータに10us単位のタイムスタンプをつけて、

EthernetのUDP通信でパソコンに送信しています。

下記はそのパソコンで受信した結果です。赤チェック部分のタイムスタンプがおかしい部分です。少し巻き戻った値になってしまっています。

マイコンC言語自体は15年ほどやっておりハードウェアタイマ割り込みなどは理解しているつもりですが

FreeRTOSやOSの知識はほとんどなく、今回はじめてFreeRTOSでの開発をしています。

単純にFSP + FreeRTOSで10usタイマを使用する場合、この使い方で良いのかが気になっております。

Stackの設定画面で追加したスレッドに、タイマ General PWMを追加して使うのは正しいやりかたなのでしょうか?

注意点等ありますでしょうか?

また原因が分かればご教授いただけると助かります。

Parents
  • 今、気付いたことが。

    下記、タイムスタンプ部分(k_tmr_10usの値の16進数表示)

    0x0003FF77

    の次がなぜか

    0x000312FF

    になっている。

    16bitから繰り上がるときにおかしくなってる。

    なんでだろう。。。

    きちんと繰り上がるときと、繰り上がらないときがある。

    タイマ割り込みの使い方の問題ではない気がしてきました。

  • 申し訳ございません!

    Ethernetのパケットにセットする部分(1byteずつに分解) でやらかしておりました。

    誤:

    cString[4] = (uint8_t)((rcv_can_frame.ts_10us >> 24) & 0xFF);

    cString[5] = (uint8_t)((rcv_can_frame.ts_10us >> 18) & 0xFF);

    cString[6] = (uint8_t)((rcv_can_frame.ts_10us >> 8) & 0xFF);

    cString[7] = (uint8_t)(rcv_can_frame.ts_10us & 0xFF);

    正:

    cString[4] = (uint8_t)((rcv_can_frame.ts_10us >> 24) & 0xFF);

    cString[5] = (uint8_t)((rcv_can_frame.ts_10us >> 16) & 0xFF);

    cString[6] = (uint8_t)((rcv_can_frame.ts_10us >> 8) & 0xFF);

    cString[7] = (uint8_t)(rcv_can_frame.ts_10us & 0xFF);

    解決しました。。。

    10usタイマ、問題なく作動しました。

    お騒がせしました

  • 質問が少し変わってしまいますが

    ハードウェアタイマ割り込み10usはOS管理外なので

    OS管理のタスクは若干処理が遅れる

    という考え方で合ってますでしょうか?

    また、ハードウェアタイマ割り込み内でインクリメントしている変数を

    タスク内で参照する場合に、セマフォを使って排他制御したほうがよいのでしょうか?

    ハードウェアタイマ割り込みハンドラー

    callback_10us()

    {

        take(セマフォ)

        tmr_10us++

        give(セマフォ)

    }

    参照部分

        take(セマフォ)

        cString[4] = (uint8_t)((tmr_10us >> 24) & 0xFF);

        cString[5] = (uint8_t)((tmr_10us >> 16) & 0xFF);

        cString[6] = (uint8_t)((tmr_10us >> 8) & 0xFF);

        cString[7] = (uint8_t)(tmr_10us & 0xFF);

        give(セマフォ)

Reply
  • 質問が少し変わってしまいますが

    ハードウェアタイマ割り込み10usはOS管理外なので

    OS管理のタスクは若干処理が遅れる

    という考え方で合ってますでしょうか?

    また、ハードウェアタイマ割り込み内でインクリメントしている変数を

    タスク内で参照する場合に、セマフォを使って排他制御したほうがよいのでしょうか?

    ハードウェアタイマ割り込みハンドラー

    callback_10us()

    {

        take(セマフォ)

        tmr_10us++

        give(セマフォ)

    }

    参照部分

        take(セマフォ)

        cString[4] = (uint8_t)((tmr_10us >> 24) & 0xFF);

        cString[5] = (uint8_t)((tmr_10us >> 16) & 0xFF);

        cString[6] = (uint8_t)((tmr_10us >> 8) & 0xFF);

        cString[7] = (uint8_t)(tmr_10us & 0xFF);

        give(セマフォ)

Children
  • callback_10us実行の時、優先度がFreeRTOSより上ならFreeRTOSはCPUが使えない状態になるので雰囲気的にはその瞬間、FreeRTOSから見たらCPUがなくなった状態と同義かなと・・・なお、callback_10us関数でtmr_10usにセマフォを使ってもうまくいかない気がします。そんなことするより、tmr_10us変数の値をFreeRTOSのタスクで参照する部分の先頭でローカル変数に値を一時コピーしてコピーの値に対して処理をしたらいい気がします。もし、外部の割り込みで複雑なデータ型がありアトミックな命令で処理が終わらない場合はその割り込みを禁止し、ローカルコピー、割り込み解除、ローカルコピー値に対してい処理をするみたい私なら実装します。