RX SmartConfiguratorのGNURX向け生成コードのBugではないかと思われる動作について

こんにちは。NoMaYです。

RXスマートコンフィグレータ(V2.0.0)とGNURX 2018q3(4.8.4.201803)でプログラムを作成しようとして気付いたものです。(RXスマートコンフィグレータに起因するものだけで無くe2 studioやGNURXに起因するものもあります。) (なおCC-RX向け生成コードでも発生するものはこちらのスレッドにあります。)

プロジェクトのファイル一式
issue_20190413.zip

(1) RX65NのROM大版ではRAMは0~0x3FFFFと0x800000~0x85FFFFにあるがリンカスクリプト上は0~0x9FFFFの扱いである
(2) GNURXでは未サポートの#pragamディレクティブを含んでいるソースがある
(3) グループ割り込み関数とバスエラー割り込み関数に__attribute__ ((interrupt))が付いていない
(4) DTCを使用するコードを生成させるとビルドしたMOTファイルがRFPでエラーになる

以下、その詳細と私が取った回避策です。

(1) RX65NのROM大版ではRAMは0~0x3FFFFと0x800000~0x85FFFFにあるがリンカスクリプト上は0~0x9FFFFの扱いである

もともとはGR-ROSEの開発者さんの指摘なのですが、生成されたリンカスクリプトは以下の通りです。

src/linker_script.ld

MEMORY
{
    RAM : ORIGIN = 0x0, LENGTH = 655360
    ROM : ORIGIN = 0xFFE00000, LENGTH = 2097152
    OFS : ORIGIN = 0xFE7F5D00, LENGTH = 256
}

回避策は以下のように修正することです。(これはGR-ROSEの開発者さんが指摘していた回避策です。)

MEMORY
{
    RAM : ORIGIN = 0x0, LENGTH = 262144
    RAMHI : ORIGIN = 0x800000, LENGTH = 393216
    ROM : ORIGIN = 0xFFE00000, LENGTH = 2097152
    OFS : ORIGIN = 0xFE7F5D00, LENGTH = 256
}

(2) GNURXでは未サポートの#pragamディレクティブを含んでいるソースがある

GNURXでは以下の4つの#pragamディレクティブは無視されますが、#pragma bit_order leftが無視された状況では以下のビットフィールドの並び順はビッグエンディアンでの並び順であり、リトルエンディアンでは逆順にするのが正しいです。

src/smc_gen/r_bsp/board/generic_rx65n/hwsetup.c

#pragma bit_order left
#pragma unpack
typedef struct bsp_bsc {
    union {
        uint32_t u_long;
        struct {
            uint32_t prerr:1;
            uint32_t :1;
            uint32_t rpstop:1;
            uint32_t :10;
            uint32_t pr5sel:3;
            uint32_t :1;
            uint32_t pr4sel:3;
            uint32_t :1;
            uint32_t pr3sel:3;
            uint32_t :1;
            uint32_t pr2sel:3;
            uint32_t :1;
            uint32_t pr1sel:3;
        } bit;
    } ebmapcr;
} st_bsp_bsc_t;
#pragma bit_order
#pragma packoption

回避策は以下の通りです。(なお、CC-RX/GNURX/ICCRX共通化BSPがリリースされれば修正される筈です。)

(A) BSCユニットのEBMAPCRレジスタにアクセスしなければ放置する(そもそもROM 2MB版でしかアクセスされない)

(B) アクセスするのであればGNURX向けiodefine.hから切り貼りして以下のように修正する

