RL78 FreeRTOS APIを特別なおまじない記述無しで割り込みルーチンから呼び出せるようにしてみた(CC-RL/GNURL78)

こんにちは。NoMaYです。

別スレッド『Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみた』で気付いたことですが、FreeRTOSでは、ポートレイヤーの実装に内蔵周辺のソフトウェア割り込み機能(これはCPUのソフトウェア割り込み命令のことでは無いです)を使用することで、素朴に簡単に割り込みルーチンからFreeRTOS APIを呼び出せるようになることに気付きました。そこで、FreeRTOS v10.2.1 RL78ポートレイヤーをそのように改変してみました。

以下、プロジェクトのファイル一式です。(CC-RL版はCS+ V8.01/e2 stuiod v7.40+CC-RL V1.02でビルド(e2 studio用.project/.cproject等を同梱))(GNURL78版はe2 studio v7.40+GNURL78 2019q2(4.9.2.201902)でビルド)(共にzipファイルをe2 studioに直接インポート可能) プロジェクト構造は極力RX版と同じにしてあります。([追記] すみません。以下に含まれるMAPファイルが別のものでした。タスク側のクリティカルセクションが以前のままのものでした。この投稿の末尾に追加したMOTファイルのzipファイルには訂正版を入れてあります。)

sim_rl78_freertos_full_demo_ccrl_c_csplus_20190705.zip    628KB
sim_rl78_freertos_full_demo_gnurl78_c_e2v740_20190705.zip    582KB

そのスレッドに投稿していたRL78ポートレイヤー(これもFreeRTOS v10.2.1 RL78ポートレイヤーを改変したものです)では、割り込みルーチンからFreeRTOS APIを呼び出すには以下のような特別なおまじないを記述する必要がありました。(以下はCC-RLの場合のものですがGNURL78でも同様です。)

#pragma interrupt r_intc3_interrupt(vect=INTP3)
/* Start user code for pragma. Do not edit comment generated here */
R_PRAGMA_FREERTOS_INTERRUPT(r_intc3_interrupt)
#define r_intc3_interrupt _r_intc3_interrupt
/* End user code. Do not edit comment generated here */

そのスレッドにはRXポートレイヤーの改変についても投稿していたのですが、その時、最初に書いたことに気付きました。RL78の内蔵周辺には専用のソフトウェア割り込み機能はありませんが、以下のハードウェアマニュアルに記載されている通り、プログラムで割り込み要求フラグをセットすると割り込みを発生させることが出来ますので、実質的に任意の空き割り込みをソフトウェア割り込み機能として使うことが出来ます。(今回は、とりあえず、ウォッチドッグタイマのオーバフロー時間の75%到達のインターバル割り込みを使用してみました。)

RL78/G13 ユーザーズマニュアル ハードウェア編からの抜粋
www.renesas.com/ja-jp/doc/products/mpumcu/doc/rl78/r01uh0146jj0340_rl78g13.pdf



なお、今回のRL78ポートレイヤーの改変で、先ほどの特別なおまじないを記述する必要は無くなりますが、割り込みルーチンからFreeRTOS APIを呼び出してブロック解除待ちタスクをブロック解除する場合のタスク切り替えの遅延時間が以下のRenesas RL78 SimulatorのSimulator GUIの画面コピーのように数十クロックほど(32MHz動作では600nsほど)延びます。(以下はCC-RLの場合のものですがGNURL78でも同様(ただし数百nsほど長い)です。) ちなみに、タスク側のクリティカルセクション(その区間では割り込み禁止となる)への出入りによるタイミングへの影響を避ける為、今回はクリティカルセクションとして扱うことしていませんので、以下の画面コピーでは別スレッドの画面コピーよりもポート出力トグルの速さが速くなっています。

今回の改変前:


今回の改変後:


以下、今回のRL78ポートレイヤの改変内容です。コメントの訂正や不要になったルーチンの削除は省略しています。(以下はCC-RLの場合のものですがGNURL78でも同様です。)

