Mikrocontroller-Programmierung vs. objektorientierte Programmierung

Ich habe einige grundlegende objektorientierte Programmierung mit C++ durchgeführt (Erstellen eines B-Baums, Hashing-Algorithmen, doppelt verknüpfte Listen) und ich habe ein kleines Projekt in C durchgeführt (wie einen wissenschaftlichen Taschenrechner erstellen usw.).

Wie unterscheidet sich die Hardwareprogrammierung (insbesondere für Mikrocontroller) von der software-/objektorientierten Programmierung in Bezug auf die Denkweise und das "Denken", das der Programmierer haben muss?

Gilt einer meiner meisten Leute normalerweise als härter als der andere?

Benötige ich mit meinem Hintergrund (wie oben beschrieben) viel Vorbereitung, um in die Hardwareprogrammierung einzusteigen, oder kann ich ohne allzu große Vorbereitung direkt einsteigen?

Die größte Lernkurve besteht darin, wie Sie die spezifische Hardware in Ihrem Mikro ansteuern. Da wird stundenlang über den Datenblättern gebrütet. Leider gibt es keinen einfachen Ausweg.
@rrazd, mir ist aufgefallen, dass Sie das Arduino-Tag eingefügt haben. Liegt das daran, dass Sie die Arduino-Verdrahtungssprache und -Bibliotheken verwenden möchten? Oder werden Sie Ihre eingebetteten Anwendungen in reinem C schreiben? Wenn Sie beabsichtigen, bei der Arduino-Umgebung zu bleiben, ist es ziemlich sicher und einfach, darin herumzuspielen, da sie einige Abstraktionen von der Hardware entfernt vorgenommen haben.
@Jon Ich plane, für den Anfang ein Arduino-Board zu verwenden. Ist es nicht ähnlich wie C-Sprache? Ich dachte, es beinhaltet die gleichen Grundkonzepte ...
Ich frage mich, ob Sie das meinen, was viele Leute als „E/A-Programmierung“ bezeichnen würden, oder ob Sie erwarten, Hardware mit Code neu anzuordnen. Das Arduino ist entschieden ersteres; Letzteres wäre die Domäne von FPGAs.
@rrazd, ich habe beschlossen, meine Antwort auf Ihren letzten Kommentar in eine Antwort umzuwandeln. Siehe unten.
Mir ist klar, dass ich eine gleiche, aber entgegengesetzte Frage stellen sollte, da ich von der Hardware komme und jetzt tief OO groken muss
@rrazd - Ich habe den Titel geändert; "Hardwareprogrammierung" klingt zu sehr nach HDL (Hardware Description Language), zB VHDL und Verilog, die zur Programmierung von FPGAs und CPLDs verwendet werden.

Antworten (7)

Bei den meisten Mikrocontrollern müssen Sie das objektorientierte Paradigma vollständig aufgeben.

Mikrocontroller sind im Allgemeinen register- und RAM-begrenzt, mit langsamen Taktraten und ohne Pipelining / parallele Codepfade. Sie können zum Beispiel Java auf einem PIC vergessen.

Sie müssen sich in eine Assembler-Denkweise versetzen und prozedural schreiben.

Sie müssen Ihren Code relativ flach halten und Rekursionen vermeiden, da RAM-Beschränkungen oft zu Stapelproblemen führen können.

Sie müssen lernen, wie man Interrupt-Service-Routinen schreibt, die effizient sind (normalerweise in Assemblersprache).

Möglicherweise müssen Sie Teile des Codes manuell in Assemblersprache umgestalten, um Funktionen zu implementieren, die der Compiler nicht (oder nur unzureichend) unterstützt.

Sie müssen mathematischen Code schreiben, der die Wortgröße und den Mangel an FPU-Fähigkeiten der meisten Mikrocontroller berücksichtigt (dh 32-Bit-Multiplikation auf einem 8-Bit-Mikro = böse).

Es ist eine andere Welt. Ein Informatik- oder professioneller Programmierhintergrund kann für mich im Umgang mit Mikrocontrollern genauso hinderlich sein wie gar keine Kenntnisse.

