Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page

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-RX 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追加

  • こんにちは。NoMaYです。

    実機(秋月電子さんのRL78基板+LED)で試してみましたが、CC-RL版のFullDemoで3日連続運転することが出来ました。(1年以上前に試していたものは、今も1日連続運転出来ませんでした。)

  • こんにちは。NoMaYです。

    GNURL78版のFullDemoも実機(秋月電子さんのRL78基板+LED)で試してみると、3日連続運転することが出来ました。これで、1年以上前に試していた時より状況は良くなっているなぁ、というところですが、今のところ好転した契機として思い浮かぶのは、以下の項目のどれかかなぁ、といったところです。

    (1) FreeRTOSのバージョン(デモのソースを含む)をv10.0.1→10.2.1へ上げた
    (2) FreeRTOSConfig.hの変更(特に16bit tick→32bit tickとしたことが気になります)
    (3) ポートレイヤでのレジスタのPUSH/POPの順番を変えた(これは関係ないと思いますが)
    (4) Yieldの実装方法をBRK命令を使うやり方からソフトウェア割り込み機能もどきを使うやり方へ変えた

    どれが原因かは調べてみたい気持ちはありますが、最近、CA78K0Rを使用しているスレッドにリプライすることが何度かありましたので、CA78K0Rにも移植してみたい気持ちもあります、、、

  • こんにちは。NoMaYです。

    ルネサスさんからRL78/G14 Fast Prototyping Boardという安い評価ボードが出たのですが、私も購入してみたので、これに自作の以下のRX-TBのFreeRTOS Sample Programを移植してみようかと思います。LEDの数とSWの数がRX-TBと同じなので、、、(RL78にはFITがありませんのでCGで、、、)

    CSplusでFreeRTOSプロジェクトもどきSample Programを作ってRenesas RX Simulator/TB-RX65Nで試せるようにしてみた
    japan.renesasrulz.com/cafe_rene/f/forum21/5980/csplus-freertos-sample-program-renesas-rx-simulator-tb-rx65n
    e2 studio+GNURXでFreeRTOSプロジェクトもどきSample Programを作ってRenesas RX Simulator/TB-RX65Nで試せるようにしてみた
    japan.renesasrulz.com/cafe_rene/f/forum21/6012/e2-studio-gnurx-freertos-sample-program-renesas-rx-simulator-tb-rx65n


    (1) TBボードのLED0を500ms毎にOn/Offする(FreeRTOS APIのvTaskDelay()を使用)
    (2) TBボードのSW1押下毎にLED1をOn/Offする(タスクでセマフォ待ちして割り込みでセマフォ待ち解除)
    (3) TBボードのSCI1で3文字受信毎に3文字エコーバックする(タスクでセマフォ待ちして割り込みで3文字毎にセマフォ待ち解除)


    [関連スレッド]

    RL78の安い評価ボードが発売されています。
    japan.renesasrulz.com/cafe_rene/f/forum18/6086/rl78
     

  • こんにちは。NoMaYです。#3連投の1つ目です。

    自作のRX-TBのFreeRTOS Sample Programを移植しようとしているのですが、ちょっと欲張って、チョコさんのリングバッファを使ってみようとか、(DMAが無いのだから)DTCを使ってみようとか、しているうちに年末になってしまいました。(コーディングまではしたものの、デバッグはこれからです。) もう暫く掛かってしまいそうですので、ひとまず、このスレッドの最初の投稿でやっていた、Renesas RL78 Simulatorで動作させていたRL78 FreeRTOS Full DemoプログラムとAmazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをG13→G14へ変更(+α)しましたので、まず、それを投稿します。

    以下、プロジェクトのファイル一式です。(CC-RL版はCS+ V8.02/e2 stuiod v7.6.0+CC-RX V1.02でビルド(e2 studio用.project/.cproject等を同梱)(当方特有の事情でCC-RX V1.02を使用))(GNURL78版はe2 studio v7.6.0+GNURL78 2019q4(4.9.2.201904)でビルド)(共にzipファイルをe2 studioに直接インポート可能) プロジェクト構造は極力RX-TBの自作のFreeRTOSプロジェクトもどきSample Programに似せてあります。

    rl78g14fpb_freertos_full_demo_ccrl_c_csplus_20191225.zip (*1,*2)    668KB
    rl78g14fpb_freertos_full_demo_gnurl78_c_e2v760_20191225.zip (*1,*2,*3)   591KB

    *1:LED(やSW)のポートはRL78/G14 Fast Prototyping Boardと同じにしてありますので、FreeRTOS Full Demoの方は実機でもLED点滅の確認が出来ます。(ですが、FreeRTOS Kernel Developer Guideのサンプルコードの方は実機対応のvPrintString()出力ルーチンを作っていませんので、実機では確認が出来ないです。))

    *2:実機用のデバッガプロパティ設定(CS+)や.launchファイル設定(e2 studio)は当方特有の事情でオンボードエミュレータが使えない為に未確認です。(ひと通りは設定してあります。)

    *3:リンカスクリプトには別スレッド「GNURL78でconst領域/Mirror領域をちょっと安全に使えるようにlinker scriptのASSERT()で小技(TIPS)を考えてみた」に投稿した内容を反映してあります。

    今回、FreeRTOS Full DemoのLEDやSWのポートのアサインは以下のようになっています。(赤文字箇所を追加しました。) なお、src/FreeRTOSフォルダ以下は、この箇所を除いて、このスレッドのこれまでのソースと同じです。

    src/FreeRTOS/Demo/demo_specific_io.h

    /*
     * FreeRTOS Kernel V10.2.1
     * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
     *
     。。。省略。。。
     *
     * 1 tab == 4 spaces!
     */

    #ifndef LED_IO_H
    #define LED_IO_H

    /* Include the register definition file that is correct for the hardware being
    used.  The C and assembler pre-processor must have one of the following board
    definitions defined to have the correct register definition header file
    included.  Alternatively, just manually include the correct files here. */

        /* Prevent the files being included from the FreeRTOS port layer assembly
        source files. */
        #ifndef __ASSEMBLER__

            #if defined(__CCRL__) || defined(__GNUC__)
                #include "iodefine.h"
                #if defined(__GNUC__)
                    #include "iodefine_ext.h"
                #endif /* defined(__GNUC__) */
            #endif /* defined(__CCRL__) || defined(__GNUC__) */

            #ifdef AE_R5F100LGAFB
                #if defined(__IAR_SYSTEMS_ICC__) && !defined(__CCRL__) && !defined(__CNV_IAR__)
                    #include "ior5f100lg.h"
                    #include "ior5f100lg_ext.h"
                #endif /* defined(__IAR_SYSTEMS_ICC__) && !defined(__CCRL__) && !defined(__CNV_IAR__) */
                /* P5.0 is compatible with LED_BUILTIN of GR-KURUMI and GR-COTTON */
                #define LED_BIT         ( P5_bit.no0 )
                #define LED_INIT()      do{ P5 &= 0xFE; PM5 &= 0xFE; }while (0)
            #endif /* AE_R5F100LGAFB */

            #ifdef RL78G14FPB
                #if defined(__IAR_SYSTEMS_ICC__) && !defined(__CCRL__) && !defined(__CNV_IAR__)
                    #include "ior5f104ml.h"
                    #include "ior5f104ml_ext.h"
                #endif /* defined(__IAR_SYSTEMS_ICC__) && !defined(__CCRL__) && !defined(__CNV_IAR__) */
                #define LED_BIT         ( P4_bit.no3 )
                #define LED_INIT()      do{ P4 &= 0xF7; PM4 &= 0xF7; P4 |= 0x10; PM4 &= 0xEF; }while (0)
            #endif /* RL78G14FPB */

            #ifdef YRPBRL78G13
                #if defined(__IAR_SYSTEMS_ICC__) && !defined(__CCRL__) && !defined(__CNV_IAR__)
                    #include "ior5f100le.h"
                    #include "ior5f100le_ext.h"
                #endif /* defined(__IAR_SYSTEMS_ICC__) && !defined(__CCRL__) && !defined(__CNV_IAR__) */
                #define LED_BIT         ( P7_bit.no7 )
                #define LED_INIT()      P7 &= 0x7F; PM7 &= 0x7F
            #endif /* YRPBRL78G13 */

            。。。省略。。。

            #ifndef LED_BIT
                #error The hardware platform is not defined
            #endif

        #endif /* INCLUDED_FROM_FREERTOS_ASM_FILE */

    #endif /* LED_IO_H */

    また、今回、RXマイコンのFITのBSPモジュールにあるplatform.hというファイル名を借用して、それっぽいような以下のヘッダファイルを作ってみました。

    src/platform.h

    #ifndef PLATFORM_H
    #define PLATFORM_H

    #ifdef __cplusplus
    extern "C" {
    #endif

    #include "r_cg_macrodriver.h"
    #include "r_cg_userdefine.h"
    #if defined(__CCRL__) && !defined(_STDINT_H)
    #define _STDINT_H
    #endif
    #include "FreeRTOS.h"
    #include "task.h"
    #include "semphr.h"
    #include "queue.h"
    #include "croutine.h"
    #include "timers.h"
    #include "event_groups.h"

    #if defined(__CCRL__) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L))
    #define bool    _Bool
    #define true    1
    #define false   0
    #define __bool_true_false_are_defined   1
    #else
    #include <stdbool.h>
    #endif
    #include <stdio.h>
    #include <stddef.h>
    #include <string.h>

    #if defined(__GNUC__)
    #define BRK()     asm("brk")
    #endif

    #define di()      DI()
    #define ei()      EI()
    #define halt()    HALT()
    #define nop()     NOP()
    #define stop()    STOP()
    #define brk()     BRK()

    #define INTERNAL_NOT_USED(p)        ((void)(p))

    #if defined(__CCRL__)

    #define R_CG_DEFAULT_ISR_UNUSED(name)\
        static void __near name##_UNUSED(void);\
        void _##name##_UNUSED(void){name##_UNUSED();}

    #define R_CG_REDEFINE_ISR(name)\
        static void __near name(void);

    #elif defined(__GNUC__)

    #define R_CG_DEFAULT_ISR_UNUSED(name)\
        void name##_UNUSED(void) __attribute__ ((unused));

    #define R_CG_REDEFINE_ISR(name)\
        void name(void) __attribute__ ((interrupt));

    #endif

    #if defined(RENESAS_SIMULATOR_DEBUGGING)
    #include "RenesasSimDebug/sim_debug_mode_hook.h"
    #endif

    #ifdef __cplusplus
    }
    #endif

    #endif /* PLATFORM_H */

    なお、このヘッダファイルをコード生成機能で自動生成されるソースでいちいち#includeするのが面倒に思われましたので、以下のようにr_cg_userdefine.hのユーザ記述部で#includeするようにしてみました。(ですが、この投稿を書いていて、platform.hとr_cg_userdefine.hでインクルードが循環していることに気付きました。インクルードガードにより問題は起きないですが、、、)

    src/r_cg_userdefine.h

    #ifndef _USER_DEF_H
    #define _USER_DEF_H

    /******************************************************************************
    User definitions
    ******************************************************************************/

    /* Start user code for function. Do not edit comment generated here */
    #include "platform.h"
    /* End user code. Do not edit comment generated here */
    #endif

    この後、2投目、3投目は以下の通りです。

    2投目 (ひたすら画面コピーです)

    ・プロジェクト構造
     極力RX-TBの自作のFreeRTOSプロジェクトもどきSample Programに似せてあります。
    ・Renesas RL78 SimulatorでのRL78 FreeRTOS Full Demoの実行例
    ・Renesas RL78 SimulatorでのAmazon AWSのFreeRTOS Kernel Developer Guideのサンプルコードの実行例

    3投目 (ひたすら画面コピーです)

    ・CC-RL/GNURL78の最適化オプション設定(及びGNURL78でのアーキテクチャ設定)
     未使用の変数/関数を削除する等の実行速度を低下させない範囲でのサイズ削減設定をしています。
     (GNURL78では-fltoオプションも指定したかったのですが、e2 studioのスタック解析ビューが表示されなくなってしまった為、今回は指定しませんでした。)
    ・コンパイルオプションにて設定しているマクロ定義

  • こんにちは。NoMaYです。#3連投の2つ目です。

    プロジェクト構造は以下の画面コピーの通りです。極力RX-TBの自作のFreeRTOSプロジェクトもどきSample Programに似せてあります。

    CC-RL+CS+の場合


    CC-RL+e2 studioの場合


    GNURL78+e2 studioの場合


    Renesas RL78 SimulatorでのRL78 FreeRTOS Full Demoの実行例は以下の画面コピーの通りです。

    CC-RL+CS+の場合


    CC-RL+e2 studioの場合


    GNURL78+e2 studioの場合


    Renesas RL78 SimulatorでのAmazon AWSのFreeRTOS Kernel Developer Guideのサンプルコードの実行例は以下の画面コピーの通りです。

    CC-RL+CS+の場合


    CC-RL+e2 studioの場合


    GNURL78+e2 studioの場合

     

  • こんにちは。NoMaYです。#3連投の3つ目です。

    CC-RL/GNURL78の最適化オプション設定(及びGNURL78でのアーキテクチャ設定)は以下の画面コピーの通りです。未使用の変数/関数を削除する等の実行速度を低下させない範囲でのサイズ削減設定をしています。なお、GNURL78では-fltoオプションも指定したかったのですが、e2 studioのスタック解析ビューが表示されなくなってしまった為、今回は指定しませんでした。また、コンパイルオプションにてRL78G14FPBとRENESAS_SIMULATOR_DEBUGGING=1のマクロ定義を設定しています。

    CC-RL+CS+の場合




    CC-RL+e2 studioの場合






    GNURL78+e2 studioの場合




     

  • こんにちは。NoMaYです。#4連投の1つ目です。

    自作の以下のRX-TBのFreeRTOS Sample ProgramをRL78/G14 Fast Prototyping Boardへ移植してみました。実は何パターンか実装するつもりでいて、今回、まず、UART送受信をDTCで行う版を投稿します。(後で、UART受信にチョコさんのリングバッファのソースコードを使用する版とか(デバッグ中)、UART送受信をコード生成機能が生成した割り込み処理のソースコードを素朴に使用する版とか(まだ未着手)、投稿してみようと思っています。)

    CSplusでFreeRTOSプロジェクトもどきSample Programを作ってRenesas RX Simulator/TB-RX65Nで試せるようにしてみた
    https://japan.renesasrulz.com/cafe_rene/f/forum21/5980/csplus-freertos-sample-program-renesas-rx-simulator-tb-rx65n
    e2 studio+GNURXでFreeRTOSプロジェクトもどきSample Programを作ってRenesas RX Simulator/TB-RX65Nで試せるようにしてみた
    japan.renesasrulz.com/cafe_rene/f/forum21/6012/e2-studio-gnurx-freertos-sample-program-renesas-rx-simulator-tb-rx65n

    (1) TBボードのLED0を500ms毎にOn/Offする(FreeRTOS APIのvTaskDelay()を使用)
    (2) TBボードのSW1押下毎にLED1をOn/Offする(タスクでセマフォ待ちして割り込みでセマフォ待ち解除)
    (3) TBボードのSCI1で3文字受信毎に3文字エコーバックする(タスクでセマフォ待ちして割り込みで3文字毎にセマフォ待ち解除)

    RL78/G14 Fast Prototyping BoardではRX65NのSCI1の置き換えとしてRL78/G14のUART3を使用

    また、このスレッドの前に投稿していた以下のスレッドで、RL78/G13ですが、UART受信をDMAで行う際に受信エラーを返せるようにしたFreeRTOSサンプルプログラムを投稿したことがありましたので、今回、それを基に、受信エラー処理として以下の(3')の処理を追加しました。また、その時の投稿と同様に、Renesas RL78 Simulatorで読み込めるシリアル送信データファイル(.serファイル)も同梱しています。(なお、今回、.serファイルを1つ追加しています。)

    Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみた
    japan.renesasrulz.com/cafe_rene/f/forum21/5790/amazon-aws-freertos-kernel-developer-guide-renesas-rx-simulator-debug-console/32271#32271
    これに投稿したRL78/G13のFreeRTOSサンプルプログラムを基に今回追加した動作

    (3') 受信エラーを検出したらLED1を200ms毎にOn/OffさせるようにしてSW1が押下されたら受信エラー状態をクリアする
       検出する受信エラー:パリティエラー、フレーミングエラー、オーバーランエラー、タイムアウト(60秒)


    以下、プロジェクトのファイル一式です。(CC-RL版はCS+ V8.02/e2 stuiod v7.6.0+CC-RX V1.02でビルド(e2 studio用.project/.cproject等を同梱)(当方特有の事情でCC-RX V1.02を使用))(GNURL78版はe2 studio v7.6.0+GNURL78 2019q4(4.9.2.201904)でビルド)(共にzipファイルをe2 studioに直接インポート可能) プロジェクト構造は極力RX-TBの自作のFreeRTOSプロジェクトもどきSample Programに似せてあります。

    rl78g14fpb_freertos_sampleprog1_ccrl_c_csplus_20200106.zip (*1)    406KB
    rl78g14fpb_freertos_sampleprog1_gnurl78_c_e2v760_20200106.zip (*1,*2)   372KB

    *1:実機用のデバッガプロパティ設定(CS+)や.launchファイル設定(e2 studio)は当方特有の事情でオンボードエミュレータが使えない為に未確認です。(ひと通りは設定してあります。)

    *2:リンカスクリプトには別スレッド「GNURL78でconst領域/Mirror領域をちょっと安全に使えるようにlinker scriptのASSERT()で小技(TIPS)を考えてみた」に投稿した内容を反映してあります。

    この後、2投目~4投目は以下の通りです。

    2投目

    ソースコードの記述でちょっと特殊なことをしている点

    (1) コード生成機能が生成した割り込み関数を自前の割り込み関数で置き換える
    (2) コード生成機能が生成した関数で使用すると都合が悪くなる関数を使用不可にする
    (3) Renesas RL78 SimulatorがN-chオープンドレイン出力でLEDを駆動する方法に未対応であることへの対処
    (4) DTC転送時の送信開始処理と送信終了判定処理
    (5) DTC保留命令によりタスク切り替えが起きなくなってしまったことへの対処

    3投目

    ・各タスクのソース

     task_LED0
     task_LED1
     task_CONIO

    ・Renesas RL78 Simulatorでシリアル送信データのファイルを使った実行例の画面コピー

     CC-RL+CS+
      sim_rl78_serial_data_ok_2.ser(今回追加)を使用
      sim_rl78_serial_data_err_uart_format.serを使用

     GNURL78+e2 studio (CC-RL+e2 studioも同様)
      sim_rl78_serial_data_ok_2.ser(今回追加)を使用
      sim_rl78_serial_data_err_uart_format.serを使用

    4投目

    ・コード生成機能の設定の画面コピー

     DTC設定(転送元アドレスと転送先アドレスは単に仮の値)
     シリアル設定
     外部割込み設定(かふぇルネの他の投稿にありましたが単なるSW入力ぐらいでは外部割り込みは使われないようです)
     ポート設定
     ウォッチドッグタイマ設定(単に使用しない設定)
     安全機能設定(単に使用しない設定)
     リセット要因確認設定(単に確認関数を出力しない設定)
     端子割り当て設定
     クロック設定

    ・GNURL78+e2 studio+コード生成機能でDTCを使用する場合のGNURL78のobjcopyコマンドの設定の画面コピー
     (MOTファイルにRAM領域のレコードが直接出力されてしまうことへの対処です)

    以下、実機で実行中の写真と画面コピーです

    RL78/G14 Fast Prototyping Boardの今回のSample Programで使用したUART3のArduioソケット端子の位置
    RxD3 : J7-D0
    TxD3 : J7-D1
    GND : J8-G


    CC-RL+CS+の場合


    GNURL78+e2 studioの場合 (CC-RL+e2 studioの場合も同様です)

     

  • こんにちは。NoMaYです。#4連投の2つ目です。

    今回、ソースコードの記述でちょっと特殊なことをしている点は、以下の通りです。

    (1) コード生成機能が生成した割り込み関数を自前の割り込み関数で置き換える

    CC-RL/GNURL78の最適化オプションで未使用の変数/関数を削除する最適化を実施することを前提にして、以下のマクロを定義して使用してみました。

    src/platform.h

    #if defined(__CCRL__)

    #define R_CG_DEFAULT_ISR_UNUSED(name)\
        static void __near name##_UNUSED(void);\
        void _##name##_UNUSED(void){name##_UNUSED();}

    #define R_CG_REDEFINE_ISR(name)\
        static void __near name(void);

    #elif defined(__GNUC__)

    #define R_CG_DEFAULT_ISR_UNUSED(name)\
        void name##_UNUSED(void) __attribute__ ((unused));

    #define R_CG_REDEFINE_ISR(name)\
        void name(void) __attribute__ ((interrupt));

    #endif

    src/r_cg_serial_user.c

    /* Start user code for global. Do not edit comment generated here */
    ...略...

    R_CG_DEFAULT_ISR_UNUSED(r_uart3_interrupt_receive)
    R_CG_DEFAULT_ISR_UNUSED(r_uart3_interrupt_error)
    R_CG_DEFAULT_ISR_UNUSED(r_uart3_interrupt_send)
    #define r_uart3_interrupt_receive r_uart3_interrupt_receive_UNUSED
    #define r_uart3_interrupt_error r_uart3_interrupt_error_UNUSED
    #define r_uart3_interrupt_send r_uart3_interrupt_send_UNUSED
    /* End user code. Do not edit comment generated here */

    static void __near r_uart3_interrupt_receive(void) ← コード生成機能が生成した割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_error(void) ← コード生成機能が生成した割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_send(void) ← コード生成機能が生成した割り込み関数
    {
    ...略...
    }

    static void r_uart3_callback_receiveend(void)
    {
        /* Start user code. Do not edit comment generated here */
        ...略...
        /* End user code. Do not edit comment generated here */
    }

    static void r_uart3_callback_softwareoverrun(uint16_t rx_data)
    {
        /* Start user code. Do not edit comment generated here */
        ...略...
        /* End user code. Do not edit comment generated here */
    }

    static void r_uart3_callback_sendend(void)
    {
        /* Start user code. Do not edit comment generated here */
        ...略...
        /* End user code. Do not edit comment generated here */
    }

    static void r_uart3_callback_error(uint8_t err_type)
    {
        /* Start user code. Do not edit comment generated here */
        ...略...
        /* End user code. Do not edit comment generated here */
    }

    /* Start user code for adding. Do not edit comment generated here */
    #undef r_uart3_interrupt_receive
    #undef r_uart3_interrupt_error
    #undef r_uart3_interrupt_send
    R_CG_REDEFINE_ISR(r_uart3_interrupt_receive)
    R_CG_REDEFINE_ISR(r_uart3_interrupt_error)
    R_CG_REDEFINE_ISR(r_uart3_interrupt_send)

    static void __near r_uart3_interrupt_receive(void) ← 自前の割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_error(void) ← 自前の割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_send(void) ← 自前の割り込み関数
    {
    ...略...
    }
    /* End user code. Do not edit comment generated here */

    ちなみに、いっそのこと、コード生成機能でコールバック関数を生成しないように設定しておき、以下のように#if 0~#endifで括ってしまう手もあったなぁ、と投稿の下書きを書いていて思いました。

    /* Start user code for global. Do not edit comment generated here */
    ...略...

    #if 0 /* NOT USED */
    /* End user code. Do not edit comment generated here */

    static void __near r_uart3_interrupt_receive(void) ← コード生成機能が生成した割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_error(void) ← コード生成機能が生成した割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_send(void) ← コード生成機能が生成した割り込み関数
    {
    ...略...
    }

    /* Start user code for adding. Do not edit comment generated here */
    #endif /* NOT USED */

    static void __near r_uart3_interrupt_receive(void) ← 自前の割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_error(void) ← 自前の割り込み関数
    {
    ...略...
    }

    static void __near r_uart3_interrupt_send(void) ← 自前の割り込み関数
    {
    ...略...
    }
    /* End user code. Do not edit comment generated here */

    (2) コード生成機能が生成した関数で使用すると都合が悪くなる関数を使用不可にする

    CC-RL/GNURL78の最適化オプションで未使用の変数/関数を削除する最適化を実施することを前提にして、以下の記述をしてみました。(こちらに関してはマクロの定義はしていません。)

    src/r_cg_serial.c

    /* Start user code for global. Do not edit comment generated here */
    ...略...

    #define R_UART3_Receive R_UART3_Receive_DO_NOT_USE
    #define R_UART3_Send R_UART3_Send_DO_NOT_USE
    MD_STATUS R_UART3_Receive(uint8_t * const rx_buf, uint16_t rx_num);
    MD_STATUS R_UART3_Send(uint8_t * const tx_buf, uint16_t tx_num);
    /* End user code. Do not edit comment generated here */

    (3) Renesas RL78 SimulatorがN-chオープンドレイン出力でLEDを駆動する方法に未対応であることへの対処

    LEDを駆動する方法としては一般的な「N-chオープンドレイン出力ポート+LED+抵抗+VDD」ですが、Renesas RL78 Simulatorの入出力パネルでN-chオープンドレイン出力ポートにアクティブロウ設定でLEDを接続しても、残念ながらLEDを点灯させることが出来ませんでした。ただ、以下の画面コピーのようにRenesas RL78 Simulatorの端子設定でN-chオープンドレイン出力ポートをPull Up設定すれば、点灯させることが出来ます。(これは、上記の一般的な接続とは異なるもの、ですが。)



    ちょっと厄介なのは、上記のPull Up設定がRenesas RL78 Simulatorのどの環境設定ファイルにも保存されないので、e2 studioでは毎回手動で設定しなければならないことです。(CS+ではmtpjファイルに記憶されます。) そこで、以下のようにソースコードを記述をして、(CS+の場合であっても)Renesas RL78 Simulatorでデバッグする時(Renesas RL78 Simulatorにダウンロードした時)には、N-chオープンドレイン出力ポートが通常のCMOS出力ポートに設定されるようにしました。

    src/r_cg_port.c

    /* Start user code for global. Do not edit comment generated here */
    #if defined(RENESAS_SIMULATOR_DEBUGGING)
    /* Workaround for a problem that the Renesas RL78 simulator does not work expectedly
     * for a wiring such as "N-ch Open Drain Output Port <--> LED <--> R <--> VDD" */
    void R_PORT_Create1(void);
    void R_PORT_Create2(void);
    void R_PORT_Create(void)
    {
        R_PORT_Create1();
        R_PORT_Create2();
    }
    #define R_PORT_Create R_PORT_Create1
    #endif
    /* End user code. Do not edit comment generated here */

    void R_PORT_Create(void)
    {
        P4 = _08_Pn3_OUTPUT_1 | _10_Pn4_OUTPUT_1;
        PU4 = _00_PUn0_PULLUP_OFF;
        PU14 = _08_PUn3_PULLUP_ON;
        POM4 = _08_POMn3_NCH_ON | _10_POMn4_NCH_ON;
        PM4 = _01_PMn0_NOT_USE | _02_PMn1_NOT_USE | _04_PMn2_NOT_USE |
    _00_PMn3_MODE_OUTPUT | _00_PMn4_MODE_OUTPUT |
              _20_PMn5_NOT_USE | _C0_PM4_DEFAULT;
    }

    /* Start user code for adding. Do not edit comment generated here */
    #if defined(RENESAS_SIMULATOR_DEBUGGING)
    /* Workaround for a problem that the Renesas RL78 simulator does not work expectedly
     * for a wiring such as "N-ch Open Drain Output Port <--> LED <--> R <--> VDD" */
    void R_PORT_Create2(void)
    {
        if (IsRenesasSimDebugMode())
        {
            POM4 &= ~(_08_POMn3_NCH_ON | _10_POMn4_NCH_ON);
        }
    }
    #endif

    /* End user code. Do not edit comment generated here */

    なお、IsRenesasSimDebugMode()マクロは以下のようにrenesas_simulator_debugging_key変数を参照するようになっていて、そのrenesas_simulator_debugging_key変数はシミュレータデバッグのダウンロード時にPythonスクリプト(CS+)やDBGコマンド(e2 studio)によって自動的に書き換えるようにしています。

    src/RenesasSimDebug/sim_debug_mode_hook.h

    #if defined(RENESAS_SIMULATOR_DEBUGGING)

    extern const unsigned short renesas_simulator_debugging_key;

    #define IsRenesasSimDebugMode() (0x0001 == renesas_simulator_debugging_key)

    #endif

    src/RenesasSimDebug/sim_debug_mode_hook.c

    #if defined(RENESAS_SIMULATOR_DEBUGGING)

    /* Switch Key for Renesas Simulator Debugging
     *
     * non 0x0001 : Emulator or No debugger
     * 0x0001     : Renesas RL78 Simulator
     */
    const unsigned short renesas_simulator_debugging_key = 0xFFFF;

    #endif

    CS+の場合: ダウンロード後のフック関数にPythonスクリプトを記述
    freertos_sampleprog1_ccrl_c.py

    ...略...
    def AfterDownload():
    ...略...
        # Set the switch key variable in case of simulator.
        if debugger.DebugTool.GetType() == DebugTool.Simulator:
            debugger.Watch.SetValue('renesas_simulator_debugging_key', 0x0001)
        return

    e2 studioの場合: デバッグ構成の[Starup]の[コマンドを実行]にGDBコマンドを記述

    set renesas_simulator_debugging_key=0x0001

    もっとも、環境設定が一括でmtpjファイルに記憶されるCS+とは異なり、e2 studioでは各種環境設定ファイルを毎回手動で読み込む必要がありますので、僅か2つのPull Up設定を毎回手動で行うことを気にしても仕方無かったかもしれないなぁ、と投稿の下書きを書いていて思いました。

    (4) DTC転送時の送信開始処理と送信終了判定処理

    DTC転送時の送信開始処理と送信終了判定処理は、以下の通りにしました。RL78マイコンのSAUでは、RXマイコンのCSIとは異なり、送信バッファエンプティ割り込みと送信終了割り込みが共通になっており(どちらにするかSAUのレジスタで切り替える)、また、同様にRXマイコンのCSIとは異なり、送信終了割り込みはエッジ検出なのではないかと思われます。

    src/r_cg_serial.c

    MD_STATUS U_UART3_DTC_Send(uint8_t * tx_buf, uint16_t tx_num)
    {
        MD_STATUS status = MD_OK;

        if (tx_num < 1U && 256U < tx_num)
        {
            status = MD_ARGERROR;
        }
        else
        {
            if (1 < tx_num)
            {
                U_DTCD1_UserInit( tx_buf + 1, tx_num - 1 );
                R_DTCD1_Start();
                SMR12 |= _0001_SAU_BUFFER_EMPTY;
            }
            else
            {
                SMR12 &= ~_0001_SAU_BUFFER_EMPTY;
            }
            STIF3 = 0U;    /* clear INTST3 interrupt flag */
            STMK3 = 0U;    /* enable INTST3 interrupt */
            TXD3 = *tx_buf;    /* also raise INTST3 interrupt */
        }
        return status;
    }

    src/r_cg_serial_user.c

    static void __near r_uart3_interrupt_send(void)
    {
        /* DTC has finished data transfer operation. (i.e. The last data has been
         * written to SDR register.) But the data may stay in either SDR register
         * or shift register.
         */

        /* It is preferred that next interrupt will be a transmission end interrupt
         * (i.e. not only SDR register but also shift register become empty) than
         * a SDR register empty interrupt.
         */
        SMR12 &= ~_0001_SAU_BUFFER_EMPTY;

        /* In normal case of interrupt, UART has just finished data transmission
         * operation at 2nd interrupt. But in abnormal case of after long or very
         * long time pending of data transfer completion interrupt, though at 1st
         * interrupt, SDR register may already become empty or, moreover, shift
         * register may already have finished data transmission operation. In the
         * latter case, it is not clear whether data transmission end interrupt
         * will occur or not, so the following check is useful.
         */
        if ((SSR12 & _0040_SAU_UNDER_EXECUTE) == 0U)
        {
            /* UART has finished data transmission operation. Note that one more
             * interrupt may occur by above change of SMR register setting unless
             * transmission interrupt becomes disabled.
             */
            STMK3 = 1U;
            r_uart3_callback_sendend();
        }

        /* If ((SSR12 & _0040_SAU_UNDER_EXECUTE) == 0U) changes from false to true
         * just here,  changing SMR register setting at the following timing may
         * lose data transmission end interrupt.
         *
         * SMR12 &= ~_0001_SAU_BUFFER_EMPTY;
         */
    }

    以下、RL78/G14のユーザーズマニュアルのハードウェア編の画面コピーと私のメモの書き込みです。

    www.renesas.com/jp/ja/search/keyword-search.html#genre=document&q=r01uh0186
    r01uh0186jj0330-rl78g14.pdf




    (5) DTC保留命令によりタスク切り替えが起きなくなることへの対処

    以下のRL78/G14のユーザーズマニュアルのハードウェア編の画面コピーの通り、幾つかの命令の実行時にDTC転送が保留されることがあるのですが、DTC転送が保留されている間は割り込みも保留されることになっています。

    不運にも、移植元のRX-TBのサンプルプログラムでは、タイマ割り込み(FreeRTOSのTick割り込み)によってタスク切り替えが起きることを前提に、単なるタスクの一例として、以下のタスクを記述していました。このタスクのwhile(1);の部分はRL78ではBR $$となり、これはDTC保留命令になります。しかも、この命令が実行され続けますので、DTC転送が保留され続けてしまうと同時に、タイマ割り込み(FreeRTOSのTick割り込み)も保留され続けてしまいます。結局、タスク切り替えが起きなくなり、サンプルプログラムが動作しなくなってしまいました。そこで、以下の通り、NOPを挿入することにして回避しました。

    src/rl78g14_fpb_main.c

    修正前

    void main_task(void *pvParameters)
    {

        INTERNAL_NOT_USED(pvParameters);

        /* Create all other application tasks here */

        while(1);

        /* vTaskDelete(NULL); */

    }

    修正後

    void main_task(void *pvParameters)
    {

        INTERNAL_NOT_USED(pvParameters);

        /* Create all other application tasks here */

        while(1)
        {
            /* The nop prevents infinite DTC pending caused by BR $$.
             * (Moreover, such DTC pending causes infinite interrupt pending.
             * Furthermore, such interrupt pending prevents task switching.
             * So, in case of without nop, task switching never occur.)
             */
            nop();
        }

        /* vTaskDelete(NULL); */

    }

    ちなみに、修正前のソースでもRenesas RL78 Simulatorでは動作してしまいましたので、実機で動作させようとした途端に動作しなくなってしまったことに関して、暫く原因について思い悩みました。

    以下、RL78/G14のユーザーズマニュアルのハードウェア編の画面コピーです。


     

  • こんにちは。NoMaYです。#4連投の3つ目です。

    以下、各タスクのソースの通りです。(ヘッダ等は省略しています。また、ソース中に/* Start user code …略… */や/* End user code …略… */の記述がありますが、移植元のRX-TBの時にRXスマートコンフィグレータで生成されたタスクのスケルトンのソースに出力されていたものです。RL78コード生成機能では、タスクのスケルトンのソースは生成されません。)

    src/frtos_skeleton/task_LED0.c

    2705.task_LED0_c_20200106.txt
    #include "task_function.h"
    /* Start user code for import. Do not edit comment generated here */
    #include "freertos_start.h"
    #include "platform.h"
    #include "rl78g14fpbdef.h"
    
    #if defined(RENESAS_SIMULATOR_DEBUGGING)
    /* Hardware or Renesas RL78 Simulator */
    #define LED0_BLINK_FREQUENCY_MS pdMS_TO_TICKS( !IsRenesasSimDebugMode() ? 500 : 50 )
    #else
    /* Hardware */
    #define LED0_BLINK_FREQUENCY_MS pdMS_TO_TICKS( 500 )
    #endif
    /* End user code. Do not edit comment generated here */
    
    void task_LED0(void * pvParameters)
    {
    /* Start user code for function. Do not edit comment generated here */
    
        INTERNAL_NOT_USED( pvParameters );
    
        LED0 = LED_ON;
        for (;;)
        {
            vTaskDelay( LED0_BLINK_FREQUENCY_MS );
            LED0 = ~LED0;
        }
    
    /* End user code. Do not edit comment generated here */
    }
    


    src/frtos_skeleton/task_LED1.c
    4331.task_LED1_c_20200106.txt
    #include "task_function.h"
    /* Start user code for import. Do not edit comment generated here */
    #include "freertos_start.h"
    #include "platform.h"
    #include "r_cg_intc.h"
    #include "rl78g14fpbdef.h"
    
    extern volatile bool g_task_CONIO_error;
    
    #if defined(RENESAS_SIMULATOR_DEBUGGING)
    /* Hardware or Renesas RL78 Simulator */
    #define SW1_REMOVE_CHATTERING_PERIOD_MS pdMS_TO_TICKS( !IsRenesasSimDebugMode() ? 10 : 0 )
    #else
    /* Hardware */
    #define SW1_REMOVE_CHATTERING_PERIOD_MS pdMS_TO_TICKS( 10 )
    #endif
    /* End user code. Do not edit comment generated here */
    
    void task_LED1(void * pvParameters)
    {
    /* Start user code for function. Do not edit comment generated here */
    
        INTERNAL_NOT_USED( pvParameters );
    
        LED1 = LED_OFF;
        for (;;)
        {
            R_INTC0_Start();
            xSemaphoreTake( semaphore_handle_SW1_PUSH, portMAX_DELAY );
    
            /* Remove mechanical switch chattering */
            vTaskDelay( SW1_REMOVE_CHATTERING_PERIOD_MS );
    
            if (true == g_task_CONIO_error)
            {
                /* Clear error */
                g_task_CONIO_error = false;
            }
            else
            {
                /* Toggle LED1 */
                if (SW1_PUSH == SW1)
                {
                    LED1 = ~LED1;
                }
            }
        }
    
    /* End user code. Do not edit comment generated here */
    }
    


    src/frtos_skeleton/task_CONIO.c
    2514.task_CONIO_c_20200106.txt.txt
    #include "task_function.h"
    /* Start user code for import. Do not edit comment generated here */
    #include "freertos_start.h"
    #include "platform.h"
    #include "r_cg_serial.h"
    #include "rl78g14fpbdef.h"
    
    volatile bool g_task_CONIO_error = false;
    
    #define CON_RECV_DEMO_SIZE 3
    
    #if defined(RENESAS_SIMULATOR_DEBUGGING)
    /* Hardware or Renesas RL78 Simulator */
    #define LED1_ERROR_BLINK_FREQUENCY_MS pdMS_TO_TICKS( !IsRenesasSimDebugMode() ? 200 : 20 )
    #define CON_RECV_TIMEOUT_MS pdMS_TO_TICKS( !IsRenesasSimDebugMode() ? 60 * 1000UL : 600L )
    //#define CON_RECV_TIMEOUT_MS pdMS_TO_TICKS( !IsRenesasSimDebugMode() ? 60 * 1000UL : portMAX_DELAY ) /* for debug */
    //#define CON_RECV_TIMEOUT_MS pdMS_TO_TICKS( !IsRenesasSimDebugMode() ? 60 * 1000UL : 0 ) /* for debug */
    #else
    /* Hardware */
    #define LED1_ERROR_BLINK_FREQUENCY_MS pdMS_TO_TICKS( 200 )
    #define CON_RECV_TIMEOUT_MS pdMS_TO_TICKS( 60 * 1000UL )
    #endif
    /* End user code. Do not edit comment generated here */
    
    void task_CONIO(void * pvParameters)
    {
    /* Start user code for function. Do not edit comment generated here */
    
        volatile uint8_t recv_buff[CON_RECV_DEMO_SIZE + 1];
        volatile uint8_t err_type;
        BaseType_t ret;
    
        INTERNAL_NOT_USED( pvParameters );
    
        U_UART3_ASYNC_Start( semaphore_handle_CON_TX_READY, semaphore_handle_CON_RX_READY );
    
        for (;;)
        {
            memset( (char *)recv_buff, 0, CON_RECV_DEMO_SIZE + 1 );
    
            U_UART3_DTC_Receive( recv_buff, CON_RECV_DEMO_SIZE, &err_type );
            ret = xSemaphoreTake( semaphore_handle_CON_RX_READY, CON_RECV_TIMEOUT_MS );
    
            nop();  /* for breakpoint, check timing chart on Simulator GUI */
    
            if (pdPASS == ret && 0 == err_type)
            {
                taskENTER_CRITICAL();
                vPrintString( "Received Message: " );
                vPrintString( (char *)recv_buff );
                vPrintString( "\n" );
                taskEXIT_CRITICAL();
            }
            else
            {
                if (pdFAIL == ret)
                {
                    U_UART3_DTC_Receive_Abort(); /* or Retry U_UART3_DTC_Receive() */
                    vPrintString( "Timeout Error\n" );
                }
                else
                {
                    if (SCI_EVT_FRAMING_ERR & err_type)
                    {
                        vPrintString( "Framing Error\n" );
                    }
                    if (SCI_EVT_PARITY_ERR & err_type)
                    {
                        vPrintString( "Parity Error\n" );
                    }
                    if (SCI_EVT_OVFL_ERR & err_type)
                    {
                        vPrintString( "Overrun Error\n" );
                    }
                }
    
                g_task_CONIO_error = true;
                LED1 = LED_ON;
                while (true == g_task_CONIO_error)
                {
                    vTaskDelay( LED1_ERROR_BLINK_FREQUENCY_MS );
                    LED1 = ~LED1;
                }
                LED1 = LED_OFF;
    
                continue;
            }
    
            U_UART3_DTC_Send( (uint8_t *)recv_buff, CON_RECV_DEMO_SIZE );
            ret = xSemaphoreTake( semaphore_handle_CON_TX_READY, portMAX_DELAY );
    
            nop();  /* for breakpoint, check timing chart on Simulator GUI */
        }
    
    /* End user code. Do not edit comment generated here */
    }
    


    以下、Renesas RL78 Simulatorでシリアル送信データのファイルを使った実行例の画面コピーです。

    CC-RL+CS+の場合

    sim_rl78_serial_data_ok_2.ser(今回追加)を使用した例





    sim_rl78_serial_data_err_uart_format.serを使用した例





    GNURL78+e2 studioの場合 (CC-RL+e2 studioの場合も同様です)

    sim_rl78_serial_data_ok_2.ser(今回追加)を使用した例



    sim_rl78_serial_data_err_uart_format.serを使用した例


     

  • こんにちは。NoMaYです。#4連投の4つ目です。

    コード生成機能の設定は以下の画面コピーの通りです。(以下の画面コピーはCC-RL+CS+のものですが、CC-RL+e2 studioでもGNURL78+e2 studioでも、同様です。)

    DTC設定(転送元アドレスと転送先アドレスは単に仮の値)




    シリアル設定




    外部割込み設定(かふぇルネの他の投稿にありましたが単なるSW入力ぐらいでは外部割り込みは使われないようです)


    ポート設定



    ウォッチドッグタイマ設定(単に使用しない設定)


    安全機能設定(単に使用しない設定)


    リセット要因確認設定(単に確認関数を出力しない設定)


    端子割り当て設定


    クロック設定


    なお、GNURL78+e2 studio+コード生成機能でDTCを使用する場合には、GNURL78のobjcopyコマンドのコマンドラインオプションに以下の画面コピーのオプションを追加しておくと良いと思います。そうしないと、DTCを使用する場合にコード生成機能によってリンカスクリプトに追加された設定により、MOTファイルにRAM領域のレコードが出力されるようになってしまいますので、最近のRenesas Flash Programmerでは以下の画面コピーのようにエラーになってしまうからです。

    GNURL78のobjcopyコマンドのコマンドラインオプションに追加するオプション
    -R .dtc_vectortable -R .dtc_controldata_*


    オプションを追加しない場合には最近のRenesas Flash Programmerではエラーになる

     

  • こんにちは。NoMaYです。

    UART受信にチョコさんのリングバッファのソースコードを使用する版をデバッグしないといけないな、と思いつつ、ちょっと好奇心から、FreeRTOSのタスク通知という機能を試したところ、このスレッドのRL78ポートレイヤの実装では動作しないことが分かりました。(修正方法を考え中です。)

    タスク通知 - AWS » ドキュメント » FreeRTOS Kernel » 開発者ガイド »
    docs.aws.amazon.com/ja_jp/freertos-kernel/latest/dg/task-notification.html

    それで、動作しない原因ですけれども、FreeRTOSのタスク通知のAPI関数であるulTaskNotifyTake()という関数は以下の通りですが、2つある赤文字部分のどちらかでタスク切り替え処理に移行しなければならないコードになっています。もともとのRL78ポートレイヤはBRK命令を使っていて、上側(A)の赤文字部分でタスク切り替え処理に移行します。それに対し、このスレッドで私が改造したRL78ポートレイヤはソフトウェア割り込み(もどき)機能を使いますが、下側(B)のちょうどtaskEXIT_CRITICAL()とtaskENTER_CRITICAL()の隙間の赤文字部分でタスク切り替え処理に移行しなければならないのでした。

    ところが、下側(B)の部分の隙間はアセンブラレベルではEI命令とDI命令の隙間になっていて、RL78の仕様上、ここでは割り込みが受け付けられないことになっています。(下記のユーザーズマニュアル ハードウェア編の画面コピーを参照) その為、ソフトウェア割り込み(もどき)でタスク切り替え処理に移行することが出来ず、ulTaskNotifyTake()の上側のクリティカルセクションと下側のクリティカルセクションを続けて実行してしまい(そして両方のクリティカルセクションの実行後にタスク切り替え処理に移行することになり)、タスク通知の機能が動作しなくなっていました。

    これが、いわゆる、生兵法は大怪我のもと、というものでしょうかね、、、(修正方法を考え中です。)

    src/FreeRTOS/Source/task.c

    #if( configUSE_TASK_NOTIFICATIONS == 1 )

        uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
        {
        uint32_t ulReturn;

            taskENTER_CRITICAL();
            {
                /* Only block if the notification count is not already non-zero. */
                if( pxCurrentTCB->ulNotifiedValue == 0UL )
                {
                    /* Mark this task as waiting for a notification. */
                    pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;

                    if( xTicksToWait > ( TickType_t ) 0 )
                    {
                        prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
                        traceTASK_NOTIFY_TAKE_BLOCK();

                        /* All ports are written to allow a yield in a critical
                        section (some will yield immediately, others wait until the
                        critical section exits) - but it is not something that
                        application code should ever do. */
                        portYIELD_WITHIN_API(); ← (A)
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            taskEXIT_CRITICAL(); ← この行の最後の命令は EI命令 です
            ちょうど此処の隙間 ← (B)
            taskENTER_CRITICAL(); ← この行の最初の命令は DI命令 です
            {
                traceTASK_NOTIFY_TAKE();
                ulReturn = pxCurrentTCB->ulNotifiedValue;

                if( ulReturn != 0UL )
                {
                    if( xClearCountOnExit != pdFALSE )
                    {
                        pxCurrentTCB->ulNotifiedValue = 0UL;
                    }
                    else
                    {
                        pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
                    }
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }

                pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
            }
            taskEXIT_CRITICAL();

            return ulReturn;
        }

    #endif /* configUSE_TASK_NOTIFICATIONS */

    以下、RL78/G14のユーザーズマニュアルのハードウェア編の画面コピーです。

    www.renesas.com/jp/ja/search/keyword-search.html#genre=document&q=r01uh0186
    r01uh0186jj0330-rl78g14.pdf

    EI命令実行直後は割り込みを受け付けない


    他の割り込みによるRETI命令実行直後は割り込みを受け付けない(1命令実行後に受け付ける)のも気掛かり

     

  • こんにちは。NoMaYです。

    FreeRTOSのタスク通知ですが、なにか手軽そうですね。先日投稿したSample Programではセマフォを使用していたのですが、タスク通知を使用する方法に書き換え中です。ただ、この機能はFreeRTOSや同じコードベースの商用版のOpenRTOSやAPI互換の商用機能安全版のSafeRTOSに特有なものなのかな、みたいな感じがしますので、いわゆるOS Abstraction layerとかでは対応されないものなのかも、という気もします。

    また、このスレッドの前に投稿していた以下のスレッドで、RL78/G13ですが、UART受信をDMAで行う際に受信エラーを返せるようにしたFreeRTOSサンプルプログラムを投稿した際に遭遇していた、予測外の割り込みによる誤動作に対しては、以下のように似たような小技で対処が出来るような感じになっていました。

    Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみた
    「ダミーのブロック解除待ちを入れることでも対処することが出来ました」
    japan.renesasrulz.com/cafe_rene/f/forum21/5790/amazon-aws-freertos-kernel-developer-guide-renesas-rx-simulator-debug-console/32254#32254

    タスク通知 - AWS » ドキュメント » FreeRTOS Kernel » 開発者ガイド »
    周辺機器デバイスドライバで使用されるタスク通知: UARTの例 ← なお送信の例なので関数名やコメントは受信の例へ脳内変換が必要です、、、
    docs.aws.amazon.com/ja_jp/freertos-kernel/latest/dg/task-notification.html#task-notifications-used-in-peripheral-device-drivers-uart-example

    BaseType_t xUART_Send( xUART *pxUARTInstance, uint8_t *pucDataSource, size_t uxLength )
    {
        BaseType_t xReturn;

        /* Save the handle of the task that called this function. The book text
        contains notes as to whether the following line needs to be protected
        by a critical section or not. */
        pxUARTInstance->xTaskToNotify = xTaskGetCurrentTaskHandle();

        /* Ensure the calling task does not already have a notification pending
        by calling  ulTaskNotifyTake() with the xClearCountOnExit parameter set
        to pdTRUE, and a block time of 0  (don't block). */
        ulTaskNotifyTake( pdTRUE, 0 );

        /* Start the transmission. */
        UART_low_level_send( pxUARTInstance, pucDataSource, uxLength );

        /* Block until notified that the transmission is complete.
        If the notification is received, then xReturn will be set to 1
        because the ISR will have incremented this task's notification value to 1 (pdTRUE).
        If the operation times out, then xReturn will be 0 (pdFALSE)
        because this task's notification value will not have been changed
        since it was cleared to 0 above.
        If the ISR executes between the calls to UART_low_level_send()
        and the call to ulTaskNotifyTake(), then the event will be latched
        in the task's notification value, and the call to ulTaskNotifyTake()
        will return immediately.*/
        xReturn = ( BaseType_t ) ulTaskNotifyTake( pdTRUE, pxUARTInstance->xTxTimeout );

        return xReturn;
    }

    Amazon AWSのFreeRTOS Kernel Developer GuideのサンプルコードをRenesas RX SimulatorのDebug Consoleで試せるようにしてみた
    「受信エラー割り込みが複数回発生しないようにするやり方でも対処してみました」
    apan.renesasrulz.com/cafe_rene/f/forum21/5790/amazon-aws-freertos-kernel-developer-guide-renesas-rx-simulator-debug-console/32271#32271

    www.freertos.org » Kernel » Developer Docs » Direct To Task Notifications » ...As Binary Semaphore
    RTOS Task Notifications
    Used As Light Weight Binary Semaphores ← なお送信の例なので関数名やコメントは受信の例へ脳内変換が必要です、、、
    www.freertos.org/RTOS_Task_Notification_As_Binary_Semaphore.html

    void StartTransmission( uint8_t *pcData, size_t xDataLength )
    {
        /* At this point xTaskToNotify should be NULL as no transmission
        is in progress.  A mutex can be used to guard access to the
        peripheral if necessary. */
        configASSERT( xTaskToNotify == NULL );

        /* Store the handle of the calling task. */
        xTaskToNotify = xTaskGetCurrentTaskHandle();

        /* Start the transmission - an interrupt is generated when the
        transmission is complete. */
        vStartTransmit( pcData, xDatalength );
    }
    void vTransmitEndISR( void )
    {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

        /* At this point xTaskToNotify should not be NULL as a transmission was
        in progress. */
        configASSERT( xTaskToNotify != NULL ); → ここを以下にすれば割り込みが複数回発生しても誤動作しない
      if (xTaskToNotify != NULL)
      {

        /* Notify the task that the transmission is complete. */
        vTaskNotifyGiveFromISR( xTaskToNotify, &xHigherPriorityTaskWoken );

        /* There are no transmissions in progress, so no tasks to notify. */
        xTaskToNotify = NULL;

        /* If xHigherPriorityTaskWoken is now set to pdTRUE then a context switch
        should be performed to ensure the interrupt returns directly to the highest
        priority task.  The macro used for this purpose is dependent on the port in
        use and may be called portEND_SWITCHING_ISR(). */
        portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

      }
    }

    [参考]

    FreeRTOSとOpenRTOS/SafeRTOS
    www.freertos.org/a00114.html#commercial

    RTOS Resources and Tutorials
    www.highintegritysystems.com/rtos/rtos-tutorials/

    [追記]

    ちなみに、タスク通知が動作しなかった件の、このスレッドのポートレイヤの問題ですが、当面は、以下のようにすることで対処しようと考えています。ただ、RTOSのカーネル/ポートレイヤで、このようなループ終了条件が自明とはちょっと言いにくいようなループは嫌われるのかも、とも感じていますので、何とか改善したい気持ちはあります。(RTOSのドキュメントで、deterministic、とか、決定論的、とか、そういう言葉を見掛けますので、そういうものなのかも、と感じているのです。)

    src/FreeRTOS/Source/portable/Renesas/RL78/portmacro.h
    src/FreeRTOS/Source/portable/GCC/RL78/portmacro.h

    #define portEXIT_CRITICAL()                                                     \
    {                                                                               \
    extern volatile uint16_t usCriticalNesting;                                     \
                                                                                    \
        if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING )                   \
        {                                                                           \
            /* Decrement the nesting count as we are leaving a critical section. */ \
            usCriticalNesting--;                                                    \
                                                                                    \
            /* If the nesting level has reached zero then interrupts should be */   \
            /* re-enabled. */                                                       \
            if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING )              \
            {                                                                       \
                portENABLE_INTERRUPTS();                                            \
                /* This NOP prevents infinite DTC pending caused by BT WDTIIF $$. */\
                /* (Moreover, such DTC pending causes infinite interrupt pending. */\
                /* Furthermore, such interrupt pending prevents task switching. */  \
                /* So, in case of without this NOP, task switching never occur */   \
                /* if DTC occurs just here.)(This is in case of CC-RL. In case of */\
                /* GNURL78, more codes are generated so this situation does not */  \
                /* happen but NOP is inserted to be the same operation as CC-RL.) */\

                do{ portNOP(); }while (WDTIIF != 0);                                \
            }                                                                       \
        }                                                                           \
    }
     
  • こんにちは。NoMaYです。

    RL78のコード生成機能で生成されたUART受信処理は以下のようなコードになるのですが、RXスマートコンフィグレータで生成されたコードとは異なり(受信処理中では無い時に受信割り込みが発生したというソフトウェアオーバーランと呼ばれるエラーの検出/対処を可能にする為?)、受信処理完了後も受信割り込みが許可された状態になっています。神経質な話ですが、次の受信処理開始時に受信割り込みで使用する変数群を変更する際に以下の(1)~(3)の途中で受信割り込みが発生してしまった場合、前の受信処理の受信バッファの(末尾+1)番地に書き込んだり、その受信バッファがスタックに確保されていた場合にはもう無関係になってしまった場所に書き込んだり、といったことが起きてしまうように思います。

    この(1)~(3)の区間は受信割り込みを一時禁止(受信開始時点なのでクリティカルセクションにするほどでは無いと思いました)するようにした方が安全だと思います。(ただし、禁止しなかった場合、この区間で他タスクへミリ秒オーダーで行ってしまうかもしれず、(末尾+1)番地よりもずっと多く書き込んでしまったりすることもあるかもしれないと思いました。) (デバッグしていて気付いた訳ではなくて、2ヶ月ほどコードと睨めっこしたあげくに思ったことです。)

    r_cg_serial_user.c

    void r_uart3_interrupt_receive(void)
    {
        volatile uint8_t rx_data;
        volatile uint8_t err_type;
        
        err_type = (uint8_t)(SSR13 & 0x0007U);
        SIR13 = (uint16_t)err_type;

        if (err_type != 0U)
        {
            r_uart3_callback_error(err_type);
        }
        
        rx_data = RXD3;

        if (g_uart3_rx_length > g_uart3_rx_count)
        {
            *gp_uart3_rx_address = rx_data;
            gp_uart3_rx_address++;
            g_uart3_rx_count++;

            if (g_uart3_rx_length == g_uart3_rx_count)
            {
                r_uart3_callback_receiveend();
            }
        }
        else
        {
            r_uart3_callback_softwareoverrun(rx_data);
        }
    }
    static void r_uart3_callback_receiveend(void)
    {
        /* Start user code. Do not edit comment generated here */
        /* End user code. Do not edit comment generated here */
    }
    static void r_uart3_callback_softwareoverrun(uint16_t rx_data)
    {
        /* Start user code. Do not edit comment generated here */
        /* End user code. Do not edit comment generated here */
    }
    static void r_uart3_callback_error(uint8_t err_type)
    {
        /* Start user code. Do not edit comment generated here */
        /* End user code. Do not edit comment generated here */
    }

    r_cg_serial.c

    MD_STATUS R_UART3_Receive(uint8_t * const rx_buf, uint16_t rx_num)
    {
        MD_STATUS status = MD_OK;

        if (rx_num < 1U)
        {
            status = MD_ARGERROR;
        }
        else
        {
            g_uart3_rx_count = 0U; - (1)
            g_uart3_rx_length = rx_num; - (2)
            gp_uart3_rx_address = rx_buf; - (3)
        }

        return (status);
    }

    こうすれば安全になると思われるコード: 受信割り込みを一時禁止する(受信開始時点なのでクリティカルセクションにするほどでは無いと思いました)

            SRMK3 = 1U;    /* disable INTSR3 interrupt */
            g_uart3_rx_count = 0U;
            g_uart3_rx_length = rx_num;
            gp_uart3_rx_address = rx_buf;
            SRMK3 = 0U;    /* enable INTSR3 interrupt */

     

  • こんにちは。NoMaYです。#4連投の1つ目です。

    このスレッドで以前に投稿した、RX-TBの自作のFreeRTOS Sample ProgramをRL78/G14 Fast Prototyping Boardへ移植したSample Programですが、今回、UART送受信を割り込みのみで行う版とDTCで行う版を作成してみました。また、今回、セマフォ(バイナリセマフォ)を使用しないで、FreeRTOSのタスク通知を使用する方法で作成してみました。(FreeRTOSのタスク通知が、なにか手軽そう、という印象だったからです。ただ、やってみると、手軽さに関しては、事前にセマフォ(バイナリセマフォ)を作成する手間が減った分ぐらいだった気がするなぁ、という感じで、ちょっと思い込み過ぎていたかなぁ、という気もしました。)

    それから、今回、FreeRTOSのAPI関数をタスク側ソースではなくコード生成側ソースで呼ぶような作りにして、タスク側では以下の3つの関数で送受信処理を実行するようにしたのですが、(C)のデバッグ用にSample Programの動作に以下の(3'')の動作を追加しました。

    (A) U_UART3_Receive_Wait
    (B) U_UART3_Send_Wait
    (C) U_UART3_Send_Receive_Wait ← 注: 受信処理を起動してから送信処理を実行します

    (1) FPBボードのLED0を500ms毎にOn/Offする(FreeRTOS APIのvTaskDelay()を使用)
    (2) FPBボードのSW1押下毎にLED1をOn/Offする(タスクでタスク通知待ちして割り込みでタスク通知発行)
    (3) FPBボードのUART3で3文字受信毎に3文字エコーバックする(タスクでタスク通知待ちして割り込みで3文字毎にタスク通知発行)
    (3') 受信エラーを検出したらLED1を200ms毎にOn/OffさせるようにしてSW1が押下されたら受信エラー状態をクリアする
       検出する受信エラー:パリティエラー、フレーミングエラー、オーバーランエラー、タイムアウト(60秒)
    (3'') CPUリセット後と受信エラー状態クリア後に"Enter characters"の文字列+CR+LFを送信する

    以下、プロジェクトのファイル一式です。(CC-RL版はCS+ V8.03/e2 studio v7.6.0+CC-RX V1.02でビルド(e2 studio用.project/.cproject等を同梱)(当方特有の事情でCC-RX V1.02を使用))(GNURL78版はe2 studio v7.6.0+GNURL78 2019q4(4.9.2.201904)でビルド)(共にzipファイルをe2 studioに直接インポート可能) プロジェクト構造は極力RX-TBの自作のFreeRTOSプロジェクトもどきSample Programに似せてあります。

    rl78g14fpb_freertos_sampleprog1and2_ccrl_c_csplus_20200204.zip (*1)    805KB
    rl78g14fpb_freertos_sampleprog1and2_gnurl78_c_e2v760_20200204.zip (*1,*2)   738KB

    含まれるプロジェクト
    sampleprog1: UART送受信をDTCで行う版
    sampleprog2: UART送受信を割り込みのみで行う版

    *1:実機用のデバッガプロパティ設定(CS+)や.launchファイル設定(e2 studio)は当方特有の事情でオンボードエミュレータが使えない為に未確認です。(ひと通りは設定してあります。)

    *2:リンカスクリプトには別スレッド「GNURL78でconst領域/Mirror領域をちょっと安全に使えるようにlinker scriptのASSERT()で小技(TIPS)を考えてみた」に投稿した内容を反映してあります。

    この後、2投目~4投目は以下の通りです。

    2投目

    ・FreeRTOSのタスク通知のAPI関数への自作ラッパー関数
    ・LED1タスクのソースとコード生成された外部割込み処理のユーザ記述部のソース
    (今回はFreeRTOSのAPI関数(のラッパー関数)をタスク側ソースではなくコード生成側ソースで呼ぶようにしています)

    3投目

    ・UART送受信を割り込みのみで行う版のCONIOタスクのソースとコード生成されたシリアル処理のユーザ記述部のソース
    (今回はFreeRTOSのAPI関数(のラッパー関数)をタスク側ソースではなくコード生成側ソースで呼ぶようにしています)
    (なお、受信完了で受信割り込みを止めるようにしています)

    4投目

    ・UART送受信をDTCで行う版のCONIOタスクのソースとコード生成されたシリアル処理のユーザ記述部のソース
    (今回はFreeRTOSのAPI関数(のラッパー関数)をタスク側ソースではなくコード生成側ソースで呼ぶようにしています)
    (なお、受信完了で受信割り込みを止めるようにしています)

    以下、画面コピーです。(といっても、動作に追加した"Enter characters"がTeraTermやe2 studioのTerminalビューに表示されているところのみ、ですが。)



     

  • こんにちは。NoMaYです。#4連投の2つ目です。

    今回、先日このスレッドに投稿したFreeRTOSのタスク通知のAPI関数を使用する時の小技に関して、以下のラッパー関数を自作してみました。(小技に関する部分を赤文字にしています。)

    src/frtos_startup/freertos_start.c

    void vTaskNotifyGiveFromISR_R_Helper(TaskHandle_t *pxTask)
    {
        if (NULL != *pxTask)[
        {
            BaseType_t sHigherPriorityTaskWoken = pdFALSE;

            /* Notify the task that the interrupt/callback is complete. */
            vTaskNotifyGiveFromISR( *pxTask, &sHigherPriorityTaskWoken );

            /* There are no interrupt/callback in progress, so no tasks to notify. */
            *pxTask = NULL;

            portYIELD_FROM_ISR( sHigherPriorityTaskWoken );
        }

    } /* End of function vTaskNotifyGiveFromISR_R_Helper() */
     
    TaskHandle_t xTaskGetCurrentTaskHandle_R_Helper(void)
    {
        /* Ensure the calling task does not already have a notification pending. */
        ulTaskNotifyTake( pdTRUE, 0 );

        /* Return the handle of the calling task. */
        return xTaskGetCurrentTaskHandle();

    } /* End of function xTaskGetCurrentTaskHandle_R_Helper() */

    なお、併せて、API関数呼び出しの簡略化の為に(といっても引数を1つ省略する為だけなのですが)、以下のラッパー関数も作成しています。

    src/frtos_startup/freertos_start.c

    uint32_t ulTaskNotifyTake_R_Helper(TickType_t xTicksToWait)
    {
        /* Wait to be notified that the interrupt/callback is complete. */
        return ulTaskNotifyTake( pdTRUE, xTicksToWait );

    } /* End of function ulTaskNotifyTake_R_Helper() */

    LED1タスクのソースは以下の通りです。今回はFreeRTOSのAPI関数(のラッパー関数)をタスク側ソースではなくコード生成側ソースで呼ぶようにしています。(コード生成側ソースの関数を呼び出している箇所を青文字にしています。)

    src/frtos_skeleton/task_LED1.c

    void task_LED1(void * pvParameters)
    {
    /* ...略... */

        INTERNAL_NOT_USED( pvParameters );

        R_INTC0_Start();

        LED1 = LED_OFF;
        for (;;)
        {
            U_INTC0_Wait();

            /* Remove mechanical switch chattering */
            vTaskDelay( SW1_REMOVE_CHATTERING_PERIOD_MS );

            if (SW1_PUSH == SW1)
            {
                if (true == g_task_CONIO_error)
                {
                    /* Clear error */
                    g_task_CONIO_error = false;
                }
                else
                {
                    /* Toggle LED1 */
                    LED1 = ~LED1;
                }
            }
        }

    /* ...略... */
    }

    コード生成された外部割込み処理のユーザ記述部のソースは以下の通りです。(FreeRTOSのAPI関数(のラッパー関数)を呼び出している箇所を赤文字にしています。)

    src/r_cg_intc.c

    /* Start user code for adding. Do not edit comment generated here */
    ...略...
    void U_INTC0_Wait(void)
    {
        g_intc0_task = xTaskGetCurrentTaskHandle_R_Helper();

        /* Wait for a notification from the interrupt/callback */
        ulTaskNotifyTake_R_Helper( portMAX_DELAY );[1行
    }
    /* End user code. Do not edit comment generated here */

    src/r_cg_intc_user.c

    void r_intc0_interrupt(void)
    {
        /* Start user code. Do not edit comment generated here */

        vTaskNotifyGiveFromISR_R_Helper( &g_intc0_task );

        /* End user code. Do not edit comment generated here */
    }

     

Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page