Daniel A. schrieb:
> Vielleicht kannst du statt einer Modul ID einfach das `static` keyword
> nehmen?
Ich habe nicht geschrieben, wofür ich das brauche… Das hole ich jetzt
nach:
Mein Programmpaket enthält einen Header namens config.h, der in alle
Module an erster Stelle nach den Library-Includes includet wird. Dort
stehen die grundlegenden Generierungsparameter drin und unter anderem
auch die Modul-IDs für jeden .c-File und die Fehlernummern, die in dem
jeweiligen Modul vorkommen. (Die ModulID und Fehlernummer kann bei
fatalen Fehlern mit einer LED signalisiert werden und anhand der Nummern
findet man mittels config.h sehr schnell die Stelle, an der es gerumst
hat.)
In jedem .c-Modul steht nach den includes ein
#define MODULE_ID MODULE_MAIN_C
oder wie der Modul auch immer heißt. (In config.h ist MODULE_MAIN_C als
Zahlwert definiert.)
So weit das Vorgeplänkel, das den Trick mit dem cpp lohnend macht. Nun
zum aktuellen Problem: ich will den Watchdog so integrieren, dass er dem
Programm mit einem Reset wieder auf die Beine hilft, wenn es sich
irgenwo verlaufen hat.
Dummerweise hatte ich in etlichen Modulen und teilweise ganz tief in den
Hardware-Dingen wdt_rest() Aufrufe eingebaut. Als ich nun die wdt_reset
an kritischen Stellen im Programm testweise lahmlegte, hätte der WD
einen Reset machen sollen – hat er aber nicht, weil eben irgendwo noch
andere wdt_reset-Aufrufe waren…
Was tun?
Ich habe in die config.h folgendes Fragment eingefügt:
1 | #ifndef ALLOW_WDT_ACCESS
|
2 | #undef wdt_reset
|
3 | void __wdt_reset(uint8_t moduleID, uint16_t line);
|
4 |
|
5 | #define WDT_CAT(x, y) x, y
|
6 | #define WDT_CAT2(x, y) WDT_CAT(x, y)
|
7 |
|
8 | #define wdt_reset() __wdt_reset(WDT_CAT2(MODULE_ID, __LINE__))
|
9 | #endif // ALLOW_WDT_ACCESS
|
Nur in watchdog.c ist ALLOW_WDT_ACCESS definiert – damit kann nur der
ein echtes wdt_reset ausführen.
Alle andern Module expandieren statt dem üblichen wdt_reset aus
avr/wdt.h zu
1 | __wdt_reset(MODULE_ID, __LINE__)
|
Die Funktion, die statt des Macros aufgerufen wird sieht so aus:
1 | void __wdt_reset(uint8_t moduleID, uint16_t line) {
|
2 | uart_puts_P(PSTR("wdt_reset: "));
|
3 | uintOut(moduleID);
|
4 | uart_putchar(',');
|
5 | uintOut(line);
|
6 | nl();
|
7 |
|
8 | wdt_reset();
|
9 | }
|
Weil sie in watchdog.c liegt, wird dort wdt_reset aus avr/wdt.h
ausgeführt.
Damit ist mit geringsten Eingriffen eine Trace-Funktion für wdt_reset
implementiert, die sich natürlich mit noch weniger Handgriffen wieder
deaktivieren lässt…