RX65N+FreeRTOS+T4の受信動作競合について

おはようございます。YIと申します。

下記について、何かご存じでしたら教えてください。

T4 + FreeRTOSで tcp_rcv_dat 関数呼び出しと実際の受信が重なった時なのですが

tcp_rcv_dat 関数 処理が始まって vTaskSuspend (t4_driver.c内)でサスペンドになる前に

xTaskResumeFromISR (t4_driver.c内)が実行されて、その後 tcp_rcv_dat がサスペンドになり

復帰しなくなります。(レジュームがサスペンドを追い越してしまった)

xTaskResumeFromISR は lan_inthdr(t4_driver.c内) からの実行と思われます。

これは、tcp_rcv_dat を実行するタスクと lan_inthdr 割り込みの優先順位の設定に問題があるの

でしょうか。(e2studioのコンフィギュレータ設定を間違えている?)

以上、よろしくお願いいたします。

  • YIさん

    シェルティです、こんにちは。T4の設計者です。

    これ不具合かもしれないです。申し訳ありません。少し調べてみます。

    以下T4のコードです。

    https://github.com/renesas/rx-driver-package/blob/master/source/r_t4_rx/r_t4_rx_vx.xx/r_t4_rx/make_lib/make_lib.zip

    以下作りになっています。

    1: tcp_api.c 690行目でtcp_rcv_dat()

    2: tcp_rcv_dat()内で754行目でdis_int()で割込み禁止 -> 続く処理にてAPIリクエストを受け付ける(TCB構造体にリクエスト情報を書き残す)

    3: tcp_rcv_dat()内で771行目でena_int()で割込み許可

    4: tcp_rcv_dat()内で773行目でAPI完了待ちの為_tcp_api_req()が呼ばれる

        4a: _tcp_api_req() 内で850行目で_tcp_api_slp()が呼ばれる  -> APIリクエストの完了待ちに入る

    3のときに何らか受信イベントが発生すると確かに「APIリクエストの完了待ち」に入る前に「APIの完了報告があがる」ことが起きてしまい、4aでデッドロックしそうです。3を消せば治りそうですがコードの作り(関数内でopen/closeが対にならない)がおかしくなるので、治し方は要検討ですね。また、送信側も同様な問題がありそうです。

    少しさらに深堀してみます。

    以上です

  • シェルティ様

    YIです。こんにちは。

    お手数をお掛けして申し訳ございませんが、よろしくお願いいたします。

  • シェルティ様

    YIです。こんにちは。

    t4_driver.c内のSuspendとResumeを下記のように置き換えてみました。

    tcpの関数が動作しているタスクが1つなのでtid未使用で固定値としました。

    (tidを更新するタイミングがありませんでした)

    とりあえず動作していると思います。

    このような修正でも良いでしょうか。

    以上、よろしくお願いいたします。

    /*
    * sleep current task
    */
    static ER rtos_slp_tsk(void)
    {
    #if BSP_CFG_RTOS_USED == 1 // FreeRTOS
    #if 0 // Sunpend置き換え
        vTaskSuspend(NULL);
    #else
        ulTaskNotifyTake( pdFALSE , portMAX_DELAY);
    #endif
        return E_OK;

    #elif BSP_CFG_RTOS_USED == 4 // Renesas RI600V4 & RI600PX
        return slp_tsk();
    #else
        return E_OK; /* nothing to do */
    #endif
    }


    /*
    * wake-up task by id/handle
    */
    static ER rtos_wup_tsk(uint32_t tid)
    {
    #if BSP_CFG_RTOS_USED == 1 // FreeRTOS
        if(0 == tid)
        {
            return E_ID;
        }

    #if 0 // Resume置き換え
        if(0 == (get_psw() & 0x20000)) */
        {
            xTaskResumeFromISR((TaskHandle_t) tid);
        }
        else
        {
            vTaskResume((TaskHandle_t) tid);
        }
    #else
        if(0 == (get_psw() & 0x20000)) */
        {
            BaseType_t xHigherPriorityTaskWoken;
            xHigherPriorityTaskWoken = pdFALSE;
            vTaskNotifyGiveFromISR( xTaskEther, &xHigherPriorityTaskWoken );
            portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
        }
        else
        {
            xTaskNotifyGive( xTaskEther ) ;
        }
    #endif
        return E_OK;

        ・
        ・
        ・
        ・

  • YIさん

    シェルティです、こんにちは。

    本件詳細確認を進めております。非常に歩みが遅く申し訳ありません。また進捗がありましたら書き込みます。

    この内容で良いように思うのですが、完全な修正方法であるかどうかが検証しきれておりません。

    以上です

  • YIさん

    シェルティです、こんにちは。

    開発チームにお願いして、YIさんの課題(Suspend/Resumeを使うとフリーズ)と対策(Notify系を使うとフリーズしない)について、課題が再現することと、対策が有効そうであることを確認しました。課題があるとき20分程でフリーズしていたところ、対策すると20時間ほど連続稼働で問題なしでした。

    ただし、上述の通り完全な修正かどうかは検証出来ていないので、お手数ですがYIさんの環境においても十分に評価いただいて問題が発生しないか確認いただければと思います。

    T4はITRON TCP/IP APIで設計しており、組み合わせて使用するRTOSもITRON系を想定していました。FreeRTOSとの組み合わせができるようにしたのは最近でして実績が少なく本件のような動作不良があったように思います。

    もしRTOSとTCP/IPの組み合わせについて強い制約がなければ以下組み合わせが推奨です。

    ①TCP/IPがT4である必要がない:FreeRTOS と FreeRTOS+TCP

    ②RTOSがFreeRTOSである必要がない:RI600V4等のITRON系のRTOSとT4

    ③RTOS自体が不要:T4のみ

    以上です

  • シェルティ様

    YIです。こんにちは。

    こちらの環境でも連続稼働1週間程度ですが問題なく動作しました。

    ありがとうございました。