#pragma pack(4)
typedef struct bsp_bsc {
    union {
        uint32_t u_long;
        struct {
#ifdef __RX_LITTLE_ENDIAN__
            uint32_t pr1sel:3;
            uint32_t :1;
            uint32_t pr2sel:3;
            uint32_t :1;
            uint32_t pr3sel:3;
            uint32_t :1;
            uint32_t pr4sel:3;
            uint32_t :1;
            uint32_t pr5sel:3;
            uint32_t :10;
            uint32_t rpstop:1;
            uint32_t :1;
            uint32_t prerr:1;
#else
            uint32_t prerr:1;
            uint32_t :1;
            uint32_t rpstop:1;
            uint32_t :10;
            uint32_t pr5sel:3;
            uint32_t :1;
            uint32_t pr4sel:3;
            uint32_t :1;
            uint32_t pr3sel:3;
            uint32_t :1;
            uint32_t pr2sel:3;
            uint32_t :1;
            uint32_t pr1sel:3;
#endif
        } bit;
    } ebmapcr;
} st_bsp_bsc_t;
#pragma pack()

(3) グループ割り込み関数とバスエラー割り込み関数に__attribute__ ((interrupt))が付いていない

ヘッダファイル上では、これらの関数に__attribute__ ((interrupt))が付いていますが、インクルードするのを忘れたのだろうと思います。

src/smc_gen/r_bsp/mcu/rx65n/mcu_interrupt.c

void group_bl0_handler_isr (void)
{

}
void group_bl1_handler_isr (void)
{

}
void group_bl2_handler_isr (void)
{

}
void group_al0_handler_isr (void)
{

}
void group_al1_handler_isr (void)
{

}

src/smc_gen/r_bsp/board/generic_rx65n/vecttbl.c

void bus_error_isr (void)
{

}

src/smc_gen/general/r_cg_interrupt_handlers.h

/* BSC BUSERR */
void bus_error_isr(void) __attribute__ ((interrupt));



/* ICU GROUPBL2 */
void group_bl2_handler_isr(void) __attribute__ ((interrupt));

/* ICU GROUPBL0 */
void group_bl0_handler_isr(void) __attribute__ ((interrupt));

/* ICU GROUPBL1 */
void group_bl1_handler_isr(void) __attribute__ ((interrupt));

/* ICU GROUPAL0 */
void group_al0_handler_isr(void) __attribute__ ((interrupt));

/* ICU GROUPAL1 */
void group_al1_handler_isr(void) __attribute__ ((interrupt));

回避策は以下の通りです。(なお、CC-RX/GNURX/ICCRX共通化BSPがリリースされれば修正される筈です。)

(A) グループ割り込み関数とバスエラー割り込み関数を使わなければ放置する

(B) 使うのであれば以下の何れかの策を取る

(B-1) mcu_interrupt.cとvecttbl.cに以下を追加する

#include "platform.h"
#include "r_cg_interrupt_handlers.h"

(B-2) r_bsp_config.hに以下を追加する

#include "r_cg_interrupt_handlers.h"

(4) DTCを使用するコードを生成させるとビルドしたMOTファイルがRFPでエラーになる

DTCを使用すると、以下のように、ソースが生成されて、リンカスクリプトにセクションが追加されて、RAM上に初期値が割り当てられますが、それがrx-elf-objcopyによりMOTファイルにレコードとして出力され、そのレコードが最近のRFPではエラーになります。

src/smc_gen/Config_DTC_ELSR18I/Config_DTC_ELSR18I.c

volatile uint32_t dtc_vector193 __attribute__ ((section (".dtc_vector193")));

src/linker_script.ld

.dtc_vector193 0x3ff04 : AT(0x3ff04)
    {
        KEEP(*(.dtc_vector193))
    } >RAM

MAPファイル

.dtc_vector193  0x0003ff04        0x4
 *(.dtc_vector193)
 .dtc_vector193
                0x0003ff04        0x4 ./src/smc_gen/Config_DTC_ELSR18I/Config_DTC_ELSR18I.o
                0x0003ff04                _dtc_vector193

MOTファイル

S3090003FF0400000000F0

RFP V3.05.01のエラーの画面コピー


回避策は以下の画面コピーのようにプロジェクトのプロパティでrx-elf-objcopyのオプションを変更してしまうことです。(今のところは素朴にObjcopyのオプションを追加する方法は無さそうです。以下の画面コピーのObjcopy→Generalの設定で任意のオプションを追加することが出来れば良かったのですが、、、)

エキスパート設定のコマンド行パターンに -R .dtc_vector* を追加する


