2015-05-03 4 views
0

Возможно ли создать препроцессорную функцию, которая будет определять несколько других макросов препроцессора?Можно ли использовать функцию препроцессора для определения нескольких макросов препроцессора?

Я работаю в микро рамках контроллера, который требует несколько макросов, которые будут сделаны для того, чтобы родовой обработчик прерывания для функции:

<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 

Есть ли законный способ получить proprocessor сделать что-то, как выше, где одна функция препроцессора вызывает генерацию множества других макросов на основе параметров, передаваемых в функцию?

+5

Вы не можете использовать '# define' в макро –

+1

HTTP: // EN .wikibooks.org/wiki/C_Programming/Preprocessor # X-Macros – Mat

+3

Нужно ли это все макросы? Вы просто могли бы объявить их как «статические» объекты const. Если определение и инициализация видны в файле заголовка, это должно быть так же хорошо, как макрос. –

ответ

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 и проблему shoudl быть решен!

Я предполагаю, что у вас могут быть другие макросы (E.G .: GPIO_IRQA (9)), а в CPU_YY я использовал его, но он может использоваться и для других процессоров.

+0

Я собирался что-то ответить на этот вкус. Однако я не вижу никаких «#define» в вашем ответе, и, кажется, есть два идентификатора препроцессора для каждой строки. – Gauthier

+0

Я должен исправить, извините! –

+0

@ Gauthier. Большое спасибо за уведомление! (Я должен перестать писать комментарий, когда устал: p) –

0

Если вы можете использовать C++, а не C, посмотрите на использование классов, по одному на тип процессора и просто используйте константы и интерфейсы в классе. Тогда вам даже не важно, что они разные, просто используйте одни и те же имена для доступа к ним (дифференциация выполняется на основе экземпляра класса.

Если вы действительно и действительно должны использовать C (например, писать драйвер устройства), вы можете использовать использование драйверов устройств подхода (все вкусы * nix, VxWorks, PSOS, QNX и большинства старых ОС DEC используют этот подход, не знают о 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); 

Очевидно, что при необходимости. Вы также можете заменить константные переменные функциями, возвращающими значения.

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 
Смежные вопросы