2009-03-24 11 views
0

Ich habe zwei Interrupt-Service-Routinen (ISR), die im Grunde die gleiche Sache, aber jeder behandelt einen Interrupt von einem anderen Gerät (obwohl der gleiche Typ von Gerät). Daher ist die Logik die gleiche, aber sie greifen auf verschiedene CPU-Register und Speicherplätze zu.Wie vermeidet man Code-Duplizierung zwischen ähnlichen ISRs?

Als ein einfaches Beispiel den folgenden Code:

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 */ 
} 

Wie kann ich die Code-Duplizierung mit den Einschränkungen zu vermeiden, die auf ISRs gilt (dh ich kann nicht Parameter übergeben, um die ISR und Funktionsaufrufe sollen vermieden werden wegen ihrer Overhead).

Ich habe daran gedacht, eine Vorlage zu schreiben, aus der die zwei ISRs mit einer höheren Skriptsprache generiert werden, aber ich würde eine Lösung bevorzugen, die nur C oder C Präprozessormakros verwendet.

Antwort

2

Warum verwenden Sie keine Inline-Hilfsfunktion, die Zeiger auf das Gerät und den Puffer bekommt?

Ich würde die generierte Assembly überprüfen, um sicherzustellen, dass der Compiler das tut, was ich erwarte.

Sie könnten auch ein Makro verwenden, aber IMHO ist es nicht gut, dies für so lange Funktionen zu tun.

2

Wenn sie den gleichen Gerätetyp behandeln, ist es sinnvoll, nur einen Interrupt-Handler zu verwenden, der mehrere Interrupts behandelt. Sie können überprüfen, welches Flag oben gesetzt wurde und von dort weitermachen. Ich würde dies jedoch nicht empfehlen, wenn die beiden Interrupt-Handler für verschiedene Arten von Geräten sind und nur denselben Logikfluss haben.

6

In solchen Fällen habe ich normalerweise das Front-End des ISR (Vector Entry Point) einen Zeiger auf einen gerätespezifischen Block einrichten und dann den gemeinsamen Code mit einem Zeiger auf diesen Block aufrufen.

Grob (keine Sorgen über ISR Syntax usw.)

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 und dev2info konfiguriert sind/beim Start initialisiert; Sie könnten Zeiger auf HW-Register usw. haben ...

+0

Mit dem Compiler, den ich verwende, müsste ich CommonISR explizit als Inline deklarieren, um einen Funktionsaufruf zu vermeiden. Ansonsten werde ich das wahrscheinlich tun. Vielen Dank. – davitenio

1

Sind Sie sicher, dass Ihr Compiler keine Funktionsaufrufe optimiert?
Sie können auf jeden Fall eine Makros verwenden diesen Code automatisch zu generieren, aber es wird ein bisschen hässlich sein:

#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 */ \ 

}

und dann:

ISR_DECLARE(dev_1) 

ISR_DECLARE(dev_2) 

Aber ich würde dringend vorschlagen, Überprüfen Sie zuerst, ob der Compiler den Code mithilfe von Inline optimiert, wie in früheren Posts vorgeschlagen.

+0

Anscheinend muss ich Funktionen explizit als Inline deklarieren und außerdem dem Compiler ein "-finline" -Flag hinzufügen, um sicherzustellen, dass der Compiler Funktionsaufrufe optimiert. danke – davitenio

+0

wie ich traurig das ist bevorzugte Optionen, aber Sie wollten explizit Makro, also gab ich ein Beispiel. – Ilya

Verwandte Themen