FreeRTOS StreamBuffer トリガー1バイトで1バイトセットしても receive で起床しない

大変お世話になっております。SAM です。

RL78/G23 で FreeRTOS V10.5.1 を動かそうとしています。
Fast Prototyping Board のサンプル(r20an0660xx0100-rl78.zip)の \portable\Renesas\RL78G2x をFreeRTOS V10.5.1 に持ってきて使っています。
サンプルは V10.4.3 でしたが \portable の全ファイルを V10.4.3, V10.4.6, V10.5.1 に亘って比較し差異は無かったので持ってきて使っても問題ないと判断しました。
FreeRTOSConfig.h、freertos_start.c、freertos_start.h はサンプル等を参考にして作りました。

StreamBuffer の異常についてですが UART 受信割り込みで xStreamBufferSendFromISR して getchar() で receive するのですが
バッファーに溜まっていることは確認したのですが recceive できません。トリガー1バイトでもダメです。

私が懸念しているは xStreamBufferCreate の中でバッファーを確保している部分で以下の Warning が発生していることです。

W0523082: 偶数アライメントのオブジェクトを指すポインタが奇数番地を保持しています。

分かる方がいらっしゃったらよろしくお願いします。

タスク、タイマー、セマフォは動作しているので全くダメではないと思っています。

  • こんにちは、ツチノコです。
    receiveする側のタスクのタスク優先度は確認済みでしょうか。
    UART 受信割り込みハンドラ内でportYIELD_FROM_ISR マクロのようなタスクスイッチを引き起こす実装を加えていない限り、割り込み完了後は割り込み直前に実行されていたタスクに戻ります。
    よって、receiveする側のタスクのタスク優先度が割り込み直前のタスクのタスク優先度より低い場合は、すぐさまreceiveのタスクが実行されない状況に陥ります。
  • SAMさん

    xStreamBufferCreate に以下の注意事項がありますが守られていますか?

    https://www.freertos.org/xStreamBufferCreate.html

  • ツチノコさん
    返信ありがとうございます。

    portYIELD_FROM_ISR()が無くて切り替わらなかったことを思い出しました。
    portYIELD_FROM_ISR()は実装しています。
    send 側のタスクとreceive 側のタスクは同じ優先度です。
    receive 側のタスクの優先度を上げることでゲットできることを期待したのですが変化はありませんでした。

  • PONSUKE さん
    返信ありがとうございます。

    configSUPPORT_DYNAMIC_ALLOCATION は 1 に設定しています。
    configUSE_SB_COMPLETED_CALLBACK は未定義でした。
    xStreamBufferCreateWithCallback() を使用しないので関係ないと思いますが

    https://www.freertos.org/a00110.html

    で、FreeRTOSConfig.h の #define を確認し、明示的に 0 にしました。
    FreeRTOSConfig.h の設定を見ています。
    問題は解決していません。

  • 実は Event Group でも同様の現象が発生しています。
    デバッガーでソースコードをステップ実行すると以下のようになりました。

    xEventGroupWaitBits(・・・, portMAX_DELAY) をたどると portYIELD_WITHIN_API() で止まります。
    IDLE タスクは動いているので、コンテキストが切り替わったと思います。

    xEventGroupSetBitsFromISR() をたどると正常に抜けました。PRIORITY を比較していることぐらいしかわかりませんでした。
    割り込み処理を出た後、Daemonタスクでタスクを起床させると思うのですがわかりませんでした。

    portYIELD_WITHIN_API() でハングしたという英語での質問がネット上に多くありましたが
    タスクの切り替えに問題はないので xEventGroupSetBitsFromISR() に問題があるのでしょう。

    他の RL78+FreeRTOS のソースコードを見つけたので参考にしたところconfigKERNEL_INTERRUPT_PRIORITY, configMAX_SYSCALL_INTERRUPT_PRIORITY は 3 固定という
    情報があり、取り入れました。
    また、G13, G23 両対応の優れものの portable でしたので取り入れました。現象は変わりませんでした。

  • SAMさん

    ご確認ありがとうございます。

    うーん、違いましたか。謎です。。

    FreeRTOS GithubのIssueを見ると以下のIssueがありました。

    同じ問題では無いかもしれないですが、参考にしてみてください。。

    https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/740

    以下の修正がいるのだとか

    Countermeasures (Fixed)

    The following changes will fix the problem.

    #define portYIELD_FROM_ISR( x ) if( x ! = pdFALSE ) portYIELD()

  • ありがとうございます。解決しました。

    私が着手したのが約2週間前だったので、そのタイミング情報を得られたのかと思うと
    口惜しいですが Github の仕組みを知ることができました。ありがとうございます。

    getchar() で 2バイト返すと scanf() で 1バイト返るという妙な標準入力の問題が
    残っていますが、これについては改めて質問させていただきます。

  • 解決して良かったです。

    PONSUKEさんへもportYIELD_FROM_ISR()のバグ情報を共有していただき感謝です。