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
 

Parents
  • こんにちは。NoMaYです。

    幸い、今回のGNURXの件は再検討して貰えることになりました。また、可能性として昔の投稿で一言だけ書いたGNU ld側で対処する手も当時よりは現実味が増したかも知れないかも、とも思うようになりました。(堅実さという点では、この対処が一番だとは思っているのですけれども、難易度が予想出来ないです。) 他方で、私の考えに思い浮かんだ案は、難易度は高くないのと、別スレッドで話題にしているRXスマートコンフィグレータの多重割り込み対応を改善しようとする時には思い浮かんだ案とちょうど同じ場所を触ることになるだろうという予想もあって、もう少し補足したいと思います。

    1つ前の投稿の以下の件の具体的な箇所は以下の通りです。

    > (3) これらは、FITモジュールであればr_rx_compiler.hのくだんのマクロ定義にて、CGコンポーネントであればr_cg_interrupt_handlers.hへRXスマートコンフィグレータにて、自動的に設定する

    r_rx_compiler.hのくだんのマクロ定義

    現状:

    #elif defined(__GNUC__)

    /* Standard */
    #define R_BSP_PRAGMA_INTERRUPT(function_name, vector)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector)));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vector)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), used));

    #define R_BSP_PRAGMA_INTERRUPT_FUNCTION(function_name)                extern void function_name(void) __attribute__((interrupt));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_FUNCTION(function_name)         static void function_name(void) __attribute__((interrupt, used));

    #define R_BSP_ATTRIB_INTERRUPT                                        extern /* only this one because __attribute__((interrupt)) prevents GNURX from generating vector */
    #define R_BSP_ATTRIB_STATIC_INTERRUPT                                 static /* only this one because __attribute__((interrupt, used)) prevents GNURX from generating vector */

    /* Fast */
    #define R_BSP_PRAGMA_FAST_INTERRUPT(function_name, vector)            extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector))) \
                                                                                                          __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT(function_name, vector)     static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), used)) \
                                                                                                          __attribute__((fast_interrupt, used));

    #define R_BSP_PRAGMA_FAST_INTERRUPT_FUNCTION(function_name)           extern void function_name(void) __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT_FUNCTION(function_name)    static void function_name(void) __attribute__((fast_interrupt, used));

    #define R_BSP_ATTRIB_FAST_INTERRUPT                                   extern /* __attribute__((interrupt(fast))) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_FAST_INTERRUPT() declaration */
    #define R_BSP_ATTRIB_STATIC_FAST_INTERRUPT                            static /* __attribute__((interrupt(fast)), used) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_STATIC_FAST_INTERRUPT() declaration */

    /* Default */
    #define R_BSP_PRAGMA_INTERRUPT_DEFAULT(function_name)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default")));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_DEFAULT(function_name)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default"), used));

     
    変更案: (変更箇所(というか追加箇所)を赤文字にしています)

    #elif defined(__GNUC__)

    /* Standard */
    #define R_BSP_PRAGMA_INTERRUPT(function_name, vector)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name)));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vector)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name), used));

    #define R_BSP_PRAGMA_INTERRUPT_FUNCTION(function_name)                extern void function_name(void) __attribute__((interrupt));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_FUNCTION(function_name)         static void function_name(void) __attribute__((interrupt, used));

    #define R_BSP_ATTRIB_INTERRUPT                                        extern /* only this one because __attribute__((interrupt)) prevents GNURX from generating vector */
    #define R_BSP_ATTRIB_STATIC_INTERRUPT                                 static /* only this one because __attribute__((interrupt, used)) prevents GNURX from generating vector */

    /* Fast */
    #define R_BSP_PRAGMA_FAST_INTERRUPT(function_name, vector)            extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name))) \
                                                                                                          __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT(function_name, vector)     static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name), used)) \
                                                                                                          __attribute__((fast_interrupt, used));

    #define R_BSP_PRAGMA_FAST_INTERRUPT_FUNCTION(function_name)           extern void function_name(void) __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT_FUNCTION(function_name)    static void function_name(void) __attribute__((fast_interrupt, used));

    #define R_BSP_ATTRIB_FAST_INTERRUPT                                   extern /* __attribute__((interrupt(fast))) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_FAST_INTERRUPT() declaration */
    #define R_BSP_ATTRIB_STATIC_FAST_INTERRUPT                            static /* __attribute__((interrupt(fast)), used) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_STATIC_FAST_INTERRUPT() declaration */

    /* Default */
    #define R_BSP_PRAGMA_INTERRUPT_DEFAULT(function_name)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default"), section(".isrtext." #function_name)));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_DEFAULT(function_name)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default"), section(".isrtext." #function_name), used));

     
    r_cg_interrupt_handlers.hの一例

    現状:

    /* RIIC0 RXI0 */
    void r_Config_RIIC0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,RXI0))));

    /* RIIC0 TXI0 */
    void r_Config_RIIC0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,TXI0))));

    /* SCI0 RXI0 */
    void r_Config_SCI0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,RXI0))));

    /* SCI0 TXI0 */
    void r_Config_SCI0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,TXI0))));

    など

     
    変更案: (変更箇所(というか追加箇所)を赤文字にしています)

    /* RIIC0 RXI0 */
    void r_Config_RIIC0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,RXI0)), section(".isrtext.r_Config_RIIC0_receive_interrupt")));

    /* RIIC0 TXI0 */
    void r_Config_RIIC0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,TXI0)), section(".isrtext.r_Config_RIIC0_transmit_interrupt")));

    /* SCI0 RXI0 */
    void r_Config_SCI0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,RXI0)), section(".isrtext.r_Config_SCI0_receive_interrupt")));

    /* SCI0 TXI0 */
    void r_Config_SCI0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,TXI0)), section(".isrtext.r_Config_SCI0_transmit_interrupt")));

    など

     