Sie müssen das objektorientierte Paradigma nicht vollständig aufgeben, aber auf kleineren Mikros kann es notwendig sein, schwergewichtige Objektimplementierungen aufzugeben und wirklich darüber nachzudenken, wie jedes Problem am besten gelöst werden kann. Das ist oft prozedural, aber leichtgewichtige Objekte, die gut implementiert sind (normalerweise von Hand), können manchmal die Größe komplizierter Mikrocontroller-Projekte schrumpfen lassen.
All dies ist wahr, außer dass die Objektorientierung aufgegeben wird. Sie werden wahrscheinlich keine Sprache mit OO-Funktionen verwenden, aber das schließt die Objektorientierung nicht aus. Für Mikrocontroller werden Sie Treiber für alle Hardware-Peripheriegeräte (ADCs, serielle Buscontroller, PWM usw.) schreiben. Ein solcher Treiber sollte immer objektorientiert geschrieben werden, damit er 1) autonom ist und den Rest des Programms nicht kennt/kümmert und 2) eine private Kapselung implementiert, damit der Rest des Programms dies nicht kann geh rein und fummel damit herum. Dies ist zu 100 % in C möglich und hat keinen Einfluss auf die Leistung.
Ich stimme dem ersten Satz überhaupt nicht zu, alle meine Mikrocontroller-Projekte wurden mit C++ und einem objektorientierten Ansatz erstellt, und die von uns verwendeten Mikros waren nicht sehr groß (32 kB ROM), der ebenfalls objektorientierte Bootloader war in weniger als 2 kB, I sehe keine Einschränkung. Sie können keine verrückten Sachen machen, aber das Design kann problemlos objektorientiert sein.
@Arsenal Hinweis Ich habe "die meisten" gesagt und beachte, dass Sie einen vier Jahre alten Thread kommentieren. :)
Dem ersten und dem letzten Satz kann ich absolut nicht zustimmen. Und auch Assembler wird ziemlich selten und meistens nur für 8-Bit-MCUs verwendet (sehen Sie einfach in diesem Forum nach, wie viele Beiträge mit Assemblercode Sie finden können?). Sie können und (IMHO) sicherlich im OO-Stil für 32-Bit-MCUs schreiben

Sie müssen an mehrere Dinge denken:

  • Als Sprache verwenden Sie C
  • Sie können immer noch ein Gefühl der Objektorientierung erzeugen, indem Sie Funktionszeiger verwenden, sodass Sie Funktionen usw. überschreiben können. Ich habe diese Methode in früheren und aktuellen Projekten verwendet und funktioniert sehr gut. OO ist also teilweise vorhanden, aber nicht im Sinne von C++.

Es gibt andere Einschränkungen, die ins Spiel kommen, wie z. B. begrenzte Geschwindigkeit und Speicher. Als allgemeine Richtlinie vermeide ich also:

  • Wenn es eine Möglichkeit gibt, das Problem ohne Malloc zu lösen, verwende ich heap. Zum Beispiel ordne ich Puffer vor und verwende sie einfach.
  • Ich reduziere absichtlich die Stapelgröße in den Compilereinstellungen, um Probleme mit der Stapelgröße frühzeitig zu lösen, und optimiere dies sorgfältig.
  • Ich gehe davon aus, dass jede einzelne Codezeile durch ein Ereignis unterbrochen wird, daher vermeide ich nicht wiedereintrittsfähigen Code
  • Ich gehe davon aus, dass sogar Interrupts verschachtelt sind, also schreibe ich diesen Code entsprechend
  • Ich vermeide es, OS zu verwenden, es sei denn, es ist notwendig. 70 % der Embedded-Projekte benötigen nicht wirklich ein Betriebssystem. Wenn ich ein Betriebssystem verwenden muss, verwende ich nur etwas mit verfügbarem Quellcode. (Freertos usw.)
  • Wenn ich ein Betriebssystem verwende, abstrahiere ich fast immer Dinge, damit ich das Betriebssystem innerhalb weniger Stunden ändern kann.
  • Für Treiber usw. verwende ich nur die vom Hersteller bereitgestellten Bibliotheken, ich fummele nie direkt an den Bits herum, es sei denn, ich habe keine andere Wahl. Dies macht den Code lesbar und verbessert das Debuggen.
  • Ich schaue mir die Loops und andere Sachen an, besonders in ISR, um sicherzustellen, dass sie schnell genug sind.
  • Ich habe immer ein paar GPIOs griffbereit, um Dinge zu messen, Kontextwechsel, ISR-Laufzeit usw.

