CC-RXもGNURXもC99仕様では_Pragmaプリプロセッサ演算子というものが使えるのですね(FITのコンパイラ対応の効率化に役立ちそうかも)

こんにちは。NoMaYです。

別スレッド『Amazon FreeRTOSだそうです。ルネサスさんのRXは参加しないのかな?』でCC-RX用プロジェクトをGNURX用プロジェクトへ移植する作業をぽつりぽつりとやっていて、CC-RXの#pragma pack / #pragma packoption相当のものとしてGNURXで#pragma pack(1) / #pragma pack()が使えることに気付いたのですが、たまたま同じタイミングで更に別スレッドの作業をやっていてGNURXで#pragma address 変数名 アドレスという記述が使えるらしいことに気付き、調べているうちにFITが前提としているC99仕様では_Pragmaプリプロセッサ演算子(関連リンク参照)というものが使えることを知りました。_Pragmaを使うと以下のように#pragmaをプリプロセッサで扱うことが出来るようになり、FITのコンパイラ対応の効率化に役立ちそうかも知れないと思いました。

#define R_PRAGMA(...) _Pragma(#__VA_ARGS__)

#if defined(__CCRX__)

#define R_PRAGMA_PACK       R_PRAGMA(pack)
#define R_PRAGMA_PACKOPTION R_PRAGMA(packoption)

#elif defined(__GNUC__)

#define R_PRAGMA_PACK       R_PRAGMA(pack(1))
#define R_PRAGMA_PACKOPTION R_PRAGMA(pack())

#endif
/*
 * EDMAC descriptor as defined in the hardware manual. It is
 * modified to support little endian CPU mode.
 */
    R_PRAGMA_PACK

typedef struct DescriptorS
{
    __evenaccess uint32_t           status;
    #if __LIT
    /* Little endian */
    __evenaccess uint16_t           size;
    __evenaccess uint16_t           bufsize;
    #else
    /* Big endian */
    __evenaccess uint16_t bufsize;
    __evenaccess uint16_t size;

    #endif
    uint8_t            *buf_p;
    struct DescriptorS *next;
} descriptor_t;

/*
 * Ethernet buffer type definition.  
 */
typedef struct EtherBufferS
{
    uint8_t buffer[EMAC_NUM_BUFFERS][ETHER_CFG_BUFSIZE];

} etherbuffer_t;

typedef struct pause_resolutionS
{
    pausemask_t mask;
    pauseval_t  value;
    uint8_t     transmit;
    uint8_t     receive;
} pauseresolution_t;

typedef struct
{
    volatile struct st_etherc __evenaccess * petherc; /* ETHERC module */
    volatile struct st_edmac __evenaccess * pedmac; /* EDMAC */
    volatile uint32_t         __evenaccess * preg_pir;
    uint32_t                  phy_address;
    uint8_t                   port_connect;
} ether_control_t;

typedef struct
{
    const ether_control_t * pether_control;
    uint32_t              phy_access;
} ether_ch_control_t;

    R_PRAGMA_PACKOPTION

[関連リンク]

クローバーフィールド.jp/_pragma演算子を使ってみた。
embedded.cloverfield.jp/2016/04/12/_pragma演算子ではまりました。
infocenter.arm.com/help/topic/com.arm.doc.dui0472ij/BABDIJDD.html
cpprefjp.github.io/lang/cpp11/pragma_operator.html
Google検索: _Pragma

[補足]

gcc-renesas.comのドキュメントには記載無いがGCC本家のドキュメントの#pragma pack(1) / #pragma pack()が使えました。(実はiodefine.hでも使われていました。)

GNURX
gcc-renesas.com/migration-guides/rx/index.html#Compiler_directives