Reply
  • こんにちは。NoMaYです。

    幸い、今回のGNURXの件は再検討して貰えることになりました。また、可能性として昔の投稿で一言だけ書いたGNU ld側で対処する手も当時よりは現実味が増したかも知れないかも、とも思うようになりました。(堅実さという点では、この対処が一番だとは思っているのですけれども、難易度が予想出来ないです。) 他方で、私の考えに思い浮かんだ案は、難易度は高くないのと、別スレッドで話題にしているRXスマートコンフィグレータの多重割り込み対応を改善しようとする時には思い浮かんだ案とちょうど同じ場所を触ることになるだろうという予想もあって、もう少し補足したいと思います。

    1つ前の投稿の以下の件の具体的な箇所は以下の通りです。

    > (3) これらは、FITモジュールであればr_rx_compiler.hのくだんのマクロ定義にて、CGコンポーネントであればr_cg_interrupt_handlers.hへRXスマートコンフィグレータにて、自動的に設定する

    r_rx_compiler.hのくだんのマクロ定義

    現状:

    #elif defined(__GNUC__)

    /* Standard */
    #define R_BSP_PRAGMA_INTERRUPT(function_name, vector)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector)));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vector)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), used));

    #define R_BSP_PRAGMA_INTERRUPT_FUNCTION(function_name)                extern void function_name(void) __attribute__((interrupt));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_FUNCTION(function_name)         static void function_name(void) __attribute__((interrupt, used));

    #define R_BSP_ATTRIB_INTERRUPT                                        extern /* only this one because __attribute__((interrupt)) prevents GNURX from generating vector */
    #define R_BSP_ATTRIB_STATIC_INTERRUPT                                 static /* only this one because __attribute__((interrupt, used)) prevents GNURX from generating vector */

    /* Fast */
    #define R_BSP_PRAGMA_FAST_INTERRUPT(function_name, vector)            extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector))) \
                                                                                                          __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT(function_name, vector)     static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), used)) \
                                                                                                          __attribute__((fast_interrupt, used));

    #define R_BSP_PRAGMA_FAST_INTERRUPT_FUNCTION(function_name)           extern void function_name(void) __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT_FUNCTION(function_name)    static void function_name(void) __attribute__((fast_interrupt, used));

    #define R_BSP_ATTRIB_FAST_INTERRUPT                                   extern /* __attribute__((interrupt(fast))) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_FAST_INTERRUPT() declaration */
    #define R_BSP_ATTRIB_STATIC_FAST_INTERRUPT                            static /* __attribute__((interrupt(fast)), used) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_STATIC_FAST_INTERRUPT() declaration */

    /* Default */
    #define R_BSP_PRAGMA_INTERRUPT_DEFAULT(function_name)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default")));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_DEFAULT(function_name)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default"), used));

     
    変更案: (変更箇所(というか追加箇所)を赤文字にしています)

    #elif defined(__GNUC__)

    /* Standard */
    #define R_BSP_PRAGMA_INTERRUPT(function_name, vector)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name)));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT(function_name, vector)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name), used));

    #define R_BSP_PRAGMA_INTERRUPT_FUNCTION(function_name)                extern void function_name(void) __attribute__((interrupt));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_FUNCTION(function_name)         static void function_name(void) __attribute__((interrupt, used));

    #define R_BSP_ATTRIB_INTERRUPT                                        extern /* only this one because __attribute__((interrupt)) prevents GNURX from generating vector */
    #define R_BSP_ATTRIB_STATIC_INTERRUPT                                 static /* only this one because __attribute__((interrupt, used)) prevents GNURX from generating vector */

    /* Fast */
    #define R_BSP_PRAGMA_FAST_INTERRUPT(function_name, vector)            extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name))) \
                                                                                                          __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT(function_name, vector)     static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, vector), section(".isrtext." #function_name), used)) \
                                                                                                          __attribute__((fast_interrupt, used));

    #define R_BSP_PRAGMA_FAST_INTERRUPT_FUNCTION(function_name)           extern void function_name(void) __attribute__((fast_interrupt));
    #define R_BSP_PRAGMA_STATIC_FAST_INTERRUPT_FUNCTION(function_name)    static void function_name(void) __attribute__((fast_interrupt, used));

    #define R_BSP_ATTRIB_FAST_INTERRUPT                                   extern /* __attribute__((interrupt(fast))) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_FAST_INTERRUPT() declaration */
    #define R_BSP_ATTRIB_STATIC_FAST_INTERRUPT                            static /* __attribute__((interrupt(fast)), used) Not necessary,
                                                                                    but Don't forget a R_BSP_PRAGMA_STATIC_FAST_INTERRUPT() declaration */

    /* Default */
    #define R_BSP_PRAGMA_INTERRUPT_DEFAULT(function_name)                 extern void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default"), section(".isrtext." #function_name)));
    #define R_BSP_PRAGMA_STATIC_INTERRUPT_DEFAULT(function_name)          static void function_name(void) __attribute__((interrupt(R_BSP_SECNAME_INTVECTTBL, "$default"), section(".isrtext." #function_name), used));

     
    r_cg_interrupt_handlers.hの一例

    現状:

    /* RIIC0 RXI0 */
    void r_Config_RIIC0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,RXI0))));

    /* RIIC0 TXI0 */
    void r_Config_RIIC0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,TXI0))));

    /* SCI0 RXI0 */
    void r_Config_SCI0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,RXI0))));

    /* SCI0 TXI0 */
    void r_Config_SCI0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,TXI0))));

    など

     
    変更案: (変更箇所(というか追加箇所)を赤文字にしています)

    /* RIIC0 RXI0 */
    void r_Config_RIIC0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,RXI0)), section(".isrtext.r_Config_RIIC0_receive_interrupt")));

    /* RIIC0 TXI0 */
    void r_Config_RIIC0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(RIIC0,TXI0)), section(".isrtext.r_Config_RIIC0_transmit_interrupt")));

    /* SCI0 RXI0 */
    void r_Config_SCI0_receive_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,RXI0)), section(".isrtext.r_Config_SCI0_receive_interrupt")));

    /* SCI0 TXI0 */
    void r_Config_SCI0_transmit_interrupt(void) __attribute__ ((interrupt(".rvectors",VECT(SCI0,TXI0)), section(".isrtext.r_Config_SCI0_transmit_interrupt")));

    など

     

Children
No Data