Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみた

こんにちは。NoMaYです。

別スレッドで、AWSドキュメントサイト内にFreeRTOS kernelの開発者ガイドの日本語版が載っていることに気付いたのですが、その中に含まれているCコード例をルネサスRXシミュレータで試せたら面白そうだと思い、やってみました。まずはCC-RX(CS+/e2 studio)版です。後日GNURX(e2 studio)版もやろうと思います。以下、プロジェクトのファイル一式です。(CS+ V8.01+CC-RX V2.03でビルド)(e2 studio用.project/.cproject等を同梱(zipファイルをe2 studioに直接インポート可能))

sim_rx65n_freertos_ccrx_c_csplus_20190526.zip

やったこと(主なもの)

(1) FreeRTOS kernelがルネサスRXシミュレータの未対応機能を使っていたので無理矢理に対応機能のみ使うように小細工
(2) Full DemoからルネサスRXシミュレータの未対応機能を使っている項目を除外
(3) ルネサスRXシミュレータではBSPモジュール内で無限ループしてしまう点を回避
(4) 開発者ガイドのCコード例で使われているvPrintString()をDebug Consoleへ出力するように作成
(5) Full Demo/Simple Blinky Demo/Cコード例でvAssertCalled()呼び出し時にDebug Consoleへメッセージを出力
(6) Full Demo/Simple Blinky DemoでLEDのOn/OffのタイミングでDebug ConsoleへOn/Offのメッセージを出力
(7) 開発者ガイドのCコード例が動くようにルネサスRXシミュレータの起動設定を変更(私の個人的な好みを含む)
(8) 開発者ガイドのCコード例をビルドする時には不要なデモソースをビルドから除外したプロジェクトを作成(CS+のみ)
(9) 開発者ガイドのCコード例をビルドするプロジェクトではコンパイル時の最適化レベルを0に変更(CS+のみ)

以下、FreeRTOS kernelの開発者ガイドのCコード例をルネサスRXシミュレータで動かした時の画面コピーです。(上記の(8)のプロジェクトです。)

FreeRTOS kernelの開発者ガイドではFreeRTOS Windowsシミュレータで実行
docs.aws.amazon.com/ja_jp/freertos-kernel/latest/dg/task-management.html


ルネサスRXシミュレータで実行


ビルドした時のビルド設定とビルド結果


zipファイルには、開発者ガイドのCコード例をビルドするプロジェクト(CS+のみ)の他に、別スレッドに投稿した、RX65N TBボードで動く(といってもデバッグ中ではありますが)Full Demo/Simple Blinky Demoをビルドするプロジェクトも含まれています。(上記の(2)で除外している項目はありますが。) 以下、それらの画面コピーです。

CS+


e2 studio