Die Liste geht weiter, ich bin wahrscheinlich unterdurchschnittlich in Sachen Softwareprogrammierung, ich bin mir sicher, dass es bessere Praktiken gibt.

+1 für "Sie können OO-Paradigmen verwenden, wenn Sie möchten". Was Sie an der Tür überprüfen müssen, ist kein OO-Design. OOD ist nur eine Philosophie, die Sie dazu ermutigt, zusammengehörigen Code und Daten zusammenzuhalten. Was Sie hinter sich lassen müssen, ist die Art und Weise, wie OO in Unternehmenssystemen implementiert wird, mit mehreren Abstraktionsebenen, Umkehrung der Kontrolle und all dem Jazz. Die Aufgabe Ihrer Firmware ist es, die Hardware anzutreiben, das war's.

Ich mache beides, also hier ist meine Ansicht.

Ich denke, die mit Abstand wichtigste Fähigkeit in Embedded ist Ihre Debugging-Fähigkeit. Die erforderliche Denkweise ist insofern anders, als so viel mehr schief gehen kann, und Sie müssen sehr offen dafür sein, all die verschiedenen Möglichkeiten zu berücksichtigen, wie das, was Sie zu tun versuchen, schief gehen kann.

Dies ist das größte Einzelproblem für neue Embedded-Entwickler. PC-Leute haben es tendenziell rauer, da sie es gewohnt sind, so viel nur für sie zu arbeiten. Sie verschwenden viel Zeit damit, nach Tools zu suchen, die Dinge für sie erledigen (Tipp: Es gibt nicht viele). Es gibt eine Menge Köpfe, die immer wieder gegen Wände schlagen, ohne zu wissen, was sie sonst tun sollen. Wenn Sie das Gefühl haben, festzustecken, treten Sie einen Schritt zurück und finden Sie heraus, ob Sie erkennen können, was alles schief läuft. Grenzen Sie systematisch Ihre Liste potenzieller Probleme ein, bis Sie es herausgefunden haben. Aus diesem Prozess folgt direkt, dass Sie den Umfang der Probleme begrenzen sollten, indem Sie nicht zu viel auf einmal ändern.

Erfahrene Embedded-Leute neigen dazu, das Debuggen als selbstverständlich zu betrachten ... die meisten Leute, die es nicht gut können, halten nicht lange durch (oder arbeiten in großen Unternehmen, die einfach "Firmware ist schwer" als Antwort darauf akzeptieren, warum ein bestimmtes Feature ist Jahre zu spät)

Sie arbeiten an Code, der auf einem externen System zu Ihrem Entwicklungssystem ausgeführt wird, mit unterschiedlichem Grad an Sichtbarkeit Ihres Ziels von Plattform zu Plattform. Wenn Sie dies unter Ihrer Kontrolle haben, drängen Sie auf Entwicklungshilfen, um diese Sichtbarkeit in Ihrem Zielsystem zu erhöhen. Verwenden Sie serielle Debug-Ports, Bit-Banging-Debug-Ausgang, das berühmte Blinklicht usw. Lernen Sie zumindest, wie man ein Oszilloskop verwendet und Pin-I / O mit dem Oszilloskop verwendet, um zu sehen, wann bestimmte Funktionen eintreten / verlassen, ISRs ausgelöst werden usw Ich habe gesehen, wie Leute buchstäblich Jahre länger als nötig kämpften, einfach weil sie sich nie die Mühe gemacht haben, einen richtigen JTAG-Debugger-Link einzurichten/zu lernen.

Es ist viel wichtiger, genau zu wissen, welche Ressourcen Sie im Verhältnis zu einem PC haben. Lesen Sie die Datenblätter sorgfältig durch. Berücksichtigen Sie die Ressourcen-"Kosten" von allem, was Sie zu tun versuchen. Lernen Sie ressourcenorientierte Debugging-Tricks wie das Füllen von Stack-Speicherplatz mit einem magischen Wert, um die Stack-Nutzung zu verfolgen.

Während sowohl für PC- als auch für eingebettete Software ein gewisses Maß an Debugging-Fähigkeiten erforderlich ist, ist dies bei eingebetteter Software viel wichtiger.

Ich gehe davon aus, dass Ihre C++-Erfahrung PC-basiert ist.

