wie Aussagekräftig ist das eigentlich ?
ziemlich, es kommt auf das Tool an und die Regeln die darin festgelegt werden ob und welche Fehler man findet .... für dich wäre es zum Beispiel extreeeeem hilfreich gewesen, wenn du eine REgel definiert hättest die Warnungen für alle Variablen generiert die innerhalb des statischen und des ISR Code verwendet werden und NICHT "volatile" deklariert wurden.
Du hast das perfekte Beispiel gezeigt wie man Variablen nicht verwenden sollte. Die Count Variable sowohl im statischen als auch im ISR Code zu manipulieren ist gefährlich.
Ich benutze für derartige Zwecke üblicherweile (ich nenn sie mal so) "Katz und Maus" Variablen und bau mir damit einen Ringpuffer. Die Maus ist der ISR counter der sich immer weiter erhöht und defineirt oder implizit überläuft (wenn man den Luxus von genug Speicher hat). Die Katze ist dann mein Readmarker, der immer der Maus hinterher läuft. So kann ich immer und zu jederzeit sicherstellen dass nur ein "Prozess" (streng genommen ist das multithreading) eine Variable zu einer bestimmten Zeit bearbeiten kann und ichkann sogar zu jedem Zeitpunkt eine Plausibilitätsprüfung machen.
Ausnahme dabei ist natürlich wenn du Variablen hast die aufeinander zulaufen, dann musst du tatsächlich volatile machen damit du garantiert den aktuellen Wert erhälst oder eben manuell die ISRs blockieren bis die Plausibilitätsprüfung abgeschlossen ist.
Das Makro das ich versprochen habe kommt im Laufe des Tages wenn cih es mal kurz funktionell arrangiert habe
- - - Aktualisiert - - -
So, hier ist das versprochene Makro, man muss zwar noch ein wenig improvisieren damit es auch sofort funktioniert aber der code wie er ist kann als template benutzt werden, man muss nur seine Datenstrukturen einbauen und den switch case entweder in eine art "callViaEnum(myEnum_t what)" methode dafür einbauen oder gleich direkt im code einarbeiten
Code:
//die Kontruktionsliste, hier werden alle Daten eingegeben um das Programm zu konstruieren
#define XTABLE(ENTRY) \
// ENUM | METHODE | DATA (ACHTUNG, dieser Kommentar erzeugt ein Multiline Comment Warning und dient nur als Tabellenkopf)\
ENTRY( CALL1, callMethode1, {irgend_welche_daten, in_struct, oder_array, oder_einzeln)\
ENTRY( CALL2, callMethode2, {irgend_welche_daten, in_struct, oder_array, oder_einzeln)\
ENTRY( DO_STH, callSomething, {irgend_welche_daten, in_struct, oder_array, oder_einzeln)
//ein X-Makro um uns passend die notwendigen Daten bereit zu stellen
#define AS_DATA(ENUM,METHODE,DATA) DATA
//das X-Makro um den Caller Switch-Case zu erzeugen, benötigt das DATA Makro, deswegen die Reihenfolge beachten
#define AS_METHODE_CASES(ENUM,METHODE,DATA) \
case(ENUM):\
{\
parameter = prepareSomething(DATA);\
METHODE(parameter,irgendwasanderes);\
break;\
}
//hier erzeugen wir einen Enum anhand unserer Tabelle als Lookup und Call Referenz für den switch-case
#define AS_ENUM(ENUM,METHODE,DATA) ENUM,
typedef enum
{
XTABLE(AS_ENUM)
LAST_ENTRY
}entryEnum_t;
//wir erzeugen hier Beispielsweise auch eine LookupTable mit den Daten falls wir dynamisch darauf zugreifen müssen
//und hinterlegen sie implizit/explizit im ROM (static const, oder andere prefixe je nach compiler) zum RAM sparen
typedef struct
{
entryEnum_t entryEnum;
somedata_t entryData;
}lookupDataStruct_t;
static const lookupDataStruct_t entryDataLookup[] = {
XTABLE(AS_DATA)
};
//hier generieren wir die eigentlichen Prototypen
#define AS_PROTOTYPE(ENUM,METHODE,DATA) return_t METHODE(simpledata_t input_parameter, otherdata_t andere_sachen);
XTABLE(AS_PROTOTYPE)
//irgendwo im Code erzeugen wir dann an der passenden stelle den switch-case
switch(entryEnum)
{
XTABLE(AS_METHODE_CASES)
default:
{
ASSERT(FAIL);
break;
}
}
Jedes Tool sollte in der Lage sein die Makros aufzulösen und über den switch-case eine code coverage von 100% damit erreichen
wenn ich nur Functionpointer in einer Tabelle einsetze kommt die Linkerebene dazwischen, man kann es zwar logisch auflösen aber das beherrscht kaum ein Tool, da die wenigsten auch den konkreten Inhalt von Arrays in die Analyse mit einbeziehen.
Was dieses X-Makro erzeugt ist ein sauber lesbarer Switch Case der Anhand der Enums die Daten passend verarbeite udn der Methode dann die Parameter übergibt und sie aufruft.
Wer Tippfehler findet darf sie behalten :P
Lesezeichen