任意のオプションを追加することが出来ると良かったのですが、、、


ちなみに上記の(2)と(3)はワーニングレベルを上げると、そのものズバリ(赤枠)、あるいは当たらずしも遠からず(橙枠)、で以下の画面コピーのようにGNURXコンパイラにより検出されていました。(なお以下のワーニング設定はAmazon FreeRTOSの別スレッドで使用していたものです。)


Parents
  • ほやさん、シェルティさん、こんにちは。NoMaYです。

    リプライ有難う御座います。私が取った(4)の回避策は、回避策として不便には成らないようにしたかったという思惑を反映しています。リンカスクリプトの該当箇所を書き換える策は、コード生成時に元に戻ってしまうのです。(なお(B-1)のmcu_interrupt.cとvecttbl.cを書き換える策は、スマートコンフィグレータのデフォルト設定では生成済みFITモジュールは書き換えても元には戻らないこと(生成済みFITモジュールは再生成しないというデフォルト設定)を利用しています。)

    それはそれとして、ほやさんのリプライを見て、そういえば何か変なような?と思ったことがあったので、調べてみました。

    > ソースを見た限りでは初期値はない
    そもそも初期値がないのにMOTファイルにレコードが出ていたのは何故なのだろう?

    気付いたことは、__attribute__ ((section ("セクション名"))) とした場合、Cソース上で初期値無しでもGNURXコンパイラが初期値0でコードを生成していた、ということです。例えば、以下の青文字の記述部分と赤文字の記述部分で、それぞれ生成コードを比較することで違いが分かります。

    Config_DTC_ELSR18I.c

    volatile uint32_t dtc_vector193 __attribute__ ((section (".dtc_vector193")));
    volatile st_dtc_data_t dtc_transferdata_vector193[2];

    Config_DTC_ELSR18I.lst

      76                                    .comm   _dtc_transferdata_vector193,24,4
      77                                    .global _dtc_vector193
      78                                    .section    .dtc_vector193,"aw",@progbits
      79                                    .balign 4
      82                                _dtc_vector193:
      83 0000 00 00 00 00                   .zero   4

    それに対して、CC-RXでは、#pragma addressでアドレス指定した場合、Cソース上で初期値無しなら初期値無しでコードが生成されていた、ことにも気付きました。

    Config_DTC_ELSR18I.c

    #pragma address dtc_vector193=0x0003FF04U
    volatile uint32_t dtc_vector193;
    volatile st_dtc_data_t dtc_transferdata_vector193[2];

    Config_DTC_ELSR18I.lst

                                            .SECTION    B,DATA,ALIGN=4
    00000000                         _dtc_transferdata_vector193:
    00000000(00000018H)                     .blkl   6
                                            .SECTION    $ADDR_B_3FF04,DATA
                                     
    0003FF04                                .ORG        3FF04H
    0003FF04                         _dtc_vector193:
    0003FF04(00000004H)                     .blkb   4

    ちなみに別スレッド『GNURX用のCCRXmachine.hとCCRXmachine.cというソースがe2 studioフォルダにありました(内容は概ね名前から予想される通りのものでした)』で気付いたことなのですが、実はGNURXでも#pragma addressが使えます。とはいえ生成コード上は.setで定義されるだけで、領域の確保は全く行われませんので、予期せぬ領域のオーバーラップを防ぐ為に、リンカスクリプト上で領域だけは確保するようにしておく必要はあります。

    Config_DTC_ELSR18I.c

    #pragma address dtc_vector193 0x0003FF04U
    volatile uint32_t dtc_vector193;
    volatile st_dtc_data_t dtc_transferdata_vector193[2];

    Config_DTC_ELSR18I.lst

      76                                     .comm    _dtc_transferdata_vector193,24,4
      77                                    .set _dtc_vector193, 0x0003ff04

     