src/FreeRTOS/Source/portable/Renesas/RL78/portmacro.h
今回の改変前:

/* Task utilities. */
#define portYIELD() __brk()
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
#define portNOP()   __nop()

今回の改変後: 赤文字行を追加/変更

#include "iodefine.h"
/* Task utilities. */
#define portYIELD() do{ WDTIIF = 1; } while (0)
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken )  if( xHigherPriorityTaskWoken ) portYIELD()
#define portNOP()   __nop()

src/FreeRTOS/Source/portable/Renesas/RL78/port.c
今回の改変後: 赤文字行を追加

BaseType_t xPortStartScheduler( void )
{
    /* Setup the hardware to generate the tick.  Interrupts are disabled when
    this function is called. */
    configSETUP_TICK_INTERRUPT();

    /* Setup the hardware to generate the yield interrupt. */
    WDTIPR1 = 1;
    WDTIPR0 = 1;
    WDTIMK = 0;

    /* Restore the context of the first task that is going to run. */
    vPortStartFirstTask();

    /* Execution should not reach here as the tasks are now running! */
    return pdTRUE;
}

src/FreeRTOS/Source/portable/Renesas/RL78/portasm.asm
今回の改変前:

_vPortYield:
    portSAVE_CONTEXT                ; Save the context of the current task.
    call@      _vTaskSwitchContext  ; Call the scheduler to select the next task.
    portRESTORE_CONTEXT             ; Restore the context of the next task to run.
    retb
    _vPortYield      .VECTOR    0x7E

今回の改変後: 赤文字行を変更

_vPortYield:
    portSAVE_CONTEXT                ; Save the context of the current task.
    call@      _vTaskSwitchContext  ; Call the scheduler to select the next task.
    portRESTORE_CONTEXT             ; Restore the context of the next task to run.
    reti
    _vPortYield      .VECTOR    0x04

