c - GCC fails(?) to expand complex macro -
the following jumble of macros compiles correctly under visual studio , keil arm compiler, failing gcc arm 6.3.1:
#define drv_acfgcal_reg_index(regulator_name,register_num) ((acfg_cfg##register_num##_en##regulator_name##_lsb+3)/4 + ((register_num-2)*8)) #define drv_acfgcal_reset_index(reset_name,reg_offset) ((acfg_cfg##reg_offset##_r##reset_name##_lsb)+((reg_offset-1)*32)) #define drv_acfgcal_info(rst,rst_reg,idx,docx,regi,vtr,pdcal) \ { \ 0 ,\ 0 ,\ idx##_acfg_idx ,\ docx##_word_count ,\ drv_acfgcal_reset_index(rst,rst_reg) ,\ drv_acfgcal_reg_index(rst,##regi##) ,\ docx##_##vtr##_lsb ,\ docx##_##vtr##_offset ,\ docx##_##pdcal##_vtrcal_mask ,\ docx##_##pdcal##_vtrcal_reset_value ,\ } #define drv_acfgcal_infon(rst,rst_reg,idx,docx,regi,vtr,pdcal) \ { \ 0 ,\ 0 ,\ idx##_acfg_idx ,\ docx##_word_count ,\ drv_acfgcal_reset_index(rst,rst_reg) ,\ drv_acfgcal_reg_index(rst,##regi##) ,\ 0 ,\ 0 ,\ 0 ,\ 0 ,\ } /* blocks reset bits don't have regulator bits. deal creating bogus values * can used identify blocks in code. */ #define acfg_cfgnone_endac01_lsb (none_index*4) #define acfg_cfgnone_endac23_lsb (none_index*4) #define acfg_cfgnone_endac45_lsb (none_index*4) #define acfg_cfgnone_enrefcal_lsb (none_index*4) #define acfg_cfgnone_entestadc_lsb (none_index*4) #define acfg_none_ennone_lsb 7 #define acfg_none_ennone_offset 2 #define acfg_none_endac01_lsb acfg_none_ennone_lsb #define acfg_none_endac01_offset acfg_none_ennone_offset #define acfg_none_endac23_lsb acfg_none_ennone_lsb #define acfg_none_endac23_offset acfg_none_ennone_offset #define acfg_none_endac45_lsb acfg_none_ennone_lsb #define acfg_none_endac45_offset acfg_none_ennone_offset #define acfg_none_enrefcal_lsb acfg_none_ennone_lsb #define acfg_none_enrefcal_offset acfg_none_ennone_offset #define acfg_none_entestadc_lsb acfg_none_ennone_lsb #define acfg_none_entestadc_offset acfg_none_ennone_offset #define none (2) #define none_index (63) #define acfg_info_addr(block) ((g_drv_acfg_info[block].m_index << 4) | first_acfg_base_addr) #define dac01_acfg_idx 1 #define dac_word_count 5 #define acfg_cfg1_rdac01_lsb 0 #define dac_testa_t_vtr_lsb 1 #define dac_testa_t_vtr_offset 1 #define dac_pdcal_vtrcal_mask 0xf #define dac_pdcal_vtrcal_reset_value 0 typedef struct { unsigned m_benabled : 1; unsigned m_caled : 1; /**< 0 until calibration occurs. after being set, cal not occur again */ unsigned m_index : 9; /**< base index of hardware block */ unsigned m_count : 5; /**< number of registers in hardware block */ unsigned m_resetidx : 6; /**< bit index (0-63) reset block sits*/ unsigned m_regulatoridx : 6; /**< group of 3 controls regulator block, 63 none*/ unsigned m_vtrlsb : 4; /**< left bit shifts testa register of block place vtr on diaga */ unsigned m_vtroffset : 4; /**< offset base address of block register containing bit vtr on diaga */ unsigned m_vtrmask : 8; /**< mask of calcode register given block */ unsigned m_vtrcache : 7; /**< starting calcode given block */ } drv_acfg_info_t; drv_acfg_info_t g_drv_acfg_info[] = { /* rst rst idx docx acfg vtr on cal * name reg# name name reg# diaga name regname function * ------ ------ -------- -------- ----- ----------------- ------ ----- */ drv_acfgcal_info (dac01,1,dac01,dac,none,testa_t_vtr,pdcal), //acfg_blk_dac01, };
there appears issue preprocessor not expanding things, hinted @ errors:
output/gcc_cortex_m3/simple/objs/main.c.o : + tests/simple/main.c "c:/usr/gcc_arm/6_2017-q2-update"/bin/arm-none-eabi-gcc.exe -j"c:/usr/gcc_arm/6_2017-q2-update"/arm-none-eabi/include -md -mf output/gcc_cortex_m3/simple/objs/main.c.d -e -j"c:/usr/gcc_arm/6_2017-q2-update"/arm-none-eabi/include -i. -d__microlib -include gcc_preinclude.h -e -dsi4790 -o3 -os -g -d_debug --no-exceptions -mthumb -mcpu=cortex-m3 -c -o output/gcc_cortex_m3/simple/objs/main.c.o tests/simple/main.c tests/simple/main.c:17:87: error: pasting "," , "none" not give valid preprocessing token drv_acfgcal_reg_index(rst,##regi##) ,\ ^ tests/simple/main.c:91:5: note: in expansion of macro 'drv_acfgcal_info' drv_acfgcal_info (dac01,1,dac01,dac,none,testa_t_vtr,pdcal), //acfg_blk_dac01, ^~~~~~~~~~~~~~~~ tests/simple/main.c:91:41: error: pasting "none" , ")" not give valid preprocessing token drv_acfgcal_info (dac01,1,dac01,dac,none,testa_t_vtr,pdcal), //acfg_blk_dac01, ^ tests/simple/main.c:17:90: note: in definition of macro 'drv_acfgcal_info' drv_acfgcal_reg_index(rst,##regi##) ,\ ^~~~ make: *** [output/gcc_cortex_m3/simple/objs/main.c.o] error 1
i apologize amazing amount of stuff crammed together, we're working in embedded environment need take auto-generated header files registers without regular layout (or naming conventions) , try make out of them. end sort of crazyness on trying make hardware sane.
i need find way 'make work' under gcc. clues i'm doing wrong? need massage macros (and how?) or need prod gcc looking @ them differently?
the answer compilers more lenient in pre-processor can use ##
operator.
visual studio , keil arm compiler allow pasted together; gcc paste 'preprocessor tokens' (which don't include ,
or .
or )
;do websearch on preprocessor tokens
find better reference can provide).
the takeaway lesson is: if crazy macro abuse, expect gcc pickier , potentially break want do.
Comments
Post a Comment