Reply
  • ほやさん、シェルティさん、こんにちは。NoMaYです。

    リプライ有難う御座います。私が取った(4)の回避策は、回避策として不便には成らないようにしたかったという思惑を反映しています。リンカスクリプトの該当箇所を書き換える策は、コード生成時に元に戻ってしまうのです。(なお(B-1)のmcu_interrupt.cとvecttbl.cを書き換える策は、スマートコンフィグレータのデフォルト設定では生成済みFITモジュールは書き換えても元には戻らないこと(生成済みFITモジュールは再生成しないというデフォルト設定)を利用しています。)

    それはそれとして、ほやさんのリプライを見て、そういえば何か変なような?と思ったことがあったので、調べてみました。

    > ソースを見た限りでは初期値はない
    そもそも初期値がないのにMOTファイルにレコードが出ていたのは何故なのだろう?

    気付いたことは、__attribute__ ((section ("セクション名"))) とした場合、Cソース上で初期値無しでもGNURXコンパイラが初期値0でコードを生成していた、ということです。例えば、以下の青文字の記述部分と赤文字の記述部分で、それぞれ生成コードを比較することで違いが分かります。

    Config_DTC_ELSR18I.c

    volatile uint32_t dtc_vector193 __attribute__ ((section (".dtc_vector193")));
    volatile st_dtc_data_t dtc_transferdata_vector193[2];

    Config_DTC_ELSR18I.lst

      76                                    .comm   _dtc_transferdata_vector193,24,4
      77                                    .global _dtc_vector193
      78                                    .section    .dtc_vector193,"aw",@progbits
      79                                    .balign 4
      82                                _dtc_vector193:
      83 0000 00 00 00 00                   .zero   4

    それに対して、CC-RXでは、#pragma addressでアドレス指定した場合、Cソース上で初期値無しなら初期値無しでコードが生成されていた、ことにも気付きました。

    Config_DTC_ELSR18I.c

    #pragma address dtc_vector193=0x0003FF04U
    volatile uint32_t dtc_vector193;
    volatile st_dtc_data_t dtc_transferdata_vector193[2];

    Config_DTC_ELSR18I.lst

                                            .SECTION    B,DATA,ALIGN=4
    00000000                         _dtc_transferdata_vector193:
    00000000(00000018H)                     .blkl   6
                                            .SECTION    $ADDR_B_3FF04,DATA
                                     
    0003FF04                                .ORG        3FF04H
    0003FF04                         _dtc_vector193:
    0003FF04(00000004H)                     .blkb   4

    ちなみに別スレッド『GNURX用のCCRXmachine.hとCCRXmachine.cというソースがe2 studioフォルダにありました(内容は概ね名前から予想される通りのものでした)』で気付いたことなのですが、実はGNURXでも#pragma addressが使えます。とはいえ生成コード上は.setで定義されるだけで、領域の確保は全く行われませんので、予期せぬ領域のオーバーラップを防ぐ為に、リンカスクリプト上で領域だけは確保するようにしておく必要はあります。

    Config_DTC_ELSR18I.c

    #pragma address dtc_vector193 0x0003FF04U
    volatile uint32_t dtc_vector193;
    volatile st_dtc_data_t dtc_transferdata_vector193[2];

    Config_DTC_ELSR18I.lst

      76                                     .comm    _dtc_transferdata_vector193,24,4
      77                                    .set _dtc_vector193, 0x0003ff04

     

Children
  • NoMaY さん
    ほや です。

    > リンカスクリプトの該当箇所を書き換える策は、コード生成時に元に戻ってしまうのです。
    そうだろうとは思いましたが...

    コード生成時に元に戻ると言う事は、やはりSmart Configuratorがスクリプトも吐いてるんですかね。

    > 予期せぬ領域のオーバーラップを防ぐ為に、リンカスクリプト上で領域だけは確保するようにしておく必要はあります。
    リンカスクリプトにKEEPが付いているのも、そういう意図だと解釈します。

    > そもそも初期値がないのにMOTファイルにレコードが出ていたのは何故なのだろう?
    KEEPで消えなくしたからか、ATで書込みアドレスをわざわざ指定してしまったためか(同じアドレスなら指定不要)、そのどちらかだと思います。