Я надеюсь, что у кого-то может быть представление о том, как контролировать / определять порядок расширения макросов. Вот контекст:
// 32 bit increments, processor has registers for set, clear and invert
#define CLR_OFF 1
#define SET_OFF 2
#define INV_OFF 3
#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits
//Now if I use this I can do it quite nicely with
#define STATUS_LED 0x0040;
SET(LATB, STATUS_LED); // LATB is port of the LED.
В последнее время мне пришлось немного переставить аппаратное обеспечение, поэтому я решил сгруппировать информацию о LATB с помощью STATUS_LED примерно так ...
#define STATUS_LED_PORT LATB
#define STATUS_LED_MASK 0x0040;
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK
//And I try to use it via
SET( STATUS_LED );
Но, увы, LATB, 0x0040 передается в аргумент 1 макроса SET. Когда этот метод не используется в качестве макроса, он работает правильно:
inline void SET(u32_t *reg, u32_t bits) { ((volatile u32_t *) (((u32_t)reg) + SET_OFF*4 )) = bits; }
//Change the STATUS_LED macro to
#define STATUS_LED &STATUS_LED_PORT, STATUS_LED_MASK
SET( STATUS_LED); //Works great!
Но, к сожалению, мой компилятор не видит необходимости встроить функцию и заставляет 6 инструкций установить регистр, а не 4, поэтому для использования во время битового разбивки это непредсказуемо.
Я надеюсь, что кто-то может знать, как сначала расширить макрос STATUS_LED, что-то вроде:
SET( ##STATUS_LED )
В настоящее время мое решение двигаться дальше - иметь два макроса SET и SETRM (установить регистр, маску), но я чувствую, что должно быть решение, потому что код для SET выглядит следующим образом ...
#define SETRM(reg,bits) ...
#define SET(args) SETRM(args) //WHY WOULD THIS GET EXPANDED HERE??
И, наконец, компилятор моего процессора не поддерживает n-аргументов макроса, я думал, что смогу поиграть с этим, но увы: (.
Большое спасибо за ваше время, и я был бы признателен за любые мысли, я могу двигаться вперед, но было бы намного чище, если бы я мог просто использовать SET везде.