Hallo zusammen, Ich stehe gerade vor der Frage, wie ich mein nächstes Projekt konfiguriere. Mikrocontroller wird ein STM32 Cortex M3, aber eher ein kleinerer mit wenig Ram. Sprache ist momentan C. C++ bis 14 wäre theoretisch möglich, aber der Vorteil muss schon groß sein. Es müssen verschiedene Sensoren über SPI ausgelesen werden, es gibt auch nen ADC für Analogwerte und CAN oder UART zur Kommunikation. Es wird verschiedene Hardware Revisionen geben mit unterschiedlich vielen Sensoren und Features, für die die FW, und zwar möglichst immer die gleiche, konfiguriert werden muss. Zur Konfiguration stehen Dinge wie clock, Ports, Parameter der Berechnungsvorschriften, Anzahl und Adresse der angeschlossenen Sensoren, sample raten, Filterlevel etc PP. Momentan stehen volatile Parameter mit Default in einem globalen Eeprom Modul, wo sich per define die einzelnen Module ihre settings holen. Das muss in die einzelnen Module gekapselt werden. Diese Parameter werden teilweise bei einem kalibrierschritt aktualisiert. Dann gibt es auch noch build options, die z.B. bestimmte Berechnungs Module ein oder ausschalten, oder spezielle Kundenoptionen darstellen. Dann gibt es momentan ein config Modul, das const structs zur Konfiguration der statischen Dinge wie clock und Ports definiert. Die config steht da also im Code (und damit in Git). Ich möchte möglichst viel vereinheitlichen, um eine zentrale config zu haben, damit ich genau weiß, was welche fw kann, anstatt das an mehreren Stellen nachschauen zu müssen. Wie wird das momentan in der Industrie gemacht? Im Prinzip kommen da imo zwei gegensätzliche Konzepte in Frage: 1. Wird die FW möglichst dynamisch gehalten, und dann erst zur Laufzeit konfiguriert, z.B. mit typabhängiger Konfiguration, die aus ner Datenbank oder einer json oder woher auch immer kommt? Nachteil: massiver flash und RAM Verbrauch für Funktionalität, die möglicherweise nicht gebraucht wird. 2. wird der Code komplett statisch generiert durch irgendwelche Code Generatoren? Cube MX geht ja so in die Richtung, aber umfasst ja eher nur Hardware config/Hal. Vorteil: config in generator config Datei und damit versioniert, viel weniger Ressourcenverbrauch. Nachteil: ggf zu wenig Flexibilität. 2.1. nicht der gesamte Code wird generiert, aber z.B. ein (einzelner) config Header, mit einer Art namespace Schema für jedes Modul. Hat den "Charm" von alten C header define Orgien. 2.2. man schreibt gegnerischen Code mit Platzhaltern, der z.B. durch ein Python Skript geparst und modifiziert wird. Was macht ihr und warum? Danke :)
Ich habe eine zentrale Konfiguration im Eeprom. Die wird am Anfang gelesen. Und ja nach Konfiguration werden einzelne Objekte mit new und den Parametern generiert, oder der Pointer auf NULL gelassen. In einem zweiten Schritt schaue ich z.B. bei I2C, was dort wirklich angeschlossen ist. Meldet sich der Chip nicht, dann wird der Konstruktor auch nicht aufgerufen, bzw abgebaut. Da das new/delete einmalig bei Hochfahren stattfindet, bekomme ich wenig Probleme mit fragmentiertem Speicher. Bei der Inbetriebnahme der Platine muss das Eeprom einmal richtig gesetzt werden.
Jan K. schrieb: > 2. wird der Code komplett statisch generiert durch irgendwelche Code > Generatoren? Cube MX geht ja so in die Richtung, aber umfasst ja eher > nur Hardware config/Hal. Vorteil: config in generator config Datei und > damit versioniert, viel weniger Ressourcenverbrauch. Nachteil: ggf zu > wenig Flexibilität. So in der Richtung habe ich jetzt angefangen. Aktuell bastel ich an einen CAN Stack mit diversen (automitive) Protokollen. Inklusive der Konfigurierbarkeit im CubeMX/CubeIDE. Gerade wenn man mehrere Konfigurationen realisieren möchte, lohnt sich der Weg über die Codegeneration. Ob der generierte Code nun statisch als Konstante im ROM oder veränderbar im EPROM liegt, ist vom Ansatz egal.
Zum Thema Eeprom: Meine Eeprom Daten sind in einem großen union/struct definiert. Das erste Element gibt immer die Eeprom-Version an. Dadurch kann ich in späteren Software-Versionen das Eeprom-Layout beliebig ändern oder erweitern. Die späteren Software-Versionen müssen lediglich alle älteren Eeprom-Layouts kennen. Dadurch kann eine neuere Software nach dem Update die Eeprom Daten nutzen, die eine älteren Softwareversion zuletzt hinterlassen hat. typedef union Eeprom { struct { unsigned long version; byte param 1; } EepromLayout_V1; struct { unsigned long version; byte param 1; byte param 2; } EepromLayout_V2; };
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.