Parents
  • こんにちは。NoMaYです。

    先日の、DMAでUART受信しながらタイムアウトエラーやフレーミングエラー/パリティエラー/オーバーランエラーを検出するようにしてみたプログラムですが、ボーレートを4Mbps→2Mbpsにすると(それに合わせてsim_rl78_serial_data_ok.ser, sim_rl78_serial_data_err_timeout.ser, sim_rl78_serial_data_err_uart_format.serの通信設定も4Mbps→2Mbps, 4Mbps→2Mbps, 2Mbps→1Mbpsにすると)、以下の通りの変な挙動をすることに気付きました。以下、変な挙動をするプロジェクトのファイル一式です。

    sim_rl78_freertos_ccrl_c_csplus_NG_20190628.zip    631KB
    sim_rl78_freertos_gnurl78_c_e2v740_NG_20190628.zip   591KB

    調べてみたところ、実は受信エラー割り込みは複数回発生していて、ボーレートを下げると、最後の受信エラーが以下のようにタスクのブロックが解除された後に発生してしまうことが分かりました。

    タスク側 割り込みルーチン側
    xSemaphoreTake()の実行でブロック解除待ちに入る  
      受信エラー発生でxSemaphoreGiveFromISR()を実行
      受信エラー発生でxSemaphoreGiveFromISR()を実行
      受信エラー発生でxSemaphoreGiveFromISR()を実行
    xSemaphoreTake()の実行でのブロックが解除される  
      受信エラー発生でxSemaphoreGiveFromISR()を実行

    そして、その結果、次にタスクがブロック解除待ちに入ろうとした時、待つことなくすぐにブロック解除されて、以下の通りの変な挙動をすることが分かりました。

    以下、変な挙動の画面コピーです。(CS+での画面コピーですが、e2 studioでも同様です。)

    手順1: シリアルウィンドウでsim_rl78_serial_data_err_timeout.serを読み込む
    手順2: 入出力パネルウィンドウで[Start Receiving]ボタンを押す
    手順3: シリアルウィンドウで[自動送信]ボタンを押す
    手順4: 入出力パネルウィンドウの[ERROR]のLEDが点灯してエラー種別が表示される
    手順5: シリアルウィンドウでsim_rl78_serial_data_err_timeout.serを読み込む
    手順6: 入出力パネルウィンドウで[Start Receiving]ボタンを押す
    ⇒⇒⇒: すぐに[OK]のLEDが点灯してしまう(しかも[自動送信]ボタンを押していない)
       : 期待値は、[自動送信]ボタンを押した後に[ERROR]のLEDが点灯してエラー種別が表示される、こと





    受信エラー割り込みが複数回発生しないようにするやり方も後で投稿しようと思いますが、ひとまず以下のようにダミーのブロック解除待ちを入れることでも対処することが出来ました。(赤文字箇所)

    src/user_main.c

    void uart_recv_dmac_demo_task(void *pvParameters)
    {
        volatile uint8_t recv_buff[UART_RECV_DEMO_SIZE + 1];
        volatile uint8_t err_type;
        BaseType_t ret;

        (void) pvParameters;
        taskENTER_CRITICAL();
        LED_B = LED_ON;
        taskEXIT_CRITICAL();

        R_INTC3_Start();
        U_UART0_DMAC0_Start();

        for (;;)
        {
            /* --- Waiting for a click of button on the Simulator GUI --- */
            xSemaphoreTake( xSemaphoreINTP3, portMAX_DELAY );

            taskENTER_CRITICAL();
            LED_B = LED_OFF;
            LED_R = LED_OFF;
            LAB_CLEAR();
            taskEXIT_CRITICAL();
            memset( (char *)recv_buff, 0, UART_RECV_DEMO_SIZE + 1 );

            /* --- Ensure a new give operation will be valid --- */
            xSemaphoreTake( xSemaphoreINTDMA0_INTSRE0, 0 );

            U_UART0_DMAC0_Receive( recv_buff, UART_RECV_DEMO_SIZE, &err_type );
            R_DMAC0_Start();

            /* --- Waiting for a transmission of serial data on the Simulator GUI --- */
            ret = xSemaphoreTake( xSemaphoreINTDMA0_INTSRE0, pdMS_TO_TICKS(100) );
            if (pdPASS == ret && 0 == err_type)
            {
                taskENTER_CRITICAL();
                LED_B = LED_ON;
                vPrintString( "Received Message: " );
                vPrintString( (char *)recv_buff );
                vPrintString( "\n" );
                taskEXIT_CRITICAL();
            }
            else
            {
                R_DMAC0_Stop();
                taskENTER_CRITICAL();
                LED_R = LED_ON;
                if (pdFAIL == ret)
                {
                    LAB_TIMEOUT_ERROR = LAB_SHOW;
                    vPrintString( "Timeout Error\n" );
                }
                else
                {
                    if (0x04 & err_type)
                    {
                        LAB_FRAMING_ERROR = LAB_SHOW;
                        vPrintString( "Framing Error\n" );
                    }
                    if (0x02 & err_type)
                    {
                        LAB_PARITY_ERROR = LAB_SHOW;
                        vPrintString( "Parity Error\n" );
                    }
                    if (0x01 & err_type)
                    {
                        LAB_OVERRUN_ERROR = LAB_SHOW;
                        vPrintString( "Overrun Error\n" );
                    }
                }
                taskEXIT_CRITICAL();
            }
        }
    }

     

