是否可以创建预处理器函数,以便定义多个其他预处理器宏?
我正在使用微控制器框架,需要制作一些宏才能使通用中断处理程序正常运行:
<MODULE_NAME>_IRQ_PIN //ex: PORTB_PIN(0)
<MODULE_NAME>_IRQ_IN_REGISTER //ex: GPIO_PBIN
<MODULE_NAME>_IRQ_NUMBER //ex: GPIO_IRQA
<MODULE_NAME>_IRQ_INTCFG_REG //ex: GPIO_INTCFGA
我试图从实现的角度来看这个过程更通用,更容易。这些宏中大约有十个需要定义,但是当给定1)端口名称2)引脚号和3)IRQ名称时,它们的定义都可以导出。我希望然后创建一个预处理器函数,它将导致生成所有这些宏。类似的东西:
#define MAKE_INTERRUPT_MACROS(module, port, pin, irq_num) \
#define module##_IRQ_pin PORT##port##_PIN(##pin##) \
#define module##_IRQ_IN_REGISTER GPIO_P##port##IN \
#define module##_IRQ_NUMBER GPIO_IRQ##irq_num \
#define module##_IRQ_INTCFG_REG GPIO_INTCFG##irq_num
是否有合法的方法让预处理器执行上述操作,其中单个预处理器函数会根据传递给函数的参数生成多个其他宏?
答案 0 :(得分:1)
我认为这种经典方案可以解决您的问题。这是一种简单明了的方法:
#ifdef CPU_X
#define IRQ_PIN 0
#define IRQ_IN_REGISTER 3
#define IRQ_NUMBER 11
#define IRQ_INTCFG_REG 12
#endif
#ifdef CPU_YY
#define IRQ_PIN PORTB_PIN(1)
#define IRQ_IN_REGISTER GPIO_PBIN(6)
#define IRQ_NUMBER GPIO_IRQA(9)
#define IRQ_INTCFG_REG GPIO_INTCFGA(0xA)
#endif
#ifdef CPU_KK
/* .
. Another CPU
.
*/
#endif
#ifdef CPU_K2
/* .
. Another CPU
.
*/
#endif
您可以使用-D CPU_xx编译指定CPU的代码,并解决问题!
我假设您可能有其他一些宏(E.G。:GPIO_IRQA(9)),而在CPU_YY中我已经使用过它,但它也可能用于其他CPU。
答案 1 :(得分:0)
如果您可以使用C ++而不是C,请查看使用类,每个CPU类型一个,并简单地使用类中的常量和接口。然后,你甚至不关心它们是不同的,只需使用相同的名称来访问它们(区分是根据实例化的类完成的。
如果你真的必须使用C(例如编写设备驱动程序),你可以使用方法设备驱动程序编写者使用(所有版本的* nix,VxWorks,PSOS,QNX和大多数旧的DEC OS使用这种方法,不了解Windows):只需构建一个结构,其中包含操作硬件所需的值和任何函数(或其他任何内容)。为每个硬件(或在您的情况下,模块)类型创建此结构的一个实例。然后间接通过结构。
示例:
struct module_wrapper {
const char *module_name;
int irq_pin;
int irq_register;
int irq_number;
int irq_intcfg_reg;
int (*init_fcn)(void);
int (*reg_access)(int register_number);
int (*open)(void);
int (*close)(void);
int (*read)(char *dst_buffer, int len);
int (*write)(const char *src_buffer, int len);
};
module_wrapper portB = { /* initialize here */ };
module_wrapper gpio = { /* initialize here */ };
printf("GPIO pin %d\n", gpio.irq_pin);
显然,根据需要进行修改。您还可以使用返回值的函数替换常量变量。
答案 2 :(得分:0)
您无法使用宏定义其他宏,但您可以通过完全相反的方式实现类似的功能。
您可以为每个可能的模块自动生成具有以下块的文件:
#ifdef <MODULE>_IRQ_DATA
#define <MODULE>_IRQ_pin CALL(GET_IRQ_PIN, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_IN_REGISTER CALL(GET_IRQ_IN_REGISTER, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_NUMBER CALL(GET_IRQ_NUMBER, <MODULE>_IRQ_DATA)
#define <MODULE>_IRQ_INTCFG_REG CALL(GET_IRQ_INTCFG_REG, <MODULE>_IRQ_DATA)
#endif
然后:
#define CALL(MACRO, ...) MACRO(__VA_ARGS__)
#define GET_IRQ_PIN(port, pin, irq_num) PORT##port##_PIN(pin)
#define GET_IRQ_IN_REGISTER(port, pin, irq_num) GPIO_P##port##IN
#define GET_IRQ_NUMBER(port, pin, irq_num) GPIO_IRQ##irq_num
#define GET_IRQ_INTCFG_REG(port, pin, irq_num) GPIO_INTCFG##irq_num
(根据定义的使用方式,您可以删除#ifdef-#endif -pairs,例如,如果所有这些都必须/可以始终定义的话)
然后实际定义所需的值只需:
#define <MODULE>_IRQ_DATA B,0,A