以下、今回のタスク側のプログラムです。先ほど書いた通り、今回は各タスクのポート出力をトグルさせる部分をクリティカルセクションとして扱うことしていません。(なお、src/frtos_config/FreeRTOSConfig.hの#define FREERTOS_USER_MAIN 0の行で0→1の変更を行うことで以下が実行されるようになります。)

src/user_main.c

void main_task(void *pvParameters)
{
    (void) pvParameters;

    while (1)
    {
        P1_bit.no6 = !P1_bit.no6;
    }
}

void second_task(void *pvParameters)
{
    (void) pvParameters;

    while (1)
    {
        P1_bit.no5 = !P1_bit.no5;
    }
}

void third_task(void *pvParameters)
{
    (void) pvParameters;

    while (1)
    {
        P1_bit.no4 = !P1_bit.no4;
    }
}

void intp3_task(void *pvParameters)
{
    (void) pvParameters;

    R_INTC3_Start();

    LED_INIT();
    while (1)
    {
        xSemaphoreTake( xSemaphoreINTP3, portMAX_DELAY );
        LED_BIT = !LED_BIT;
    }
}


[追記]

MOTファイル

sim_rl78_freertos_full_demo_ccrl_c_csplus_20190705_mot.zip    2019/07/12追加
sim_rl78_freertos_full_demo_gnurl78_c_e2v740_20190705_mot.zip    2019/07/24追加

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

    これまで投稿してきたSample Programでは、コンパイラの最適化オプションで未使用の変数/関数を削除する最適化を実施してデータサイズ/コードサイズを削減していたのですが、今回、FreeRTOSConfig.hを以下のファイル比較ツールの画面コピーの通りに変更してみたところ、更に削減することが出来ました。

    例えば、sampleprog2(UART送受信を割り込みのみで行う版)では、CC-RLで表示されるPROGRAM SECTIONのサイズが8247(2037H)→4274(10b2H)へ、GNURL78で表示されるtextセクションのサイズが11240→5898へ、となりました。(ちなみに、CC-RLとGNURL78では集計の発想が異なる為、双方を直接は比較出来ません。)

      CC-RL V1.02 GNURL78 2019q4(4.9.2.201904)  
      PROGRAM
    (Bytes)
    ROMDATA
    (Bytes)
    RAMDATA
    (Bytes)
    text
    (Bytes)
    data
    (Bytes)
    bss
    (Bytes)
     
     
      今まで 今回 今まで 今回 今まで 今回 今まで 今回 今まで 今回 今まで 今回  
    sampleprog1 8475 4502 725 665 9246 9198 11578 6236 188 188 9198 9150  
    sampleprog2 8247 4274 697 637 9197 9149 11240 5898 132 132 9196 9148  
    sampleprog3 8658 4685 713 653 9198 9170 11730 6386 132 132 9218 9170  

    sampleprog1: UART送受信をDTCで行う版
    sampleprog2: UART送受信を割り込みのみで行う版
    sampleprog3: UART受信をリングバッファで行いUART送信を割り込みのみで行う版

    なお、今回試したFreeRTOSConfig.hとビルドした結果のmapファイル等を以下のzipファイルに固めました。

    rl78g14fpb_freertos_sampleprogs_issue_20200413.zip

    以下、画面コピーです。

    zipファイル内のファイル一覧


    FreeRTOSConfig.hの変更内容: 今まで(左側ペイン)と今回(右側ペイン)


    サイズ比較結果例: sampleprog2: CC-RL: 今まで(左側ペイン)と今回(右側ペイン)


    サイズ比較結果例: sampleprog2: GNURL78: 今まで(左側ペイン)と今回(右側ペイン)


     

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

    これまで投稿してきたSample Programでは、コンパイラの最適化オプションで未使用の変数/関数を削除する最適化を実施してデータサイズ/コードサイズを削減していたのですが、今回、FreeRTOSConfig.hを以下のファイル比較ツールの画面コピーの通りに変更してみたところ、更に削減することが出来ました。

    例えば、sampleprog2(UART送受信を割り込みのみで行う版)では、CC-RLで表示されるPROGRAM SECTIONのサイズが8247(2037H)→4274(10b2H)へ、GNURL78で表示されるtextセクションのサイズが11240→5898へ、となりました。(ちなみに、CC-RLとGNURL78では集計の発想が異なる為、双方を直接は比較出来ません。)

      CC-RL V1.02 GNURL78 2019q4(4.9.2.201904)  
      PROGRAM
    (Bytes)
    ROMDATA
    (Bytes)
    RAMDATA
    (Bytes)
    text
    (Bytes)
    data
    (Bytes)
    bss
    (Bytes)
     
     
      今まで 今回 今まで 今回 今まで 今回 今まで 今回 今まで 今回 今まで 今回  
    sampleprog1 8475 4502 725 665 9246 9198 11578 6236 188 188 9198 9150  
    sampleprog2 8247 4274 697 637 9197 9149 11240 5898 132 132 9196 9148  
    sampleprog3 8658 4685 713 653 9198 9170 11730 6386 132 132 9218 9170  

    sampleprog1: UART送受信をDTCで行う版
    sampleprog2: UART送受信を割り込みのみで行う版
    sampleprog3: UART受信をリングバッファで行いUART送信を割り込みのみで行う版

    なお、今回試したFreeRTOSConfig.hとビルドした結果のmapファイル等を以下のzipファイルに固めました。

    rl78g14fpb_freertos_sampleprogs_issue_20200413.zip

    以下、画面コピーです。

    zipファイル内のファイル一覧


    FreeRTOSConfig.hの変更内容: 今まで(左側ペイン)と今回(右側ペイン)


    サイズ比較結果例: sampleprog2: CC-RL: 今まで(左側ペイン)と今回(右側ペイン)


    サイズ比較結果例: sampleprog2: GNURL78: 今まで(左側ペイン)と今回(右側ペイン)


     

Children
No Data