Programmierer, die von PCs auf Mikrocontroller umsteigen, machen häufig den Fehler, dass sie nicht erkennen, wie begrenzt Ressourcen sein können. Auf einem PC wird Sie niemand aufhalten, wenn Sie eine Tabelle mit 100.000 Einträgen erstellen oder ein Programm schreiben, das zu 1 MB Maschinencode kompiliert.
Es gibt Mikrocontroller, die über eine Fülle von Speicherressourcen verfügen, insbesondere im High-End-Bereich, aber es ist immer noch weit entfernt von dem, was Sie gewohnt sind. Bei einem Hobbyprojekt können Sie wahrscheinlich immer das Maximum herausholen, aber bei einem professionellen Projekt werden Sie oft gezwungen sein, mit dem kleineren Gerät zu arbeiten, weil es billiger ist .
An einem Projekt arbeitete ich mit einem TI MSP430F1101. 1 KB Programmspeicher, 128 Byte Konfigurations-Flash, 128 Byte RAM. Das Programm passte nicht in die 1K, also musste ich eine 23-Byte-Funktion in das Konfigurations-Flash schreiben. Mit diesen kleinen Controllern rechnen Sie byteweise . Bei einer anderen Gelegenheit war der Programmspeicher 4 Byte zu klein. Boss ließ mich den Controller nicht mit mehr Speicher verwenden, stattdessen musste ich einen bereits optimierten Maschinencode (der bereits in Assembler geschrieben war) optimieren, um die zusätzlichen 4 Bytes einzufügen. Sie erhalten das Bild.

Abhängig von der Plattform, auf der Sie arbeiten, müssen Sie mit I/O auf sehr niedrigem Niveau umgehen . Einige Entwicklungsumgebungen haben Funktionen, um auf ein LCD zu schreiben, aber bei anderen sind Sie auf sich allein gestellt und müssen das Datenblatt des LCDs von Anfang bis Ende lesen, um zu wissen, wie man es steuert.
Möglicherweise müssen Sie ein Relais steuern, das ist einfacher als ein LCD, aber Sie müssen auf die Registerebene des Mikrocontrollers gehen. Wieder ein Datenblatt oder Benutzerhandbuch. Den Aufbau des Mikrocontrollers, den Sie in einem Blockschaltbild wiederfinden, müssen Sie noch einmal im Datenblatt kennenlernen. Zu Zeiten des Mikroprozessors sprachen wir von einem Programmiermodell, was im Grunde eine Anordnung der Register des Prozessors war. Heutige Mikrocontroller sind so komplex, dass eine Beschreibung aller Register den größten Teil eines 100-seitigen Datenblatts einnehmen kann. IIRC nur die Beschreibung des Taktmoduls für den MSP430 war 25 Seiten lang.

Sie müssen sich oft mit Echtzeit- Event-Handling befassen. Ein Interrupt , den Sie innerhalb von 10 bearbeiten müssen μ s zum Beispiel und haben währenddessen einen anderen Interrupt, der die gleiche Zeitgenauigkeit erfordert.

Mikrocontroller werden oft in C programmiert . C++ ist ziemlich ressourcenhungrig, also ist das normalerweise out. (Die meisten C++-Implementierungen für Mikrocontroller bieten eine begrenzte Teilmenge von C++.) Wie gesagt, je nach Plattform steht Ihnen möglicherweise eine umfangreiche Funktionsbibliothek zur Verfügung, mit der Sie einiges an Entwicklungszeit sparen können. Es lohnt sich, sich etwas Zeit zu nehmen, um es zu studieren, es kann Ihnen später viel Zeit sparen, wenn Sie wissen, was verfügbar ist.

