Forum: Compiler & IDEs Hardwareabstraktion und ISR


von Geri (Gast)


Lesenswert?

Hallo

Ich möchte gerne soweit wie möglich und sinnvoll den 
controllerspezifischen Code (u.a. ISRs) vom controllerunabhängigen Code 
trennen.

Meine Überlegung: Hardwarefile (hal) anlegen und dort eine Funktion 
InitTimerISR codieren. Diese übernimmt während der Programmlaufzeit 
einen Timer-Handler. Der Timer-Handler wird mit hoher Frequenz 
aufgerufen.
1
hal.h und hal.c 
2
void InitTimerISR(uint32_t ISR_Handler)
3
{
4
...
5
...
6
  VICVectAddr1 = (uint32_t)ISR_Handler;
7
...
8
}
9
10
11
common.h, common.c
12
13
static ISR_Handler1(void) INTERRUPT;
14
{
15
  ..
16
}
17
18
static ISR_Handler1(void) INTERRUPT;
19
{
20
  ...
21
}
22
23
24
static void SetTimerISR(uint8_t Mode)
25
{
26
   if (Mode == 0) InitTimerISR(Addr(ISR_Handler1)); else
27
   if (Mode == 1) InitTimerISR(Addr(ISR_Handler2)); else
28
       ...
29
}

Hat es einen negativen Einfluss auf die Performance wenn das Programm so 
aufbaut ist bzw. wie könnte man es besser machen?
Meiner Ansicht dürfte es bei einer ARM7-Architektur nichts ausmachen....

Danke für eure Meinung

Geri

von (prx) A. K. (prx)


Lesenswert?

Wird nur begrenzt funktionieren, das Interrupt meisten quittiert werden 
müssen und fast alle Device-Interrupts ausser vielleicht solchen Timern 
auf I/O zugreifen.

Was besser funktioniert: Für Kram wie solche Timer, RTCs, UARTs, I2C, 
1-Wire, ... Treiber schreiben. Die nach oben hin ein recht einheitliches 
Interface haben und so die Deviceabhängigkeit abstrahieren. Bei einer 
neuen Controller-Familie muss dann nur ein neuer Satz von Treiber gebaut 
werden.

Bei einem zyklischen Timer könnte das beispielsweise ein Treiber sein, 
in den sich Routinen der Anwendung als Callbacks einklinken können. Das 
ist geringfügig weniger effizient, aber trennt Hardware von Anwendung.

von Geri (Gast)


Lesenswert?

Vielen Dank für deine Meinung!

>Wird nur begrenzt funktionieren, das Interrupt meisten quittiert werden
>müssen und fast alle Device-Interrupts ausser vielleicht solchen Timern
>auf I/O zugreifen.

In meinem Fall werden in der Timer-ISR auch Ausgänge gesetzt und 
gelesen. Es sind lauter einfache IO-Operationen. Ich hätte mir es aber 
so gedacht, dass ich IO-Routinen durch Defines ersetze. Wenn ich das 
Programm auf einem PC compilieren möchte, dann z.B. durch Funktionen

HAL.c
1
#define CLEAR_VEC_ADDR()          VICVectAddr = 0;
2
#define CLEAR_Timer0_ISR_FLAG()   T0IR  = 0x01;
3
#define DONE_TIMER0_ISR()         {CLEAR_Timer0_ISR_FLAG(); CLEAR_VEC_ADDR
4
5
// Beispiel setzten digitaler Ausgang
6
#define MODULE_LED_PIN    22
7
#define MODULE_LED_MASK    (1 << MODULE_LED_PIN)
8
#define MOUDLE_LED_PORT_ON   FIO0SET
9
#define MOUDLE_LED_PORT_OFF  FIO0CLR
10
11
#define MODULE_LED_ON        MOUDLE_LED_PORT_ON = MODULE_LED_MASK
12
#define MODULE_LED_OFF       MOUDLE_LED_PORT_OFF = MODULE_LED_MASK

Im Controllerspezifischen Code würde man dann am Ender der Timer0ISR das 
Define DONE_TIMER0_ISR(); aufrufen

