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

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の別スレッドで使用していたものです。)


  • NoMaYさん
    ほや です。こんにちは。

    ひとつだけ。

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

    この対処方法について。

    .dtc_vector193 セクションの中身次第ではあるのですが、無理やりオプションを突っ込まなくてもリンカスクリプトの書き換えで対処できるのではないかと思います(動かしてみたわけではないのでテキトウに言ってますが)。

    • 初期化が必要な変数がない場合 : セクションに NOLOAD を指定する  (→ 領域だけが確保され、値はバイナリに出力されなくなる)
    • 初期値ありの変数が入る場合 : セクションのロードアドレス(ATで指定されているアドレスの方)をROMアドレスに変更する  (→ ROMアドレスの方だけがバイナリに吐かれる)

    ※ リンク先のソースを見た限りでは初期値はないので、前者の方法(NOLOAD指定)を試してみてはいかが。

  • In reply to ほや:

    NoMaYさん、ほやさん

    こんにちは、シェルティです。

    (1)はリンカスクリプト修正します。
    (2)(3)はBSPを修正します。
    (4)はRFPの実装なりを確認し、原因や適切な対策を探っています。何が原因でも直す方向で検討中です。

    ご報告感謝いたします。大変たすかります。

    以上です
  • In reply to シェルティ:

    シェルティ さん
    ほや です。

    (4)の件、ROMではない場所に書こうとしてRFPがエラーを吐いているのであれば、RFPとしては極めて正常な動作をしている事になります。
    (4)も直すべきはリンカスクリプト(Smart Configuratorが出力しているならその元になるリソース)の記述ではないかと考えています。

    オプションが追加できるようにするのは、それはそれで必要なのですけれど。

  • ほやさん、シェルティさん、こんにちは。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

     

  • In reply to NoMaY:

    NoMaY さん
    ほや です。

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

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

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

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

  • ほやさん、シェルティさん、こんにちは。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


     

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