2009-03-24 4 views
0

У меня есть две процедуры обслуживания прерываний (ISR), которые в основном выполняют то же самое , но каждый обрабатывает прерывание с другого устройства (хотя тот же тип устройства). Поэтому логика одна и та же, но они имеют доступ к различным регистрам процессора и ячейкам памяти.Как избежать дублирования кода между аналогичными ISR?

В качестве простого примера рассмотрим следующий код:

extern volatile unsigned int dev1_rx_buffer; 
extern volatile unsigned int dev2_rx_buffer; 

volatile unsigned char data; 

void __attribute__((__interrupt__)) _dev1_interrupt(void) 
{ 
    /* Clear interrupt flag */ 
    dev1.IF = 0; 

    if (dev1.IS_FULL) { 
     /* Read data from device */ 
     data = dev1_rx_buffer; 
    } else { 
     /* do something else using registers of device 1 */ 
    } 
    /* More stuff using registers of device 1 */ 
} 

void __attribute__((__interrupt__)) _dev2_interrupt(void) 
{ 
    /* Clear interrupt flag */ 
    dev2.IF = 0; 

    if (dev2.IS_FULL) { 
     /* Read data from device */ 
     data = dev2_rx_buffer; 
    } else { 
     /* do something else using registers of device 2 */ 
    } 
    /* More stuff using registers of device 2 */ 
} 

Как я могу избежать дублирования кода с ограничениями, которые применяются к ЗРМС (т.е. я не могу передать параметры ЗРМС и вызовы функций следует избегать из-за их накладных расходов).

Я подумал о написании шаблона, из которого можно создать два ISR с использованием языка сценариев более высокого уровня, но я бы предпочел решение, используя только макросы препроцессора C или C.

ответ

2

Почему вы не используете встроенную вспомогательную функцию, которая получает указатели на устройство и буфер?

Я бы проверил сгенерированную сборку, чтобы убедиться, что компилятор делает то, что я ожидаю.

Вы также можете использовать макрос, но IMHO нехорошо это делать для таких функций.

2

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

6

В таких случаях, как правило, передняя часть ISR (точка ввода вектора) настраивает указатель на конкретный блок устройства, а затем вызывает общий код с указателем на этот блок.

Грубо (не заботясь о ISR синтаксиса и т.д.)

void __attribute__((__interrupt__)) Isr1(void) 
{ 
    CommonISR(&dev1info); 
} 

void __attribute__((__interrupt__)) Isr2(void) 
{ 
    CommonISR(&dev2info); 
} 

void CommonISR(Foo *devptr) 
{ 
    devptr->count = 0; 
    devptr->reset(); 
    etc... 
} 

dev1info и dev2info сконфигурированы/инициализируется при запуске; они могут иметь указатели на регистры HW и т. д.

+0

С использованием компилятора я должен был бы объявить CommonISR явным образом, чтобы избежать вызова функции. В противном случае это, вероятно, то, что я буду делать. Благодарю. – davitenio

1

Вы уверены, что ваш компилятор не будет оптимизировать вызовы функций?
Вы, безусловно, можете использовать макросы для создания этого кода автоматически, но это будет немного уродливый:

#define __CONCAT(a,b) a ## b 

#define ISR_DECLARE(name) \ 
\ 
void __attribute__((__interrupt__)) _CONCAT(name,_interrupt)(void) \ 
{ \   
    /* Clear interrupt flag */ \ 
    name.IF = 0; \ 
    \ 
    if (name.IS_FULL) \ 
    { \ 
     /* Read data from device */ \ 
     data = _CONCAT(name, _rx_buffer); \ 
    } \ 
    else \ 
    { \ 
     /* do something else using registers of device 1 */ \ 
    }\ 
    /* More stuff using registers of device 1 */ \ 

}

, а затем:

ISR_DECLARE(dev_1) 

ISR_DECLARE(dev_2) 

Но я бы настоятельно рекомендую сначала проверьте, будет ли ваш компилятор оптимизировать код с помощью встроенного, как это было предложено в предыдущих сообщениях.

+0

По-видимому, я должен объявлять функции явно как встроенные и, кроме того, добавить флаг «-finline» в компилятор, чтобы убедиться, что компилятор оптимизирует функции. спасибо – davitenio

+0

как я грустный это предпочтительные варианты, но вы явно хотели макроса, поэтому я привел пример. – Ilya

Смежные вопросы