I am working with an STM32F1 microcontroller, for which a header is provided that defines bit masks and values for registers as follows:
#define RCC_CFGR_PLLMULL //Mask of PLL multiplier setting bits
#define RCC_CFGR_PLLMULL1 //Value of PLL multiplier bits for PLL x1
#define RCC_CFGR_PLLMULL2 //Value of PLL multiplier bits for PLL x2
#define RCC_CFGR_PLLMULL3 //Value of PLL multiplier bits for PLL x3
etc etc.
What I want to do is define my PLL multiplier as an integer so I can use it to derive the clock value - ie PLLCLK = IN_CLK * PLL_MULT
- and paste the value onto RCC_CFGR_PLLMULL
to obtain the correct setting bits. The macros I would normally use for this are as follows:
#define APPEND_VAL_HELPER(A, B) A##B
#define APPEND_VAL(A, B) APPEND_VAL_HELPER(A,B)
Then if I define SOME_NUM as, say, 123:
#define FOO APPEND_VAL(BAR, SOME_NUM)
Results in the FOO
defining as BAR123
. Normally this works. Here's the problem: in this case, RCC_CFGR_PLLMULL
is a valid token before being pasted. This results in it expanding in the invocation of APPEND_VAL
and I get something like ((uint32_t)0x003C0000)123
. I can't figure out how to get B
to expand without also expanding A
, at least in GCC. There are workarounds to this but I'm looking for a clean solution. Does it exist?
I'm not sure what you would consider a "clean" solution, but this works for me and doesn't seem too bad:
/* target header */
#define RCC_CFGR_PLLMULL 0x003C
#define RCC_CFGR_PLLMULL1 0x0003
/* pasting macros */
#define APPEND_VAL_HELPER(A, B) A ## B
#define APPEND_VAL(A, B) APPEND_VAL_HELPER(A, B)
#define RCC_CFGR(T, N) APPEND_VAL(RCC_CFGR_, APPEND_VAL(T, N))
You use that as, for example,
#define FOO RCC_CFGR(PLLMUL, 1)
You can also do
#define BAR RCC_CFGR(PLLMUL, )
to define BAR
to RCC_CFGR_PLLMUL
(no tail).
Obviously, this is specific to a subset of possible target macros, but it does the job and reads cleanly. To the best of my knowledge there is no way to write a fully general token-pasting macro -- those that are most general suffer from issues such as the one you described.