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)の「そもそも初期値がないのにMOTファイルにレコードが出ていたのは何故なのだろう?」の件ですが、Windows上のMinGWというx86向けのGCCの処理系の1つで試してみたところ、MinGWでは.space擬似命令でコードが出力されていましたが、GNUのアセンブラのドキュメントによると、この擬似命令は初期値付きで領域を確保しますので、GCCというのはそういうものである、ということであるように思われます。(なおGNURXでは.zero擬似命令でコードが出力されていました。) なので、RXスマートコンフィグレータを修正する方法としては、ほやさんが指摘されたように、リンカスクリプトでNOLOAD指定をするように修正するのが良さそうな気がします。

    ソース上の記述

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

    gcc (MinGW.org GCC-6.3.0-1)でのリストファイル

      40                        .globl  _dtc_vector193
      41 001e 9090              .section    .dtc_vector193,"w"
      42                        .align 4
      43                    _dtc_vector193:
      44 0000 00000000          .space 4

    rx-elf-gcc (GNURX 2018q3 4.8.4.201803)でのリストファイル

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

     以下、GCCのアセンブラのドキュメントの画面コピーです。

    sourceware.org/binutils/docs/as/Space.html#Space

    .space size , fill
    This directive emits size bytes, each of value fill. Both size and fill are absolute expressions. If the comma and fill are omitted, fill is assumed to be zero.



    sourceware.org/binutils/docs/as/Zero.html#Zero

    .zero size
    This directive emits size 0-valued bytes. size must be an absolute expression.



    ちなみに、GCCのドキュメントを過去に遡って調べたところ、gcc-4.3.6とgcc-4.4.7の間で__attribute__ ((section ("セクション名")))に関して以下の仕様の拡張があったことに気付きましたが、その仕組みは、C言語上は初期値無し変数も結局は0という初期値を持つので初期値無しで領域を確保するのも初期値0で領域を確保するもの結局は区別が付かない、という発想で上に書いたようになっているのかも知れません。

    __attribute__ ((section ("セクション名")))についてのGCCのドキュメントの記載

    gcc-4.3.6以前: 初期値付きグローバル変数にのみ適用出来る

    You may only use the section attribute with a fully initialized global definition


    gcc-4.4.7以後: 初期値付きグローバル変数だけでなく初期値無しグローバル変数にも適用出来る

    You may use the section attribute with initialized or uninitialized global variables


    以下、GCCのドキュメントの画面コピーです。(赤枠は私によるものです。)

    gcc-4.3.6
    gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/Variable-Attributes.html#index-g_t_0040code_007bsection_007d-variable-attribute-2216


    gcc-4.4.7
    gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Variable-Attributes.html#index-g_t_0040code_007bsection_007d-variable-attribute-2316


     

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

    先日の(4)の「そもそも初期値がないのにMOTファイルにレコードが出ていたのは何故なのだろう?」の件ですが、Windows上のMinGWというx86向けのGCCの処理系の1つで試してみたところ、MinGWでは.space擬似命令でコードが出力されていましたが、GNUのアセンブラのドキュメントによると、この擬似命令は初期値付きで領域を確保しますので、GCCというのはそういうものである、ということであるように思われます。(なおGNURXでは.zero擬似命令でコードが出力されていました。) なので、RXスマートコンフィグレータを修正する方法としては、ほやさんが指摘されたように、リンカスクリプトでNOLOAD指定をするように修正するのが良さそうな気がします。

    ソース上の記述

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

    gcc (MinGW.org GCC-6.3.0-1)でのリストファイル

      40                        .globl  _dtc_vector193
      41 001e 9090              .section    .dtc_vector193,"w"
      42                        .align 4
      43                    _dtc_vector193:
      44 0000 00000000          .space 4

    rx-elf-gcc (GNURX 2018q3 4.8.4.201803)でのリストファイル

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

     以下、GCCのアセンブラのドキュメントの画面コピーです。

    sourceware.org/binutils/docs/as/Space.html#Space

    .space size , fill
    This directive emits size bytes, each of value fill. Both size and fill are absolute expressions. If the comma and fill are omitted, fill is assumed to be zero.



    sourceware.org/binutils/docs/as/Zero.html#Zero

    .zero size
    This directive emits size 0-valued bytes. size must be an absolute expression.



    ちなみに、GCCのドキュメントを過去に遡って調べたところ、gcc-4.3.6とgcc-4.4.7の間で__attribute__ ((section ("セクション名")))に関して以下の仕様の拡張があったことに気付きましたが、その仕組みは、C言語上は初期値無し変数も結局は0という初期値を持つので初期値無しで領域を確保するのも初期値0で領域を確保するもの結局は区別が付かない、という発想で上に書いたようになっているのかも知れません。

    __attribute__ ((section ("セクション名")))についてのGCCのドキュメントの記載

    gcc-4.3.6以前: 初期値付きグローバル変数にのみ適用出来る

    You may only use the section attribute with a fully initialized global definition


    gcc-4.4.7以後: 初期値付きグローバル変数だけでなく初期値無しグローバル変数にも適用出来る

    You may use the section attribute with initialized or uninitialized global variables


    以下、GCCのドキュメントの画面コピーです。(赤枠は私によるものです。)

    gcc-4.3.6
    gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/Variable-Attributes.html#index-g_t_0040code_007bsection_007d-variable-attribute-2216


    gcc-4.4.7
    gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Variable-Attributes.html#index-g_t_0040code_007bsection_007d-variable-attribute-2316


     

Children
No Data