2013-02-28 14 views
5

Chciałbym móc napisać ISR w jednym miejscu:Jak mogę wygenerować tablicę protokołów obsługi przerw w C++?

some_collection TimerHandlers;  

// added to ISR table in linker script 
void rawTimerIRQHandler() { 
    call_each_handler_in(handlers); 
} 

taka, że ​​mogę następnie zarejestrować ładowarki w innych plikach

// file1.cpp 
void ledTimerHandler1() { 

} 
register(ledTimerHandler1); //or in an init function if not possible here 
// file2.cpp 
void ledTimerHandler2() { 

} 
register(ledTimerHandler2); //or in an init function if not possible here 

a gdy sprzęt przeskakuje do rawTimerIRQHandler, wykonuje się w kilku dowolnych zamówieniach ledTimerHandler1 i ledTimerHandler2.


Oczywiście, mogę wdrożyć to używając coś podobnego do vector<void(*)()>, ale ponieważ liczba tych koparki jest znany w czasie kompilacji, czy jest jakiś sposób mogę wygenerować tablicę (lub szablon związany lista) na czas kompilacji? Chciałbym uniknąć dynamicznej alokacji pamięci, która przychodzi z vector.

Jestem otwarty na używanie template<>, #define, a nawet atrybutów specyficznych dla GCC do osiągnięcia tego celu.

+0

[This] (http://stackoverflow.com/a/8688526/102441) wygląda potencjalnie trafnie – Eric

Odpowiedz

4

Rusztowanie to trochę uciążliwe, ale gdy to się robi wykorzystanie nie może być prostsze:

// example.h: 
#include "Registered.h" 
struct example : Registered<example> {}; 
// main.cc: 
#include <iostream> 
#include "example.h" 

int main() 
{ 
    for (auto p = example::registry; p; p=p->chain) 
     std::cout << p << '\n'; 
} 
// Registered.h : 
template<class registered> 
struct Registered { 
    static registered *registry; 
    registered *chain; 
    Registered() : chain(registry) {registry=static_cast<registered*>(this);} 
}; 
// example.cc: 
#include "example.h" 
template<> example *Registered<example>::registry = 0; 

static struct example first, second, third; // these can be defined anywhere w/ static duration 

edit: przeniósł first,second,third deklaracji/definicji zaspokoić mój wewnętrzny pedant

+0

Bardzo sprytny! Nie jestem pewien, dlaczego nie widziałem statycznych pól i konstruktorów jako sposobu na stworzenie globalnego stanu początkowego. Już zmierzałem w kierunku list powiązanych. Przyjmę to, gdy tylko będę działał w moim kontekście. – Eric

+0

Czy można przenieść przykład 'template <> * Registered :: registry = 0;' do definicji szablonu w 'Registered.h'? – Eric

+0

Ponadto, prawdopodobnie mógłbym użyć tego w niestatycznym kontekście i sprawić, że każdy element sam się usunie w ograniczniku. – Eric

1

Absolutnie. Jeśli dobrze rozumiem, po prostu potrzebujesz stałej tablicy wskaźników funkcji do swoich programów obsługi. Korzystanie z C++ 11 składnię, a zakładając, 3 ładowarki tylko przez wzgląd na przykładzie

#include <array> 

const std::array<HandlerPtr, 3> handlers= {&ledTimerHandler1, &ledTimerHandler2, &ledTimerHandler3}; 

lub przy użyciu bardziej klasyczny C/C++ składni

const HandlerPtr handlers[] = {&ledTimerHandler1, &ledTimerHandler2, &ledTimerHandler3}; 
+0

Chyba przegapiłem coś ważnego tutaj. Wolałbym nie tworzyć ręcznie tablicy w jednym pliku. Miałem nadzieję, że zrobię jakąś sztuczkę obok definicji w każdym pliku, i że kompilator (lub linker) zbuduje dla mnie tablicę. W ten sposób mogę wykluczyć testy z kompilacji, a ich programy obsługi przerwań również są wykluczone, bez żadnych modyfikacji źródła. – Eric

+0

Rozumiem. Przepraszam, że nie rozumiem tego pytania. –

+0

Prawdopodobnie pomogłeś to wyjaśnić innym. Ciężko mi było zadawać pytanie słowami. – Eric

0

Opierając się odpowiedź jthill, oto co będę prawdopodobnie kończy się przy użyciu (ponieważ nie potrzebują Ogólna forma)

struct timer_handler { 
    static timer_handler *first = 0; 
    timer_handler *next; 
    void (*f)(); 
public: 
    timer_handler(void (*f)()) : next(first), f(f) { first = this;} 

    // connect this to the interrupt vector 
    static inline void executeAll() { 
     auto p = first; 
     while(p) { 
      p->f(); 
      p = p->next; 
     } 
    } 
}; 
//a.cpp 
void foo() { 

} 
timer_handler tfoo = foo; 
//b.cpp 
void bar() { 

} 
timer_handler tbar = bar; 
Powiązane problemy