こんにちは。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_PACKtypedef 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.htmlcpprefjp.github.io/lang/cpp11/pragma_operator.htmlGoogle検索: _Pragma[補足]gcc-renesas.comのドキュメントには記載無いがGCC本家のドキュメントの#pragma pack(1) / #pragma pack()が使えました。(実はiodefine.hでも使われていました。)GNURXgcc-renesas.com/migration-guides/rx/index.html#Compiler_directivesGCC本家gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Structure_002dPacking-Pragmas.html#Structure_002dPacking-Pragmas
こんにちは。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")));など