Reply
  • こんにちは。NoMaYです。

    先日の、DMAでUART受信しながらタイムアウトエラーやフレーミングエラー/パリティエラー/オーバーランエラーを検出するようにしてみたプログラムですが、ボーレートを4Mbps→2Mbpsにすると(それに合わせてsim_rl78_serial_data_ok.ser, sim_rl78_serial_data_err_timeout.ser, sim_rl78_serial_data_err_uart_format.serの通信設定も4Mbps→2Mbps, 4Mbps→2Mbps, 2Mbps→1Mbpsにすると)、以下の通りの変な挙動をすることに気付きました。以下、変な挙動をするプロジェクトのファイル一式です。

    sim_rl78_freertos_ccrl_c_csplus_NG_20190628.zip    631KB
    sim_rl78_freertos_gnurl78_c_e2v740_NG_20190628.zip   591KB

    調べてみたところ、実は受信エラー割り込みは複数回発生していて、ボーレートを下げると、最後の受信エラーが以下のようにタスクのブロックが解除された後に発生してしまうことが分かりました。

    タスク側 割り込みルーチン側
    xSemaphoreTake()の実行でブロック解除待ちに入る  
      受信エラー発生でxSemaphoreGiveFromISR()を実行
      受信エラー発生でxSemaphoreGiveFromISR()を実行
      受信エラー発生でxSemaphoreGiveFromISR()を実行
    xSemaphoreTake()の実行でのブロックが解除される  
      受信エラー発生でxSemaphoreGiveFromISR()を実行

    そして、その結果、次にタスクがブロック解除待ちに入ろうとした時、待つことなくすぐにブロック解除されて、以下の通りの変な挙動をすることが分かりました。

    以下、変な挙動の画面コピーです。(CS+での画面コピーですが、e2 studioでも同様です。)

    手順1: シリアルウィンドウでsim_rl78_serial_data_err_timeout.serを読み込む
    手順2: 入出力パネルウィンドウで[Start Receiving]ボタンを押す
    手順3: シリアルウィンドウで[自動送信]ボタンを押す
    手順4: 入出力パネルウィンドウの[ERROR]のLEDが点灯してエラー種別が表示される
    手順5: シリアルウィンドウでsim_rl78_serial_data_err_timeout.serを読み込む
    手順6: 入出力パネルウィンドウで[Start Receiving]ボタンを押す
    ⇒⇒⇒: すぐに[OK]のLEDが点灯してしまう(しかも[自動送信]ボタンを押していない)
       : 期待値は、[自動送信]ボタンを押した後に[ERROR]のLEDが点灯してエラー種別が表示される、こと





    受信エラー割り込みが複数回発生しないようにするやり方も後で投稿しようと思いますが、ひとまず以下のようにダミーのブロック解除待ちを入れることでも対処することが出来ました。(赤文字箇所)

    src/user_main.c

    void uart_recv_dmac_demo_task(void *pvParameters)
    {
        volatile uint8_t recv_buff[UART_RECV_DEMO_SIZE + 1];
        volatile uint8_t err_type;
        BaseType_t ret;

        (void) pvParameters;
        taskENTER_CRITICAL();
        LED_B = LED_ON;
        taskEXIT_CRITICAL();

        R_INTC3_Start();
        U_UART0_DMAC0_Start();

        for (;;)
        {
            /* --- Waiting for a click of button on the Simulator GUI --- */
            xSemaphoreTake( xSemaphoreINTP3, portMAX_DELAY );

            taskENTER_CRITICAL();
            LED_B = LED_OFF;
            LED_R = LED_OFF;
            LAB_CLEAR();
            taskEXIT_CRITICAL();
            memset( (char *)recv_buff, 0, UART_RECV_DEMO_SIZE + 1 );

            /* --- Ensure a new give operation will be valid --- */
            xSemaphoreTake( xSemaphoreINTDMA0_INTSRE0, 0 );

            U_UART0_DMAC0_Receive( recv_buff, UART_RECV_DEMO_SIZE, &err_type );
            R_DMAC0_Start();

            /* --- Waiting for a transmission of serial data on the Simulator GUI --- */
            ret = xSemaphoreTake( xSemaphoreINTDMA0_INTSRE0, pdMS_TO_TICKS(100) );
            if (pdPASS == ret && 0 == err_type)
            {
                taskENTER_CRITICAL();
                LED_B = LED_ON;
                vPrintString( "Received Message: " );
                vPrintString( (char *)recv_buff );
                vPrintString( "\n" );
                taskEXIT_CRITICAL();
            }
            else
            {
                R_DMAC0_Stop();
                taskENTER_CRITICAL();
                LED_R = LED_ON;
                if (pdFAIL == ret)
                {
                    LAB_TIMEOUT_ERROR = LAB_SHOW;
                    vPrintString( "Timeout Error\n" );
                }
                else
                {
                    if (0x04 & err_type)
                    {
                        LAB_FRAMING_ERROR = LAB_SHOW;
                        vPrintString( "Framing Error\n" );
                    }
                    if (0x02 & err_type)
                    {
                        LAB_PARITY_ERROR = LAB_SHOW;
                        vPrintString( "Parity Error\n" );
                    }
                    if (0x01 & err_type)
                    {
                        LAB_OVERRUN_ERROR = LAB_SHOW;
                        vPrintString( "Overrun Error\n" );
                    }
                }
                taskEXIT_CRITICAL();
            }
        }
    }

     

Children
No Data