Ich habe Spiele für den Atari 2600 geschrieben, der eine eher eingeschränkte Plattform ist; Mein erstes veröffentlichtes Spiel war im Wesentlichen 4K-Code (da ich einen 32K-Wagen hatte, fügte ich einige Extras hinzu, aber die 4K-Version war vollständig spielbar); RAM ist 128 Byte. Ich finde es interessant, darüber nachzudenken, dass in dem Jahr, in dem ich dieses Spiel geschrieben habe (2005), andere Spiele veröffentlicht wurden, die buchstäblich eine Million Mal so groß waren.
@supercat - Ja, aber das war zu erwarten, 2005 war der Atari 2600 schon 200 Jahre alt! Ich habe noch nie Actionspiele wie Egoshooter gespielt, aber wenn ich mir anschaue, was man zum Spielen braucht, eine GPU, die sowohl programmatisch als auch elektrisch viel leistungsfähiger ist als Ihre CPU, kann ich nicht anders, als den Kopf zu schütteln :-). Ich habe Schach (Sargon) auf einem 16k TRS-80 IIRC gespielt. Der Flugsimulator meines Bruders brauchte nicht mehr.
Nicht ganz 200 Jahre alt. Es debütierte 1977, also waren es nicht einmal 30. Obwohl ich zustimme, dass das in technologischer Hinsicht Äonen her ist, bin ich immer noch überwältigt von der Tatsache, dass es nicht nur eine hundertfache oder tausendfache Steigerung gibt , aber eine MILLIONENfache Erhöhung sowohl des RAM als auch der Codegröße. Die Geschwindigkeit wurde nicht ganz so stark gesteigert, da der 2600 1,19 MHz hatte und neuere Systeme nur im niedrigen GHz-Bereich liegen. Sie können pro Zyklus viel mehr leisten als der 2600 (der in jedem Zyklus 1/76 einer Videozeile erzeugen konnte und musste), aber ich glaube nicht, dass sie 1.000.000-mal so schnell sind.

"Hardwareprogrammierung" kann vieles bedeuten. Das Programmieren eines sehr kleinen Chips (denken Sie an 10F200, 512 Befehle, ein paar Bytes RAM) kann fast wie das Entwerfen einer elektronischen Schaltung sein. Andererseits kann die Programmierung eines großen Cortex-Mikrocontrollers (1 Mb FLASH, 64 kB RAM) der PC/GUI-Programmierung mit einem großen GUI-Toolkit sehr ähnlich sein. Meiner Meinung nach benötigt ein guter Embedded-/Echtzeitprogrammierer Fähigkeiten sowohl auf der Seite der Softwareentwicklung als auch auf der Seite des Schaltungsdesigns. Für die größeren uC ist C++ eine gute Sprachwahl, für die ganz kleinen dürfte C die einzige Wahl sein. Montagekenntnisse können nützlich sein, aber ich würde nicht empfehlen, ernsthafte Projekte vollständig in Montage durchzuführen.

Ich habe ernsthafte eingebettete Arbeit mit Leuten von beiden Seiten (SWI und EE) gemacht. Ich bevorzuge im Allgemeinen die SWI-Leute, vorausgesetzt, sie haben etwas Erfahrung mit Multi-Thread-Programmierung.

Ihre Frage klingt, als wollten Sie in die eingebettete Programmierung eintauchen. Tun Sie das auf jeden Fall. Für die Low-Level-Aspekte (Verbindung der Peripheriegeräte in Ihrem Chip und der Hardware darum herum) müssen Sie einige neue Fähigkeiten erlernen, aber es ist nur eine Menge Arbeit ohne viele neue Konzepte. Für die höheren Schichten Ihrer Projekte können Sie auf Ihr vorhandenes Wissen zurückgreifen.