GCC本家
gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Structure_002dPacking-Pragmas.html#Structure_002dPacking-Pragmas
 

  • NoMaYさん

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

    _Pragma 使えそうですね。
    FITの活動ではマルチコンパイラ対応は私も継続して提案しておりました。
    開発リソースと対応優先度の兼ね合いから見送られてきましたが、
    Amazon FreeRTOSの件もあり、対応すべきという機運の高まりを感じます。
    FITのマルチコンパイラ対応を実現するとしたら、CC-RXに加えて、GCCとIARの3点になります。

    _Pragmaを教えていただく前までは、各ソフトにおいてpragmaなりコンパイラ依存のコードがある個所を
    すべてifdefで分岐させるつもりでしたが、この方式でそれが不要になりそうですね。
    IARでも_Pragmaが使えそうなことを確認しました。

    情報提供いただきありがとうございます。
    ちょっとBSP、Ether、CMT、TCP/IPの組み合わせで1コード3コンパイラ対応ができるか
    実験してみようと思います。

    以上です
  • シェルティさん、こんにちは。NoMaYです。

    私は、この後、以前に別スレッド『GUNRX用プロジェクトにFITモジュールを組み込む方法について』に投稿したGNURXの割り込み関数の記述方法を、これと組み合わせてみようかと思っています。(ちなみに、IARコンパイラでCC-RXのような割り込み関数の記述方法、つまり、割り込み関数のアドレスを設定した割り込みベクタの配列を用意する必要が無く、割り込み関数をグローバルにする必要が無い、が出来るかどうか気になるところです。)

  • こんにちは。NoMaYです。

    今度は#pragma inlineについて考えてみました。CC-RXのヘルプを読んでいて気付いたことは、FITが前提としているC99仕様では、以下のようなCC-RXとGNURXに共通なマクロを用意するのが良いのではないかということです。

    #define R_ATTRIB_INLINE        inline extern
    #define R_ATTRIB_STATIC_INLINE inline static
    #define R_PRAGMA_INLINE(function_prototype)        R_ATTRIB_INLINE function_prototype;
    #define R_PRAGMA_STATIC_INLINE(function_prototype) R_ATTRIB_STATIC_INLINE function_prototype;

    そうすれば、以下のようなCC-RXとGNURXで共通な記述に出来ると思います。(ただ、この関数に限りませんが、ファイル間インライン展開される為にはコンパイル時に大域最適化オプション-merge_filesが必要だという点がFITのプログラマの人達に認識されていないような気がします。この件はスレッドを分けようかと思います。[追記] 別スレッド『FITのソースを見ていて気付いたCC-RXの仕様をプログラマが勘違いしている気がするコード』に分けました。)

    例) r_sci_rx.c

    現状

    #pragma inline(R_SCI_GetVersion)
    uint32_t  R_SCI_GetVersion(void)
    {
    uint32_t const version = (SCI_VERSION_MAJOR << 16) | SCI_VERSION_MINOR;

        return version;
    } /* End of function R_SCI_GetVersion() */

    共通化案

    R_PRAGMA_INLINE(uint32_t R_SCI_GetVersion(void))
    uint32_t  R_SCI_GetVersion(void)
    {
    uint32_t const version = (SCI_VERSION_MAJOR << 16) | SCI_VERSION_MINOR;

        return version;
    } /* End of function R_SCI_GetVersion() */

    もしくは

    R_ATTRIB_INLINE
    uint32_t  R_SCI_GetVersion(void)
    {
    uint32_t const version = (SCI_VERSION_MAJOR << 16) | SCI_VERSION_MINOR;

        return version;
    } /* End of function R_SCI_GetVersion() */

    以下のCC-RXのC99仕様のinline指定子に関する赤文字の挙動はGNURXでも同じ(というか常に生成される?)でした。([追記] 念の為に確認したらCC-RXでも常に生成されたので調べてみたら、プロトタイプ宣言があった場合にも生成されるようでした。)

    4.2.4 拡張仕様の使用方法 - CS+ V6.01.00 > コンパイラ編 > コンパイラ言語仕様 > 拡張言語仕様 > 拡張仕様の使用方法
    (4)関数のインライン展開記述
    tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V6.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx04c0204y.html#19230


    今までに投稿した内容を組み込んで、以下のヘッダファイルを作成してみました。

    SCFGcompiler.h

    1207.SCFGcompiler_h_20180708.txt
    #ifndef SCFGCOMPILERS_H
    #define SCFGCOMPILERS_H
    
    /*
    https://gcc-renesas.com/migration-guides/rx/index.html#Compiler_directives
    
    https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/RX-Function-Attributes.html
    
    https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
    */
    
    #if defined(__CCRX__)
        /* supported */
    #elif defined(__GNUC__)
        /* supported */
    #else
        #error "Unrecognized compiler"
    #endif
    
    #define R_PRAGMA(...) _Pragma(#__VA_ARGS__)
    
    #if defined(__CCRX__)
    
    #define R_PRAGMA_PACK       R_PRAGMA(pack)
    #define R_PRAGMA_PACKOPTION R_PRAGMA(packoption)
    
    #elif defined(__GNUC__)
    
    #define R_PRAGMA_PACK       R_PRAGMA(pack(1))
    #define R_PRAGMA_PACKOPTION R_PRAGMA(pack())
    
    #endif
    
    #if defined(__CCRX__)
    
    #define R_PRAGMA_INTERRUPT(function_name, vector)           R_PRAGMA(interrupt function_name(vect=vector))\
    extern void function_name(void);
    #define R_PRAGMA_STATIC_INTERRUPT(function_name, vector)    R_PRAGMA(interrupt function_name(vect=vector))\
    static void function_name(void);
    
    //TODO: fast interrupt
    
    #elif defined(__GNUC__)
    
    #define R_PRAGMA_INTERRUPT(function_name, vector)           extern void function_name(void) __attribute__((interrupt(".rvectors", vector)));
    #define R_PRAGMA_STATIC_INTERRUPT(function_name, vector)    static void function_name(void) __attribute__((interrupt(".rvectors", vector), used));
    
    //TODO: fast interrupt
    
    #endif
    
    #define R_ATTRIB_INLINE        inline extern
    #define R_ATTRIB_STATIC_INLINE inline static
    #define R_PRAGMA_INLINE(function_prototype)        R_ATTRIB_INLINE function_prototype;
    #define R_PRAGMA_STATIC_INLINE(function_prototype) R_ATTRIB_STATIC_INLINE function_prototype;
    
    #if defined(__CCRX__)
    
        /* nothing to do */
    
    #elif defined(__GNUC__)
    
    #define __evenaccess /* none */
    
    #endif
    
    /*
    https://gcc-renesas.com/migration-guides/rx/index.html#Compiler_predefined
    */
    
    #if defined(__CCRX__)
    
        /* maybe nothing to do */
    
    #elif defined(__GNUC__)
    
    #define __RX 1
    
    #if defined(__RX_LITTLE_ENDIAN__)
    #define __LIT 1
    #endif
    
    #if defined(__RX_BIG_ENDIAN__)
    #define __BIG 1
    #endif
    
    #endif
    
    #endif /* SCFGCOMPILERS_H */
    

     

  • こんにちは。NoMaYです。

    今度は#pragma bit_orderについて考えてみました。FITのソースには以下のような記述があります。残念ながらGNURXに(というかGCC本家にも)相当する機能はありませんでした。そこで、この#pragma単体ではなく、着目するソース範囲を少し広げて、マクロを考えてみました。

    例) r_flash_rx65n.h

    現状

    #pragma bit_order left
    #pragma unpack
    typedef union
    {
        unsigned long LONG;
        struct {
            unsigned long BTFLG:1;
            unsigned long :3;
            unsigned long FAWE:12;
            unsigned long FSPR:1;
            unsigned long :3;
            unsigned long FAWS:12;
        } BIT;
    } fawreg_t;
    #pragma bit_order
    #pragma packoption

    共通化案

    R_PRAGMA_UNPACK
    typedef union
    {
        unsigned long LONG;
        R_BITFIELD_BIT_ORDER_LEFT_6(
            unsigned long BTFLG:1,
            unsigned long :3,
            unsigned long FAWE:12,
            unsigned long FSPR:1,
            unsigned long :3,
            unsigned long FAWS:12
        ) BIT;
    } fawreg_t;
    R_PRAGMA_PACKOPTION

    考えたマクロ

    #if defined(__CCRX__)


    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
        };\
    R_PRAGMA(bit_order)\
    }


    #elif defined(__GNUC__)

    #if defined(__RX_LITTLE_ENDIAN__)

    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }

    #else

    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
    }

    #endif

    #endif

    なお、#pragma bit_orderの仕様は以下の通りです。

    4.2.4 拡張仕様の使用方法 - CS+ V6.01.00 > コンパイラ編 > コンパイラ言語仕様 > 拡張言語仕様 > 拡張仕様の使用方法
    (7)ビットフィールド並び順指定
    tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V6.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx04c0204y.html#53130


    ちなみに、今回の例の構造体(というかビットフィールド)の定義はiodefine.hに存在しているのですが、もっと大きな構造体の定義の一部となっており、それを利用する手段はないものかと考えてみたのですが、思い浮かびませんでした、、、

    CC-RX用iodefine.h

    #pragma bit_order left
    #pragma unpack

    typedef struct st_flash {

        union {
            unsigned long LONG;
            struct {
                unsigned long BTFLG:1;
                unsigned long :3;
                unsigned long FAWE:12;
                unsigned long FSPR:1;
                unsigned long :3;
                unsigned long FAWS:12;
            } BIT;
        } FAWMON;

    } st_flash_t;

    #pragma bit_order
    #pragma packoption

    GNURX用iodefine.h

    #pragma pack(4)

    typedef struct st_flash {

        union {
            unsigned long LONG;
            struct {
                
    #ifdef __RX_LITTLE_ENDIAN__
                unsigned long FAWS : 12;
                unsigned long  : 3;
                unsigned long FSPR : 1;
                unsigned long FAWE : 12;
                unsigned long  : 3;
                unsigned long BTFLG : 1;
    #else
                unsigned long BTFLG : 1;
                unsigned long  : 3;
                unsigned long FAWE : 12;
                unsigned long FSPR : 1;
                unsigned long  : 3;
                unsigned long FAWS : 12;
    #endif
            } BIT;
        } FAWMON;

    } st_flash_t;

    #pragma pack()

    以下、前回投稿したヘッダファイルを更新しました。

    SCFGcompiler.h

    7077.SCFGcompiler_h_20180710.txt
    #ifndef SCFGCOMPILERS_H
    #define SCFGCOMPILERS_H
    
    /*
    https://gcc-renesas.com/migration-guides/rx/index.html#Compiler_directives
    
    https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/RX-Function-Attributes.html
    
    https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
    */
    
    #if defined(__CCRX__)
        /* supported */
    #elif defined(__GNUC__)
        /* supported */
    #elif defined(__ICCRX__)
        /* not supported yet */
        #error "IAR RX compiler is not supported yet"
        /* http://netstorage.iar.com/SuppDB/Public/UPDINFO/007248/ew/doc/EWRX_MigratingFromRenesasHEWRX.pdf */
    #else
        #error "Unrecognized compiler"
    #endif
    
    #define R_PRAGMA(...)    _Pragma(#__VA_ARGS__)
    
    #if defined(__CCRX__)
    
    #define R_PRAGMA_PACK          R_PRAGMA(pack)
    #define R_PRAGMA_UNPACK        R_PRAGMA(unpack)
    #define R_PRAGMA_PACKOPTION    R_PRAGMA(packoption)
    
    #elif defined(__GNUC__)
    
    #define R_PRAGMA_PACK          R_PRAGMA(pack(1))
    #define R_PRAGMA_UNPACK        R_PRAGMA(pack(4))
    #define R_PRAGMA_PACKOPTION    R_PRAGMA(pack())
    
    #endif
    
    #if defined(__CCRX__)
    
    #define R_PRAGMA_INTERRUPT(function_name, vector)           R_PRAGMA(interrupt function_name(vect=vector))\
    extern void function_name(void);
    #define R_PRAGMA_STATIC_INTERRUPT(function_name, vector)    R_PRAGMA(interrupt function_name(vect=vector))\
    static void function_name(void);
    
    //TODO: fast interrupt
    //TODO: exception (i.e. without vector)
    //TODO: vector only
    
    #elif defined(__GNUC__)
    
    #define R_PRAGMA_INTERRUPT(function_name, vector)           extern void function_name(void) __attribute__((interrupt(".rvectors", vector)));
    #define R_PRAGMA_STATIC_INTERRUPT(function_name, vector)    static void function_name(void) __attribute__((interrupt(".rvectors", vector), used));
    
    //TODO: fast interrupt
    //TODO: exception (i.e. without vector)
    //TODO: vector only
    
    #endif
    
    //TODO: __attribute__((always_inline)) should be used for GNURX?
    
    #define R_ATTRIB_INLINE        inline extern
    #define R_ATTRIB_STATIC_INLINE inline static
    #define R_PRAGMA_INLINE(function_prototype)           R_ATTRIB_INLINE function_prototype;
    #define R_PRAGMA_STATIC_INLINE(function_prototype)    R_ATTRIB_STATIC_INLINE function_prototype;
    
    #if defined(__CCRX__)
    
    #define R_BITFIELD_BIT_ORDER_LEFT_2(bf1, bf2)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_3(bf1, bf2, bf3)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_4(bf1, bf2, bf3, bf4)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_5(bf1, bf2, bf3, bf4, bf5)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_7(bf1, bf2, bf3, bf4, bf5, bf6, bf7)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
            bf7;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_8(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
            bf7;\
            bf8;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_9(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
            bf7;\
            bf8;\
            bf9;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #elif defined(__GNUC__)
    
    #if defined(__RX_LITTLE_ENDIAN__)
    
    #define R_BITFIELD_BIT_ORDER_LEFT_2(bf1, bf2)\
    struct {\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_3(bf1, bf2, bf3)\
    struct {\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_4(bf1, bf2, bf3, bf4)\
    struct {\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_5(bf1, bf2, bf3, bf4, bf5)\
    struct {\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_7(bf1, bf2, bf3, bf4, bf5, bf6, bf7)\
    struct {\
        bf7;\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_8(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8)\
    struct {\
        bf8;\
        bf7;\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_9(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9)\
    struct {\
        bf9;\
        bf8;\
        bf7;\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #else
    
    #define R_BITFIELD_BIT_ORDER_LEFT_(bf1, bf2)\
    struct {\
        bf1;\
        bf2;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_3(bf1, bf2, bf3)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_4(bf1, bf2, bf3, bf4)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_5(bf1, bf2, bf3, bf4, bf5)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_7(bf1, bf2, bf3, bf4, bf5, bf6, bf7)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
        bf7;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_8(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
        bf7;\
        bf8;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_9(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
        bf7;\
        bf8;\
        bf9;\
    }
    
    #endif
    
    #endif
    
    #if defined(__CCRX__)
    
    /* #define volatile    volatile __evenaccess    |* I guess this is a bad practice, but ... */
    
    #elif defined(__GNUC__)
    
    #define __evenaccess    /* none */
    
    #endif
    
    /*
    https://gcc-renesas.com/migration-guides/rx/index.html#Compiler_predefined
    */
    
    #if defined(__CCRX__)
    
    /* maybe nothing to do */
    
    #elif defined(__GNUC__)
    
    #define __RX 1
    
    #if defined(__RX_LITTLE_ENDIAN__)
    #define __LIT 1
    #else
    #define __BIG 1
    #endif
    
    #endif
    
    #endif /* SCFGCOMPILERS_H */
    

     

  • こんにちは。NoMaYです。

    今度は#pragma sectionについて考えてみました。FITのソースには以下のような記述があります。幸いなことにGNURXにも(というかGCC本家にも)相当する機能があります。とは言え、CC-RXとの構文の違いをどのようにラップしてソースの共通化に使えるマクロにするか悩ましいところがありましたが、以下のマクロを考えてみました。

    例1) r_ether_rx.c

    現状

    /*
     * Receive, transmit descriptors and their buffer.  They are
     * defined with section pragma directives to easily locate them
     * on the memory map.
     */
    #pragma section _RX_DESC
    static descriptor_t rx_descriptors[ETHER_CHANNEL_MAX][ETHER_CFG_EMAC_RX_DESCRIPTORS];
    #pragma section _TX_DESC
    static descriptor_t tx_descriptors[ETHER_CHANNEL_MAX][ETHER_CFG_EMAC_TX_DESCRIPTORS];

    /*
     * As for Ethernet buffer, the size of total buffer which are use for transmission and the reception is secured.
     * The total buffer's size which the value is integrated from  EMAC_NUM_BUFFERS (buffer number) and
     * ETHER_CFG_BUFSIZE (the size of one buffer).
     * The ETHER_CFG_BUFSIZE and EMAC_NUM_BUFFERS are defined by macro in the file "r_ether_private.h".
     * It is sequentially used from the head of the buffer as a receive buffer or a transmission buffer.
     */
    #pragma section _ETHERNET_BUFFERS
    static etherbuffer_t ether_buffers[ETHER_CHANNEL_MAX];

    #pragma section

    共通化案

    /*
     * Receive, transmit descriptors and their buffer.  They are
     * defined with section pragma directives to easily locate them
     * on the memory map.
     */
    R_ATTRIB_SECTION_CHANGE(_RX_DESC)
    static descriptor_t rx_descriptors[ETHER_CHANNEL_MAX][ETHER_CFG_EMAC_RX_DESCRIPTORS];
    R_ATTRIB_SECTION_CHANGE(_TX_DESC)
    static descriptor_t tx_descriptors[ETHER_CHANNEL_MAX][ETHER_CFG_EMAC_TX_DESCRIPTORS];

    /*
     * As for Ethernet buffer, the size of total buffer which are use for transmission and the reception is secured.
     * The total buffer's size which the value is integrated from  EMAC_NUM_BUFFERS (buffer number) and
     * ETHER_CFG_BUFSIZE (the size of one buffer).
     * The ETHER_CFG_BUFSIZE and EMAC_NUM_BUFFERS are defined by macro in the file "r_ether_private.h".
     * It is sequentially used from the head of the buffer as a receive buffer or a transmission buffer.
     */
    R_ATTRIB_SECTION_CHANGE(_ETHERNET_BUFFERS)
    static etherbuffer_t ether_buffers[ETHER_CHANNEL_MAX];

    R_ATTRIB_SECTION_CHANGE_END

    例2) r_flash_type4.c

    現状

    #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)

    static flash_err_t flash_write_faw_reg(fawreg_t faw);

    #if (FLASH_IN_DUAL_BANK_MODE)
    #pragma section FRAM2

    flash_err_t flash_toggle_banksel_reg()
    {
        略
    }

    #endif // FLASH_IN_DUAL_BANK_MODE

    #pragma section FRAM
    #endif // #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)

    flash_err_t get_cmdlk_err(void)
    {
        略
    }



    #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)



    flash_err_t flash_write_faw_reg (fawreg_t   faw)
    {
        略
    }



    #pragma section // end FRAM
    #endif // FLASH_CFG_CODE_FLASH_ENABLE

    共通化案

    #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)

    static flash_err_t flash_write_faw_reg(fawreg_t faw);

    #if (FLASH_IN_DUAL_BANK_MODE)

    R_ATTRIB_SECTION_CHANGE(FRAM2)
    flash_err_t flash_toggle_banksel_reg()
    {
        略
    }

    #endif // FLASH_IN_DUAL_BANK_MODE

    #define FLASH_PE_MODE_SECTION    R_ATTRIB_SECTION_CHANGE(FRAM)
    #define FLASH_SECTION_CHANGE_END R_ATTRIB_SECTION_CHANGE_END

    #else // #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)

    #define FLASH_PE_MODE_SECTION
    #define FLASH_SECTION_CHANGE_END

    #endif // #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)

    FLASH_PE_MODE_SECTION
    flash_err_t get_cmdlk_err(void)
    {
        略
    }



    #if (FLASH_CFG_CODE_FLASH_ENABLE == 1)



    FLASH_PE_MODE_SECTION
    flash_err_t flash_write_faw_reg (fawreg_t   faw)
    {
        略
    }



    FLASH_SECTION_CHANGE_END // end FRAM

    #endif // FLASH_CFG_CODE_FLASH_ENABLE

    考えたマクロ

    #if defined(__CCRX__)

    #define R_ATTRIB_SECTION_CHANGE(section_name)    R_PRAGMA(section section_name)
    #define R_ATTRIB_SECTION_CHANGE_END              R_PRAGMA(section)

    #elif defined(__GNUC__)

    #define R_ATTRIB_SECTION_CHANGE(section_name)    __attribute__((section(#section_name)))
    #define R_ATTRIB_SECTION_CHANGE_END              /* none */

    #endif

    以下、前回投稿したヘッダファイルを更新しました。

    SCFGcompiler.h

    4130.SCFGcompiler_h_20180711.txt
    #ifndef SCFGCOMPILERS_H
    #define SCFGCOMPILERS_H
    
    /*
    https://gcc-renesas.com/migration-guides/rx/index.html#Compiler_directives
    
    https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/RX-Function-Attributes.html
    
    https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
    https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
    */
    
    #if defined(__CCRX__)
        /* supported */
    #elif defined(__GNUC__)
        /* supported */
    #elif defined(__ICCRX__)
        /* not supported yet */
        #error "IAR RX compiler is not supported yet"
        /* http://netstorage.iar.com/SuppDB/Public/UPDINFO/007248/ew/doc/EWRX_MigratingFromRenesasHEWRX.pdf */
    #else
        #error "Unrecognized compiler"
    #endif
    
    #define R_PRAGMA(...)    _Pragma(#__VA_ARGS__)
    
    #if defined(__CCRX__)
    
    #define R_PRAGMA_PACK          R_PRAGMA(pack)
    #define R_PRAGMA_UNPACK        R_PRAGMA(unpack)
    #define R_PRAGMA_PACKOPTION    R_PRAGMA(packoption)
    
    #elif defined(__GNUC__)
    
    #define R_PRAGMA_PACK          R_PRAGMA(pack(1))
    #define R_PRAGMA_UNPACK        R_PRAGMA(pack(4))
    #define R_PRAGMA_PACKOPTION    R_PRAGMA(pack())
    
    #endif
    
    #if defined(__CCRX__)
    
    #define R_PRAGMA_INTERRUPT(function_name, vector)           R_PRAGMA(interrupt function_name(vect=vector))\
    extern void function_name(void);
    #define R_PRAGMA_STATIC_INTERRUPT(function_name, vector)    R_PRAGMA(interrupt function_name(vect=vector))\
    static void function_name(void);
    
    //TODO: fast interrupt
    //TODO: exception (i.e. without vector)
    //TODO: vector only
    
    #elif defined(__GNUC__)
    
    #define R_PRAGMA_INTERRUPT(function_name, vector)           extern void function_name(void) __attribute__((interrupt(".rvectors", vector)));
    #define R_PRAGMA_STATIC_INTERRUPT(function_name, vector)    static void function_name(void) __attribute__((interrupt(".rvectors", vector), used));
    
    //TODO: fast interrupt
    //TODO: exception (i.e. without vector)
    //TODO: vector only
    
    #endif
    
    //TODO: __attribute__((always_inline)) should be used for GNURX?
    
    #define R_ATTRIB_INLINE                               inline extern
    #define R_ATTRIB_STATIC_INLINE                        inline static
    #define R_PRAGMA_INLINE(function_prototype)           R_ATTRIB_INLINE function_prototype;
    #define R_PRAGMA_STATIC_INLINE(function_prototype)    R_ATTRIB_STATIC_INLINE function_prototype;
    
    #if defined(__CCRX__)
    
    #define R_BITFIELD_BIT_ORDER_LEFT_2(bf1, bf2)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_3(bf1, bf2, bf3)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_4(bf1, bf2, bf3, bf4)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_5(bf1, bf2, bf3, bf4, bf5)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_7(bf1, bf2, bf3, bf4, bf5, bf6, bf7)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
            bf7;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_8(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
            bf7;\
            bf8;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_9(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9)\
    struct {\
    R_PRAGMA(bit_order left)\
        struct {\
            bf1;\
            bf2;\
            bf3;\
            bf4;\
            bf5;\
            bf6;\
            bf7;\
            bf8;\
            bf9;\
        };\
    R_PRAGMA(bit_order)\
    }
    
    #elif defined(__GNUC__)
    
    #if defined(__RX_LITTLE_ENDIAN__)
    
    #define R_BITFIELD_BIT_ORDER_LEFT_2(bf1, bf2)\
    struct {\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_3(bf1, bf2, bf3)\
    struct {\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_4(bf1, bf2, bf3, bf4)\
    struct {\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_5(bf1, bf2, bf3, bf4, bf5)\
    struct {\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_7(bf1, bf2, bf3, bf4, bf5, bf6, bf7)\
    struct {\
        bf7;\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_8(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8)\
    struct {\
        bf8;\
        bf7;\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_9(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9)\
    struct {\
        bf9;\
        bf8;\
        bf7;\
        bf6;\
        bf5;\
        bf4;\
        bf3;\
        bf2;\
        bf1;\
    }
    
    #else
    
    #define R_BITFIELD_BIT_ORDER_LEFT_(bf1, bf2)\
    struct {\
        bf1;\
        bf2;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_3(bf1, bf2, bf3)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_4(bf1, bf2, bf3, bf4)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_5(bf1, bf2, bf3, bf4, bf5)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_6(bf1, bf2, bf3, bf4, bf5, bf6)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_7(bf1, bf2, bf3, bf4, bf5, bf6, bf7)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
        bf7;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_8(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
        bf7;\
        bf8;\
    }
    
    #define R_BITFIELD_BIT_ORDER_LEFT_9(bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9)\
    struct {\
        bf1;\
        bf2;\
        bf3;\
        bf4;\
        bf5;\
        bf6;\
        bf7;\
        bf8;\
        bf9;\
    }
    
    #endif
    
    #endif
    
    #if defined(__CCRX__)
    
    #define R_ATTRIB_SECTION_CHANGE(section_name)    R_PRAGMA(section section_name)
    #define R_ATTRIB_SECTION_CHANGE_END              R_PRAGMA(section)
    
    #elif defined(__GNUC__)
    
    #define R_ATTRIB_SECTION_CHANGE(section_name)    __attribute__((section(#section_name)))
    #define R_ATTRIB_SECTION_CHANGE_END              /* none */
    
    #endif
    
    #if defined(__CCRX__)
    
    /* #define volatile    volatile __evenaccess    |* I guess this is a bad practice, but ... */
    
    #elif defined(__GNUC__)
    
    #define __evenaccess    /* none */
    
    #endif
    
    /*
    https://gcc-renesas.com/migration-guides/rx/index.html#Compiler_predefined
    */
    
    #if defined(__CCRX__)
    
    /* maybe nothing to do */
    
    #elif defined(__GNUC__)
    
    #define __RX 1
    
    #if defined(__RX_LITTLE_ENDIAN__)
    #define __LIT 1
    #else
    #define __BIG 1
    #endif
    
    #endif
    
    #endif /* SCFGCOMPILERS_H */
    

     

  • こんにちは。NoMaYです。

    今度はIAR C/C++コンパイラのユーザーズマニュアルを調べてみました。ここまでのところのCC-RXの#pragmaに相当する機能はありました。ただし、変数のセクションの変更に関しては特別な点(以下の表の赤文字)があり、恐らく、セクションの変更に関してはマクロを関数用と変数用の2つのマクロに分ける必要がありそうでした。加えて、関数のセクションの変更に関しては不明な点(同じく以下の表の赤文字)があって、少し気掛かりです。(それでも、試しに後で、今回作成しているヘッダファイルに組み込んでみようかと思います。とは言っても、IAR C/C++コンパイラはインストールしていませんので、ドキュメントだけに頼ったものになりますが、、、)

    C/C++ Development Guide for the Renesas RX Family (どうもFTPサーバーが重いようです)
    ftp.iar.se/WWWfiles/RX/webic/doc/EWRX_DevelopmentGuide.ENU.pdf

    CC-RX  ICCRX (365頁 - C/C++ Development Guide)
    #pragma pack  #pragma pack(1)
    #pragma unpack   #pragma pack(4)
    #pragma pack           #pragma pack()

     

    CC-RX ICCRX (372頁 - C/C++ Development Guide)
    #pragma interrupt FUNCTION_NAME(vect=VECTOR) #pragma vector=VECTOR
    __interrupt void FUNCTION_NAME(void);
    #pragma interrupt FUNCTION_NAME(fint) __fast_interrupt void FUNCTION_NAME(void);

     

    CC-RX ICCRX (354頁 - C/C++ Development Guide)
    #pragma bit_order left #pragma bitfield=reversed_disjoint_types
    #pragma bit_order right #pragma bitfield=disjoint_types
    #pragma bit_order #pragma bitfield=default

     

    CC-RX ICCRX (362頁 - C/C++ Development Guide)
    #pragma section NAME #pragma location="NAME"
    __no_init 変数定義(__no_initというキーワードが必要!)
    #pragma location="NAME"
    関数宣言 (関数定義は?)


    [関連リンク]

    Migration guide from Renesas HEW or e2 studio (どうもFTPサーバーが重いようです)
    ftp.iar.se/WWWfiles/RX/webic/doc/EWRX_MigratingFromRenesas.pdf

    Project migration tools
    www.iar.com/jp/iar-embedded-workbench/project-migration/

    User Guides: IAR Embedded Workbench for Renesas RX
    www.iar.com/support/user-guides/user-guides-iar-embedded-workbench-for-renesas-rx/
     

  • NoMaYさん

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

    いつも貴重な情報ありがとうございます。

    次の3連休に調査いただいた情報をえいやでAmazon FreeRTOSに適用して
    GCCで動くところまで持っていきたいと考えています。
    IARのRXマイコン用のコンパイラも仕入れてきたので、できれば1コード3コンパイラ対応を目指します。
    こちらでは大きな方針を考えて、細かい調整や検証は休み明けに協力会社に実施いただく算段です。

    いつも本当にありがとうございます。

    以上です
  • シェルティさん、こんにちは。NoMaYです。

    次の3連休というと明日からですね。文面から察するところ、作業中ではありますが、私の手元にあるAmazon FreeRTOSのRenesas RXのGNURXの.projectとか.cprojectとか小細工ソースとかFITソースの修正箇所情報とか、commitしておいた方が良さそうですね。今日もう少し作業を進めて、深夜にcommitしておこうかと思います。(もし寝落ちしたら、明日の朝に。^_^;)

  • NoMaYさん

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

    あっ!? 明日から休みでした。言われて気付きました。
    はい、明日から色々試してみようと思っています。
    commitについて、ご連絡ありがとうございます。大変助かります。

    GitHubの renesas-rx の organizationもそろそろ動かそうかなと思うので、
    機を見てNoMaYさんにメンバー申請送っておきます。
    コミュニティと協力して開発できるようなルールにしました。

    以上です
  • こんにちは。NoMaYです。

    現在、FITのBSPモジュールには以下のスレッドへの投稿を発展させた形でCC-RX/GNURX/ICCRX共通化割り込み関数定義マクロが組み込まれていますが、その影響で以下のFITのDTCモジュールのドキュメントに記載されているように、GNURXで未使用の変数/関数を削除するリンク最適化が出来なくなっていることを把握しました。(確かに以前に何かおかしなことがあるかもと感じたことがあった記憶はあるのですが、他のことに気を取られていて、深く追求しなかった記憶があります。) 今回、別スレッドでFreeRTOSのRTOSDemoプログラムを作成する傍ら、対策を考えてみました。(GNU ld側で対処する手もあるとは思いますが、、、) 取り敢えずの応急処置は、リンカスクリプトlinker_script.ldに以下の赤文字箇所を追加することかと思います。ただ、関数の名前の付け方だけに頼るのはトラブルの元だと思いますので、r_rx_compiler.hのマクロを改造して併用する方法を模索中です。

    GUNRX用プロジェクトにFITモジュールを組み込む方法について
    japan.renesasrulz.com/cafe_rene/f/forum5/4860/gunrx-fit/27041#27041

    ●リンカスクリプトlinker_script.ldに以下の赤文字箇所を追加する(他の箇所に関して思うところがあるのは別途)

    src/linker_script.ld

        .text 0xFFC00000: AT(0xFFC00000)
        {
            *(.text)
            KEEP(*(.text.*ISR))
            KEEP(*(.text.*_isr))
            KEEP(*(.text.*_interrupt))
            *(.text.*)
            *(P)
            etext = .;
        } > ROM

    RXファミリ DTCモジュール Firmware Integration Technology
    www.renesas.com/ja-jp/search/keyword-search.html#genre=document&q=r01an1819

    r01an1819jj0350-rx-dtc-dmac2.pdf