PDG2 RX220 watch dogコード

みなさん、こんにちは。

どんと申します。いつもお世話になっております。

PDG2(version 2.08)でRX220のwatch dogのコードを生成すると

bool R_PG_Timer_GetStatus_IWDT(uint16_t* counter_val, bool * undf, bool * ref_err)
{
    uint16_t status;
    bool res;

    res = R_IWDT_Read( &status );

    if(counter_val){ *counter_val = status & 0x3fff; }
    if(undf){ *undf = (status >> 14) & 0x01; } // ここが不正ではないですか?
    if(ref_err){ *ref_err = (status >> 15) & 0x01; } // ここも不正ではないですか?
    return res;
}

と言うコードが出力されるのですが、このコードでは

bool * undf, bool * ref_errというポインタを通した書き込みで

引数が指すメモリエリアにboolサイズ以上の書き込みが起こりませんか?

m(_ _)m

  • (status >> 14) & 0x01 は status のbit14の値

    (status >> 15) & 0x01 は status のbit15の値

    でどちらも & 0x01 があるので、0 or 1 を値として取ります。(この時点は uint16_t 型の値)

    これを bool * 型のポインタ変数が指す bool 型の変数に代入するので、この時点でbool型に変換して1ビットの書き込みとなります。

  • ramothさん、返信ありがとうございます。

    uint16_tのデータがboolのポインタを通して書き込みされる時に、

    32bit分のメモリエリアに返される様な気がするんですが?

    そうですかboolになってますか。

  • オブジェクトへの代入はそのオブジェクトのサイズで行われ、そのオブジェクトのサイズに収まらないビットは捨てられます。

  • アセンブラを出力させてみて、現象が分かりました。

    C89を指定してコンパイルした場合、

    bool のポインタを通した書き込みは MOV.L R2, [R7] のようなコードが出力されていて、

    サイズの指定が L なので、R7レジスタが指すアドレスから4バイト分の書き込みがされるようです。

    C99を指定してコンパイルした場合、

    MOV.B R2, [R7] のようなコードが出力されて、

    サイズの指定が B なので、R7レジスタが指すアドレスから1バイト分の書き込みがされるようです。

    従って、C89を指定してコンパイルした場合には、メモリ破壊が発生し

    プログラムが不正動作することがあるようです。

    この辺のことは、マニュアルに書いてあるのでしょうか?

    全てC言語でプログラムを記述すれば、問題がないのかでしょうか?

    C++とC89の混在ではサイズ違いによる問題がでるのではないでしょうか?

  • C99ではboolが言語仕様に組み込まれてるので_Boolが言語仕様に組み込まれboolが標準ヘッダで定義されているので普通に使えますが、C89の標準にはないため typedef int bool; とかされてるだけだと思います。

  • 下記のアプリケーションノートで HEW 版の CC-RX の C89/C99 の相違点を説明しています。

    CubeSuite+ / CS+ 版 についても言語仕様は同じなのでそのまま適用できるはずです。

    この資料を読めば C99 指定でコンパイルした場合と C89 指定でコンパイルした場合でどのような差異があるのかが判ります。

    RXコンパイラ アプリケーションノート 3-コンパイラ活用ガイド: 言語編 (C89, C99)

    documentation.renesas.com/.../rjj06j0095_rxc_uglgc8999_ap.pdf

  • CC-RX の include/stdbool.h の中で、

     #ifndef __cplusplus
    		/* TYPES */
    
     #if 199901L <= __STDC_VERSION__
    
     #else /* 199901L <= __STDC_VERSION__ */
    typedef unsigned long _Bool;
     #endif /* 199901L <= __STDC_VERSION__ */
    
    		/* MACROS */
     #define bool	_Bool
     #define false	0
     #define true	1
     #endif /* __cplusplus */
    

    としているので、C89 でこのファイルをインクルードしていると bool は unsigned long と同じになります。

  • ramothさん、fujita nozomuさん、返信ありがとうございます。

    いま作っているサンプルプログラムではC++で大半をコーディングし、cubeSuite+のC言語の選択はC89でした。

    PDG2が出力したCのコードをC++から呼び出したため、boolポインタが指すアドレスから

    4バイトの書き込みになり、メモリ破壊によってプログラムが不正な動作をしていました。

    この開発環境が初めてのこともあり、型のサイズは自動で調整してくれているとばかり思っていたため、

    理由が分かるまで時間がかかりました。

    #if defined(__STDC_VERSION__) && 199901L <= __STDC_VERSION__

    #else

    #error C99以降のコンパイラでコンパイルしてください。C89では不正な動作になります

    #endif

    こんな感じのコードを resetprg.c の中に記述して、C89の選択ではコンパイルエラーになるようにしました。

    色々ありがとうございました。これで、スッキリしました。(^^)/