Hintergrund :
Junior R & D Electronics Engineer ( der einzige EE im Unternehmen ) - die Hardware und die Codierung sind nicht das Problem. Mein größtes Problem ist es, einen richtigen Überblick über das Projekt zu bekommen und wo ich anfangen soll.
Bisher habe ich nur kleinere Softwareprojekte erstellt (weniger als 500 Codezeilen), aber ich kann mir nicht vorstellen, größere Projekte durchzuführen, ohne den Überblick über die Funktionalität oder den Mangel an Funktionalität zu verlieren.
Wie strukturieren Sie am besten bzw. mit welchen Tools strukturieren Sie große eingebettete Softwaresysteme?
Was ich gerade mache :
Normalerweise beginne ich damit, die Funktionalität des Projekts zu skizzieren. Es kann sich um ein oder mehrere geschichtete Flussdiagramme oder verwandte Diagramme (Blockdiagramme usw.) handeln, bei denen die Komponenten / Chips untersucht werden. Dann springe ich direkt in die Codierung (ich vermute, scheitere schnell), während ich auf die Datenblätter / das Internet verweise, eine Funktionalität nach der anderen codiere und sie mit Dummy-Daten oder einem ähnlichen Test teste. Es könnte sich um das Schreiben von Daten auf einen MEM-Chip handeln, und wenn dies funktioniert, könnte es sich um einen SPI-Treiber zwischen dem Hauptchip und dem MEM-Chip handeln.
Welche Antwort suche ich? :
Wirklich alles. Ich werde klären, was ich für sinnvoll halte. Es kann sich um ein Buch, einen Artikel, eine persönliche Erfahrung, Empfehlungen usw. handeln.
Ich bin sehr daran interessiert zu wissen, wie Senioren das angehen.
Bearbeiten
Zunächst einmal vielen Dank, dass Sie Ihre jahrelange Erfahrung teilen! Alle Antworten werden sehr geschätzt. Daraus nehme ich:
- Erstellen Sie ein klares und präzises Spezifikationsdokument.
- Erstellen Sie ein Software-Designdokument. (Etwas, das ich jetzt hinzufügen werde) Entwerfen Sie Dokumentvorlagen
- Denken Sie in Modulen, wie redundant es erscheinen mag. (Etwas worauf ich mich mehr konzentrieren muss)
- Befolgen Sie einen Kodierungsstandard für die Strukturierung von Header- / Quelldateien. (Nie zuvor) Barr Group C Standard
- Konzentrieren Sie sich zunächst auf die Erstellung der Implementierungen auf niedriger Ebene. (Mitteilung usw.)
- Implementieren Sie Entwurfsmuster, wo immer dies möglich / sinnvoll ist. Designmuster
- Richten Sie etwas für die Versionskontrolle ein (Github usw. - nie so oft verwendet)
- Forschung kontinuierliche Integration / kontinuierliche Bereitstellung (etwas Neues, auf das ich gestoßen bin) CI- und CD-Grundlagen
quelle
Antworten:
Es gibt verschiedene Aspekte, die den Detaillierungsgrad der Strukturierung eines Projektbedarfs beeinflussen. Für mich ist einer der Hauptfaktoren, ob ich die einzige Kodierung bin (was für Sie anscheinend der Fall ist, wenn Sie schreiben, dass Sie die einzige EE sind) oder ob andere beteiligt sind. Dann stellt sich die Frage, was "groß" eigentlich bedeutet. Normalerweise teile ich den Designprozess in die folgenden Schritte ein:
Anforderungsdefinition Wenn Sie die richtige Softwarespezifikation erhalten, um mit viel Planung zu arbeiten, ist dies bereits geschehen. Wenn Sie nur vage Anforderungen haben, müssen Sie als Erstes klären, was der Kunde tatsächlich möchte (manchmal wissen sie es überhaupt nicht). Ich weiß, dass es verlockend ist, einfach direkt in die Codierung einzusteigen, aber das birgt das Risiko, dass ein wichtiges Feature fehlt, das anfangs nicht offensichtlich war und nicht einfach irgendwo mitten in der Entwicklung in den Code eingearbeitet werden kann.
Systemgrenzen und Wartbarkeit In eingebetteten Systemen gibt es häufig einige Systemschnittstellen, einige nach außen (Bediener), aber auch nach innen. Definieren Sie diese gut und versuchen Sie, die Abhängigkeiten so gering wie möglich zu halten. Dies vereinfacht das kontinuierliche Engineering und die Wartbarkeit. Auch Kommentar- / Dokumentcode, wo nötig, Sie wissen nie, wer sonst damit arbeiten muss. Er wird froh sein, nicht ein Dutzend Code-Schichten durchgreifen zu müssen, bevor er wirklich weiß, was eine Funktion tut.
Überprüfbare Aufgaben definieren Insbesondere wenn andere Entwickler auf derselben Codebasis arbeiten, ist es unvermeidlich, klare Aufgaben (Funktionen) und die erforderlichen Schnittstellen zwischen ihnen zu definieren. Wenn immer möglich, sollten die einzelnen Funktionen unabhängig von anderen getestet / verifiziert werden. Hier müssen die Schnittstellen gut definiert sein, damit Sie Ihre Testfälle definieren können.
Ein Feature nach dem anderen Menschen mögen Fortschritt. Wenn Sie also eine Vielzahl von Aufgaben haben, arbeiten sie normalerweise an dem, was den größten Fortschritt verspricht. Normalerweise versuche ich, eine Aufgabe zu beenden und in einen überprüften und getesteten Zustand zu versetzen, bevor ich mit der nächsten beginne. Dadurch kann Ihr Code von anderen getestet werden, ohne dass Sie etwas vergessen.
Revisionskontrolle Während der Laufzeit eines Projekts benötigen Sie manchmal ältere Versionen, um einen mit einer neuen Version aufgetretenen Fehler zu identifizieren oder um ein Gerät zu erstellen, das sich genauso verhält wie das, das Sie vor 3 Jahren ausgeliefert haben. Stellen Sie sicher, dass Ihr Code klare Build-Revisionen und Tags enthält. Git ist definitiv dein Freund hier.
quelle
Humpawumpa hat eine tolle Antwort geschrieben ! Ich möchte nur einige seiner Punkte ergänzen, aber da dies zu lang ist, um einen Kommentar abzugeben, schreibe ich eine separate Antwort.
Ich war einmal in der Position des OP - nicht der einzige EE, sondern der einzige EE, der eine MCU-Entwicklung in einem kleinen Unternehmen durchgeführt hatte.
Ich kann die Bedeutung der Modularität nicht betonen genug , auch wenn Sie der einzige Entwickler sind. Dies ist die einzige Möglichkeit, bei wachsendem Projektwachstum vernünftig zu bleiben. Sie müssen beim Schreiben von Modulen, die jeweils nur ein Funktionskonzept behandeln, streng vorgehen und ihre externen Schnittstellen so gering wie möglich halten. High-Level-Module entsprechen den funktionalen Anforderungen, während Low-Level-Module eng mit Hardwareressourcen (dh Gerätetreibern) verbunden sind.
Ich habe viel Zeit damit verbracht, ein detailliertes Datenflussdiagramm 1 zu pflegen , das genau zeigte, wie die verschiedenen Module Informationen austauschten. Einige Funktionen stellen sehr unterschiedliche Anforderungen an die Echtzeitleistung. Stellen Sie sicher, dass Sie wissen, wie sich der Informationsaustausch darauf auswirkt. Über das Diagramm wurden Grenzen gezogen, die den Nicht-Interrupt-Code von den verschiedenen Interrupt-gesteuerten Domänen trennten.
1 Sehr verschieden von einem Flussdiagramm, das sich auf den Kontrollfluss konzentriert .
quelle
Für jedes große Projekt plane ich, als ob mehrere Entwickler beteiligt wären, auch wenn ich beabsichtige, das Ganze selbst zu machen.
Die Gründe sind einfach:
1 Komplexität. Ein großes Projekt wird immer komplexe Aufgaben haben. Wenn Sie das Projekt so geplant haben, als wären mehrere Teams beteiligt, wurde die Komplexität berücksichtigt und dokumentiert . Ich habe oft gesehen, wie große Projekte auf Probleme stießen, und normalerweise, weil etwas durch die Ritzen gerutscht ist. Vergessen Sie nicht, dass auch die mechanische Montage berücksichtigt werden muss und nicht nur die Größe der Box - werden Kühlkörper benötigt? Muss die Box aus Sicherheitsgründen geerdet werden? Allein in dieser Kategorie gibt es viele Fragen.
2 Voraussetzungen. Unter der Annahme , mehrere Personen beteiligt sind , bedeuten , dass die Top-Level - Anforderungen (die ich oft in Frage stellen , da sie unnötige Komplexität und Kosten bringen können) müssen in die verschiedenen kleineren erforderlich und erreichbar Aufgaben aufgeschlüsselt werden (die zu einem anderen Team in einer größeren Organisation zugeführt werden könnten , ) anstatt nur einen einzelnen Klecks zu betrachten.
3 Partitionierung. Es gibt zwei Hauptarten der Partitionierung. Hardware-Funktionalität und Hardware / Software. Der erste Typ besteht darin, zu bestimmen, welche separaten (aber kommunizierenden) Funktionsblöcke vorhanden sein müssen. Der zweite ist ein Kompromiss zwischen einfacherer (manchmal) Hardware und Software, aber denken Sie daran, dass ein Hardwareproblem nicht unbedingt dadurch behoben werden kann, dass einfach mehr Dinge in Software verschoben werden. Mehr in Software zu investieren, kann unter bestimmten Umständen die Hardware-Komplexität erheblich erhöhen (mehr Verarbeitungsleistung, komplexere Schnittstellen und mehr).
4 Schnittstellen. Der Partitionierungsprozess hilft beim Definieren der internen Schnittstellen. Externe Schnittstellen sind in der Regel Teil der Gesamtanforderungen (wenn auch nicht immer). Es gibt viele Möglichkeiten für die Zusammenarbeit verschiedener Teile eines Systems, bei denen es sich um ein komplexes Kommunikationsprotokoll oder einfach um eine gute / schlechte Signalisierung handeln kann.
5 Überprüfung. Dies ist eine Mischung aus Tests auf niedriger Ebene (für Hardware und Treiber) und Systemebene. Nachdem das Projekt in genau definierten Blöcken durchgeführt wurde, ist eine zuverlässige Überprüfung möglich (dies kann durch Analyse oder tatsächlichen Test erfolgen und ist normalerweise eine Mischung aus beidem; Aktualisierungen von Designs können Ähnlichkeitsargumente verwenden).
6 Standards. Ich verwende Codierungs- und Zeichnungsstandards, als wäre es ein größeres Team. Ich verwende die Codierungsstandards der Barr-Gruppe, da sie nicht zu lästig sind, aber verhindern, dass viele Fehlerklassen im Code vorkommen. Für die Dokumentation der Leiterplattenausgabe folge ich IPC-D-326 (IPC-D-325), da dies eine bewährte Methode ist, um den Leiterplattenherstellern und -monteuren meine Absichten mitzuteilen. Dies mag seltsam erscheinen, aber die Disziplin, eine Reihe von Standards einzuhalten, bedeutet, dass die Qualität konstant ist.
7 Versionskontrolle. Ich benutze die Revisionskontrolle für alle Teile des Projekts (System, Hardware, Software, Mechanik, Testanforderungen - alles). Die von mir verwendeten CAD-Tools unterstützen die Versionsverwaltung sowie alle Software- und FPGA-Build-Tools.
Ich habe an vielen Embedded-Projekten gearbeitet (so wie viele der erfahrenen Leute hier) und die Teamgrößen variierten von 1 (ich) bis zu Dutzenden (oder Hunderten bei einer bestimmten Gruppe von Projekten), die über mehrere Disziplinen und manchmal auch andere geografisch entfernte Bereiche verteilt waren Websites. Wenn ich denselben übergreifenden Ansatz verwende (von dem bekannt ist, dass er funktioniert), kann ich eine bestimmte Aufgabe in relativer Isolation aufgreifen und abschließen und sie als eigenständigen Teil des größeren Projekts gründlich testen. Es bedeutet auch, dass ich bei Bedarf einige Dinge gelegentlich unterbreiten kann.
All diese Dinge zu erledigen, bedeutet ein wenig Zeitgewinn, ist aber letztendlich ein schnellerer Weg für komplexe eingebettete Systeme.
quelle
Die anderen Antworten geben viele gute Tipps. Hier sind zwei, die ich in meiner Karriere als Embedded-Entwickler als am wichtigsten empfunden habe:
Das ist es, was Sie brauchen, um auf eingebetteten Systemen einen "kontinuierlichen Integrations" -Stil zu entwickeln. Es wird immer eine Menge Code geben, die für automatische Tests zu stark an die Hardware gebunden ist, aber versuchen Sie, sie zu minimieren. Sie können ziemlich weit kommen, indem Sie simulierte Daten oder Datenerfassungen von der tatsächlichen Hardware verwenden, die Sie dann in das Testsystem einspeisen.
quelle
Zu vorhandenen Antworten hinzufügen ...
Ich fange immer von unten nach oben an. Anhand Ihres Hardware-Designs wissen Sie, was Ihre E / A ist. Beginnen Sie damit, Treibermodule zu erstellen, die diese E / A kapseln, sodass Ihr übergeordneter Code nicht zu viel über die untergeordneten Elemente wissen muss.
Wenn Sie die Low-Level-Schnittstellen erstellen, benötigen Sie natürlich ein Testkabel. Wenn Sie dies so planen, dass es von Anfang an mit dem PC verbunden wird (möglicherweise mit einem RS-232-Anschluss, möglicherweise USB, möglicherweise Telnet über Ethernet), können Sie diese Test-Harness-Schnittstelle beim Erstellen Ihrer Anwendung beibehalten. Sie können weitere Test-Harness-Hooks hinzufügen, wenn die Anwendung Gestalt annimmt. Auf diese Weise können Sie Ihren Code auch im weiteren Verlauf einer Regression unterziehen.
quelle
Ich neige dazu, in vier Fragen zu denken. Die ersten beiden gehören zum Beginn eines Systemprojekts, die beiden am Ende.
Wollen sie das System wirklich? Wird das System das Problem des Kunden zu einem von ihm akzeptierten Zeitpunkt und zu einem akzeptablen Preis lösen? Ein häufiges Problem ist die Erstellung von Systemen, die der Kunde nicht verwenden wird.
Können wir dieses System tatsächlich bauen? Wird es möglich sein, die erforderliche Leistung, Präzision, Stromverbrauch, ... zu liefern?
Das Erstellen früher Prototypen ist ein guter Weg, um diese beiden ersten Fragen zu beantworten. Risikominderung ist in den frühen Phasen äußerst wichtig.
Die nächsten beiden Fragen richten sich eher an die späteren Phasen des Projekts:
Sind wir tatsächlich fertig? Alles entworfen, codiert, getestet, geliefert
Verwenden sie das System tatsächlich?
quelle