Für jede Arduino-Bibliotheksmethode, die Sie aufrufen, gibt es eine Fülle von C/C++-Code, der dies ermöglicht, es ist einfach schön verpackt, damit Sie es als API verwenden können. Werfen Sie einen Blick auf den Arduino-Quellcode unter dem Verzeichnis hardware/arduino/* und Sie sehen das gesamte für Sie geschriebene C/C++, das direkt mit den Registern des AVR-Mikrocontrollers interagiert. Wenn Sie lernen möchten, wie man solche Dinge schreibt (direkt für die Hardware), dann gibt es viel zu tun. Wenn Ihr Ziel darin besteht, etwas mit ihren Bibliotheken zum Laufen zu bringen, gibt es möglicherweise nicht viel zu besprechen, da die meiste harte Arbeit für Sie erledigt wird und ihre Bibliotheken und Entwicklungsumgebungen sehr einfach zu bedienen sind.

Einige Faustregeln bei der Arbeit mit ressourcenbeschränkten Geräten, die entweder für Arduino-Umgebungen oder andere gelten könnten:

Achten Sie darauf, wie viel Speicher Sie verwenden. Sowohl die Codegröße (die in den Flash-Speicher geht) als auch die statische RAM-Nutzung (Konstanten in Ihrem Code, die immer im RAM vorhanden sind). Ich würde argumentieren, dass die statische RAM-Nutzung am Anfang etwas wichtiger ist, da sie leicht zu übersehen ist. Es ist nicht ungewöhnlich, dass Sie nur 1000 Bytes für Ihren Stack, Heap und Ihre Konstanten haben. Seien Sie klug, wie Sie es ausgeben, vermeiden Sie also Dinge wie lange Arrays von Ganzzahlen (jeweils 4 Bytes), wenn Bytes oder Zeichen ohne Vorzeichen (jeweils 1 Byte) ausreichen. Eine andere Antwort hier deckt einige andere wichtige Punkte sehr gut ab, also höre ich hier auf. Ich wollte hauptsächlich klarstellen, dass es viel zu behandeln gibt, wenn Sie die Arduino-Bibliothek nicht verwenden und Ihre eigenen C-Bibliotheken schreiben.

In Bezug auf die Programmierung von Mikrocontroller und OOP sind sie keine Gegensätze. Es stimmt, dass alle Herstellerbibliotheken in reinem C vorliegen, aber alle Plattformen unterstützen auch C++ OOP. Entwickler können darüber hinaus C++ High-Level-Bibliotheken und Geräte-Firmware erstellen und erstellen. Das gute Beispiel sind Arduino-Bibliotheken, offizielle und vom Benutzer erstellte - hauptsächlich C++-Klassen. Möglicherweise können nicht alle OOP-Vorteile in einer eingebetteten Umgebung vollständig genutzt werden, aber auch hier gelten die bekannten Vorteile von C++ gegenüber C.

In Bezug auf die Denkweise und das Denken sind Mikrocontroller, wie in anderen Antworten erwähnt, sehr ressourcenbeschränkte Plattformen (insbesondere im RAM, weniger in der Geschwindigkeit) - Dinge wie die dynamische Speicherzuweisung, C++-Ausnahmen sind normalerweise ausgeschlossen. Wenn die richtige Hardware ausgewählt ist, ist es einfach, sich an diese Einschränkungen anzupassen und andere Techniken zu verwenden (die auch auf anderen Plattformen weit verbreitet sind).

Meiner Ansicht nach könnte die schwierigere Herausforderung eine weitere zusätzliche Dimension sein, die in der eingebetteten Programmierung zu finden ist – das Timing. Dies liegt daran, dass eingebettete Software normalerweise viel mit Echtzeitereignissen, streng zeitgesteuerten Protokollen zum Ansteuern von Peripheriehardware und allgemeinen Aufgaben selbst zu tun hat (dies sind auch einige Parallelen zu anderen "High-Level" -Plattformen, wie z. B. Multithread-Anwendungen).

Seien Sie bereit, viele Datenblätter zu lesen, wenn Sie sich mit neuer Hardware befassen - ich denke, es könnte mit dem Fragenteil "Mindset" zusammenhängen :) Sicherlich wären einige EE- und Hardwarekenntnisse erforderlich.

Ich möchte auch darauf hinweisen, dass die Entwicklung eingebetteter Software heutzutage keine Assemblersprache erfordert. Tatsächlich ist Java (übrigens ist es standardmäßig OOP) bereits da und wird stärker (zumindest für einige Klassen von eingebetteten Geräten, zum Beispiel IoT-Geräten, könnte es eine sehr gute Zukunft haben).

In Bezug auf Bedenken sind diejenigen rund um die (Neu-)Zuweisung von dynamischem Speicher tendenziell ein größeres Hindernis für traditionelles OO als das Timing .
Vielleicht hast du recht. Aber es gibt Leute, die in den 80-90er Jahren für MSDOS-Real-Mode-Software programmiert haben, mit 64K (Datenspeichersegment) verfügbarem RAM-Speicherplatz, und für sie war es "natürlich". Vielleicht war MSDOS PC eine "eingebettete" Umgebung als der heutige STM32F4 :)
Der STM32F4 hat normalerweise mehr Programmspeicher in Form von Flash, aber der PC wurde normalerweise mit viel mehr RAM-Speicher geliefert, um veränderliche Laufzeitobjekte zu speichern. Während die ganze Far-Pointer-Sache, die durch die segmentierte Adressierung erzwungen wurde, ein Schmerz war, fehlt beiden eine echte MMU, und das wird auf dem System mit weniger RAM, dem STM32F4, noch mehr Anlass zur Sorge geben. Außerdem waren die PC-Betriebszeiten tendenziell kürzer und die akzeptablen Ausfallraten höher.