Ist dieser Ansatz deiner Meinung nach eine Sackgasse?



>Bei einem zyklischen Timer könnte das beispielsweise ein Treiber sein,
>in den sich Routinen der Anwendung als Callbacks einklinken können. Das
>ist geringfügig weniger effizient, aber trennt Hardware von Anwendung.

Würde das deiner Ansicht dann ein sinnvolles Gerüst wenn es sich nur um 
einfache IO-Operationen handelt?

1
// file hal.c - controllerspezifischer Code
2
void (*Timer0ISR_CallBack )(void);
3
4
void Timer0ISR() INTERRUPT
5
{
6
   Timer0ISR_CallBack(); 
7
   VicVectAddr = 0;
8
}
9
10
// Aktiviere Timer 0 Interrupt
11
#define EnableT0ISR()     T0MCR = 3
12
13
// Deaktiviere Timer 0 Interrupt
14
#define DisableT0ISR()     T0MCR = 0   
15
16
();} 
17
18
// file common.c - controllerunabhängiger Code
19
#include "hal.h"
20
21
void InitmyTimer0ISR(void)
22
{
23
   Timer0ISR_CallBack = &myTimer0ISR;
24
   EnableTimer0ISR();
25
}
26
27
void myTimer0ISR(void)
28
{
29
   // führe hier controllerunabhängigen Code aus
30
   ..
31
   ..
32
}
Ein Vorteil der Treiber-Idee wäre meiner Meinung nach dann, wenn die 
IO-Routinen komplexer werden und viel controllerspezifischen Coder 
erfordern.


Wie gross ist denn die Einbusse eigentlich?
Könnte mir vorstellen:
1.) Einbusse für Aufruf einer Funktion in einer ISR
2.) Einbusse für das Sichern von Registern?
3.) ??

von (prx) A. K. (prx)


Lesenswert?

Geri schrieb:
> Ist dieser Ansatz deiner Meinung nach eine Sackgasse?

Das ist nur begrenzt auf wenige Fälle sinnvoll. Also bei solchen 
einfachen Pin-Aktionen, ebenso kann ein 1-Wire Treiber so implementiert 
werden, weil nur 2 GPIO-Pins bedient werden.

Letztlich ist das eine Abwägung.

> Würde das deiner Ansicht dann ein sinnvolles Gerüst wenn es sich nur um
> einfache IO-Operationen handelt?

Es gibt keine universelle eierlegende Wollmilchsau. In sehr einfachen 
Fällen ist der Treiber-Ansatz komplexer als nötig. Andererseits hat man 
bei Controllern auch oft mehrere regelmässige Timer-basierte 
Aktivitäten, die man in einem Systick (oder wie immer der heisst) 
zusammenfassen kann. Dann kann es sinnvoll sein, einen generischen 
Systick zu definieren, in den man mehrere Handler einklinken kann, 
beispielsweise orientiert an Peter Danneggers Scheduler.

> Ein Vorteil der Treiber-Idee wäre meiner Meinung nach dann, wenn die
> IO-Routinen komplexer werden und viel controllerspezifischen Coder
> erfordern.

Exakt.

> Wie gross ist denn die Einbusse eigentlich?

Wenn man zeitlich knapp dran ist, beispiesweise weil ein Pin alle 100 
Takte getoggelt werden muss, dann ist das sehr relevant. Nicht hingehen 
wenn es um einen 1KHz Systemtimer geht.

von Geri (Gast)


Lesenswert?

Vielen Dank für deine schnelle Rückmeldung. Das hilft mir mal schon sehr 
weiter!

Der Treiber-Ansatz ist zwar mehr Schreibarbeit (beim ersten mal), dafür 
sieht das Interface wahrscheinlich immer sehr ähnlich aus. Das 
erleichtert das Lesen des Programmes auch wieder. Ebenso dünkt mich die 
Trennung von Anwendung und hal eindeutiger weil Hardwareaufrufe 
vordergründig im HAL erfolgen.

Besten Dank nochmals!!!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.