1 Punkte von GN⁺ 2024-07-07 | 1 Kommentare | Auf WhatsApp teilen
  • Da ein auf dem Raspberry Pi Pico basierender Controller für Video-Equipment viele gleichzeitige Aufgaben erfordert, wurde die Softwarestruktur mit pico-sdk und einer bloßen Aufteilung auf zwei Kerne zunehmend schwer beherrschbar
  • Der Controller muss RS-485 VISCA, Ethernet, 9 RGB-Tasten, einen Joystick und ein Display gemeinsam handhaben und außerdem DHCP, mDNS sowie das UDP-basierte ATEM-Protokoll verarbeiten
  • FreeRTOS ermöglichte mit Scheduler und Task-zu-Task-Kommunikation Teile der Umsetzung, doch Probleme mit hängendem printf und fehlende Hardware-Abstraktion erschwerten Debugging und Code-Wiederverwendung
  • Apache NuttX bot eine Shell, ein Dateisystem, Geräteabstraktionen wie /dev/i2c0 und Kconfig-Konfiguration; das I2C-Problem wurde später jedoch als Konfigurationsfehler korrigiert, sodass ein großer Teil der damaligen Bewertung ungültig sein könnte
  • Zephyr scheiterte an einem 5 GB großen Repository, SDK, Board-Definitionen und Build-Komplexität; am Ende tendierte die Entscheidung dazu, weiter FreeRTOS zu versuchen, weil es sich am einfachsten in die bestehende Umgebung einfügen lässt

Warum ein RTOS nötig wurde

  • Mehrere kleine Mikrocontroller-Projekte entstehen rund um das Raspberry Pi Pico-Board
    • Der Pico lässt sich dank brauchbarem SDK, günstiger Hardware und gdb/openocd-Debugging-Unterstützung leicht in IDEs integrieren
  • Das aktuelle Projekt ist ein Hardware-Controller zur Steuerung mehrerer Videogeräte
    • Gesteuert werden zwei motorisierte PTZ-Kameras, eine feste Kamera und ein angeschlossenes Video-Switching-Gerät
  • Der vorhandene PTZ-Kamera-Controller ist ein No-Name-Panel, das dem Marshall VS-PTC-200 ähnelt
    • Vor einigen Jahren kostete es €650, aber das Tastengefühl und die Qualität des analogen Joysticks sind schlecht
    • Viele Tasten funktionieren mit den derzeit verwendeten Kameras nicht und es scheint auf Sicherheitskameras optimiert zu sein
    • Mit den Kameras ist es über einen RS-485-Bus verbunden
  • Die Steuerung des ATEM-Video-Switchers erfolgt derzeit nur über ein Software-Panel auf einem Computer
    • Die Hardware-Panels von Blackmagic Design sind sehr teuer

Hardware-Aufbau des Controllers

  • Als Minimaldesign wurden 9 Tasten, ein Joystick und ein Display für die Benutzeroberfläche festgelegt
  • Nach mehreren Iterationen des Hardware-Designs über ein Jahr hinweg lag schließlich eine Leiterplatte vor
    • 9 RGB-Tasten
    • Der $10-Joystick, der auch im Marshall-Klon-Panel steckt
    • TP8485E für die Kommunikation mit den PTZ-Kameras über RS-485
    • Ein Wiznet W5500-Modul für die Kommunikation mit dem Video-Switcher über Ethernet
  • Nach Board-Änderungen funktionierten schließlich alle Hardware-Komponenten, doch der schwierigere Teil war die Software

Software nur mit pico-sdk wurde zu schwerfällig

  • Wie bei bisherigen RP2040-Projekten begann alles mit einem cmake-Projekt, das pico-sdk einbindet
  • Um etwas Funktionsfähiges zu erreichen, wurde der zweite Core des Pico für die Verarbeitung des Wiznet-Moduls reserviert, während der erste Core die I/O der Benutzeroberfläche übernimmt
    • LED-Blinken und sogar eine auf dem zweiten Core laufende DHCP-Client-Implementierung waren möglich
    • Die Umsetzung des restlichen Systems wurde deutlich komplexer
  • Die Zahl der gleichzeitig zu erledigenden Aufgaben wuchs schnell
    • Eine einigermaßen flüssige Benutzeroberfläche auf dem Display zeichnen
    • VISCA-Befehle über die RS-485-Schnittstelle senden
    • Auf Tasteneingaben reagieren
    • Einen Netzwerk-Stack mit mehreren Verbindungen am Leben halten
  • Die Netzwerkseite erfordert separate Hintergrundarbeit
    • Standardkonforme DHCP-Unterstützung muss Ablaufzeiten verfolgen und gelegentlich mit dem DHCP-Server kommunizieren, um die Lease aufrechtzuerhalten
    • mDNS wird benötigt, um die IP des ATEM-Video-Switchers automatisch zu finden; außerdem wäre es gut, auch die Anwesenheit des Control Panels bekanntgeben zu können
    • Das ATEM-Protokoll ist simpel, aber manchmal treffen mehr Daten ein, als in die Puffer des Wiznet-Moduls passen, und wenn das Senden von UDP-Datagrammen aussetzt, ist der Timeout bis zum Verbindungsabbruch sehr kurz
  • Unter diesen Bedingungen wirkte es sinnvoller, die Arbeit mit einem RTOS aufzuteilen, statt weitere eigene Schleifen aufzuschichten

FreeRTOS: einfach, aber mit zu wenig Abstraktion

  • FreeRTOS ist technisch im pico-sdk enthalten, doch die Tutorials laden eine neue Kopie herunter; diesem Ansatz wurde gefolgt
  • Unter den betrachteten RTOS wirkte es am einfachsten und stellt hauptsächlich einen Scheduler sowie Kommunikation zwischen Tasks bereit
    • Die Struktur besteht darin, mit xTaskCreate Tasks zu erstellen und mit vTaskStartScheduler den Scheduler zu starten
    • Über Queues lässt sich IPC nutzen, etwa um Tastenzustände an einen LED-Task weiterzugeben
  • Nach einigen Tagen Nutzung war die Codebasis bereits in mehrere Tasks aufgeteilt, obwohl sie noch wenig echte Funktionalität enthielt
    • buttonsTask: pollt den I2C-GPIO-Expander, prüft Tasteneingaben und legt Nachrichten in die Tasten-Queue
    • ledTask: setzt anhand von ledQueue-Nachrichten die RGB-Farbe bestimmter Tasten
    • mainTask: führt die Hauptschleife aus, die den Projektzustand anhand von Tasteneingaben aktualisiert
    • networkTask: kommuniziert mit dem Wiznet-Modul
    • dhcpTask: wird von networkTask erstellt, wenn ein Netzwerkkabel angeschlossen ist
    • mdnsTask: wird von dhcpTask erstellt, nachdem eine IP-Adresse bezogen wurde
    • atemTask: wird erstellt, wenn mDNS eine Antwort eines ATEM-Geräts erhält
    • viscaTask: tut noch nichts, soll aber Daten über den RS-485-Port senden
  • Obwohl die Hardware bislang außer dem Auftauchen im Netzwerk nichts tut, ist die Zahl der Tasks bereits hoch
  • Das unangenehmste Problem ist, dass printf jedes Mal hängen bleibt
    • Der gdb-Debugger funktioniert, eignet sich aber nicht dafür, DHCP-Traffic durch Ausgabe zu prüfen
  • FreeRTOS bietet keine Hardware-Abstraktion, sodass sich Code für die Kommunikation mit mehreren Chips nur schwer wiederverwenden lässt
  • Später sollte ein sauberes neues FreeRTOS-Projekt erstellt und die Funktionen dorthin verschoben werden, doch das unbequeme Debugging im Blindflug ohne serielle Ausgabe führte dazu, andere Optionen anzusehen

Apache NuttX: Unix-artige Struktur und ein Konfigurationsfehler

  • Apache NuttX wirkt eher wie ein allgemeines Betriebssystem und behandelt Mikrocontroller wie Unix-Systeme
  • Das Tutorial weist an, pico-sdk einzubinden und Umgebungsvariablen zu setzen
    • Obwohl das SDK bereits unter /usr/share lag und die Umgebungsvariablen vorhanden waren, versuchte NuttX, die Datei version.h des pico-sdk zu überschreiben; wegen fehlender Rechte schlug der Build fehl
  • Nachdem eine minimale NuttX-Firmware gebaut und mit dem seriellen Port verbunden wurde, erschien tatsächlich eine Shell
    • Befehle wie uptime, uname und uname -a funktionieren
    • Die angezeigte Version ist NuttX 12.5.1, das Ziel ist arm raspberrypi-pico
  • Da es dem Unix-Ansatz folgt, scheint es möglich, eine Anwendung zu schreiben und beim Boot automatisch auszuführen
    • Es gibt ein Dateisystem, und Hardware wird über Abstraktionen wie /dev/i2c0 und /dev/adc0 offengelegt
  • Gefallen hat die menuconfig/Kconfig-basierte Konfiguration
    • Das ist aus der Linux-Entwicklung vertraut
    • Es gibt ein echtes System für Hardware-Treiber, und für den verwendeten GPIO-Expander-Chip der Tasten existiert bereits ein Treiber
    • Auch die Pin-Mux-Konfiguration des RP2040 lässt sich in menuconfig festlegen, sodass keine separaten Pin-Nummer-Konstanten gepflegt oder viel Code zur Initialisierung des I2C-Busses geschrieben werden muss
    • Ein I2C-Testwerkzeug kann ebenfalls in die Firmware aufgenommen werden
  • Zunächst sah es so aus, als würde I2C grundsätzlich nicht funktionieren
    • In einem späteren Update wurde korrigiert, dass es tatsächlich funktionierte und der I2C-Bus durch einen Konfigurationsfehler kaputtkonfiguriert war
    • Es wird ausdrücklich erwähnt, dass der Rest dieses NuttX-Abschnitts größtenteils ungültig sein könnte
  • Damals war nicht klar, wie NuttX mitgeteilt werden sollte, dass die GPIO-Tasten hinter einem GPIO-Expander sitzen, und wie der GPIO-Expander mit dem I2C-Bus verbunden werden sollte
  • Nach einem Fehlschlag von configure.sh befand sich das Repository in einem inkonsistenten Zustand, sodass das NuttX-Repository mehrfach neu geklont werden musste
    • Auch distclean funktionierte aus demselben Grund in manchen Situationen nicht richtig
  • Der Unix-like-Ansatz wirkte zunächst attraktiv, aber auf einem Mikrocontroller sollen keine künstlichen Dateisystempfade verwaltet werden
    • In einem Produktionssystem wird auch keine Shell benötigt; der Code soll einfach laufen

Zephyr: großes SDK und Hürde bei Board-Definitionen

  • Die nächste Option war Zephyr, das ein Python-Utility zur Projekteinrichtung bereitstellt
  • Im ersten Schritt wird ein etwa 5 GB großes Git-Repository geholt
    • Darin sind HAL-Bibliotheken für viele Chips enthalten
    • Es beeinflusst auch die globalen cmake-Einstellungen des Benutzers
  • Das Tutorial verlangt die Installation des Zephyr SDK
    • Das Zephyr SDK enthält Toolchains, Compiler, Assembler, Linker und Build-Tools für die unterstützten Architekturen
    • Auch Host-Tools wie QEMU und OpenOCD sind enthalten
  • Da bereits mehrere ARM-Toolchains vorhanden sind, bestand kein Wunsch, Compiler für alle Architekturen zu bauen oder vorgefertigte herunterzuladen
  • Um ohne Zephyr SDK zu bauen, wurden Cross-Compile-Optionen gesetzt
    • ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
    • CROSS_COMPILE=/usr/bin/arm-none-eabi-
    • west build -p always -b sparkfun_pro_micro_rp2040 samples/basic/blinky
  • Der Raspberry Pi Pico wird tatsächlich nicht unterstützt; unterstützt werden nur andere Boards mit demselben SoC
    • Da sie denselben SoC verwenden, wurde angenommen, dass sie praktisch ähnlich genug sind
  • Sofort trat das Problem auf, dass die blinky-Demo nicht gebaut werden konnte
    • Die Demo verlangt eine Definition für led0, also die LED, die blinken soll
    • Das Sparkfun Pro Micro RP2040 hat keine einfache GPIO-LED, sondern eine adressierbare WS2812B-LED
  • Entsprechend dem Handbuch für Custom Boards wurde versucht, eine andere Board-Definition zu kopieren, doch auch nach dem Beheben von Build-Fehlern und Warnungen gelang kein Build für das Zielboard

Am Ende zurück zu FreeRTOS

  • Von den drei RTOS war FreeRTOS das einzige, mit dem ein Teil der tatsächlichen Anwendung gebaut wurde
  • Das printf-Problem muss wahrscheinlich gelöst werden, indem wie in Online-Anleitungen eine andere printf-Implementierung eingesetzt und an den nötigen Stellen eine andere Funktion aufgerufen wird
  • Geplant ist, FreeRTOS weiter zu versuchen
    • Denn es war die einzige Option, die sich relativ einfach in die bestehende Umgebung integrieren ließ, statt die Entwicklungsumgebung an das RTOS anzupassen

1 Kommentare

 
GN⁺ 2024-07-07
Hacker-News-Kommentare
  • Der Autor dieses Beitrags scheint RTOS als etwas zu betrachten, das wie die Arduino-Umgebung ist oder bei dem man erwarten kann, dass es mit ein wenig Herumprobieren einfach läuft. Meistens ist das nicht so.
    Viele aktuelle Arduino-Boards haben intern bereits mbed oder FreeRTOS und bieten Wege, das freizulegen; für den Stil des Autors wäre das womöglich die bessere Wahl gewesen.
    Zephyr ist einfach zu benutzen und hat auch gute CLion-Unterstützung, aber man kann nicht erwarten, dass alles funktioniert, ohne die Toolchain zu installieren. Das Pi Pico wird ebenfalls klar unterstützt, und als ich es selbst benutzt habe, gab es keine Probleme.
    Kurz gesagt: FreeRTOS wird fast überall unterstützt, aber die Treiber sind meist SoC-/geräteabhängig und dadurch umständlich, und die API ist auch nicht gerade freundlich, aber man kann sich daran gewöhnen. Für Bluetooth muss man sich den Stack selbst suchen.
    Zephyr bietet echte Hardware-Abstraktion und unterstützt die meisten SoCs, allerdings muss man eventuell etwas Board-Arbeit leisten. Ein Bluetooth-Stack ist dabei, und man muss unter Umständen etwas HCI-Unterstützung ergänzen.
    NuttX hat keine überragende Unterstützung, aber wenn man es zum Laufen bekommt, ist es eine ziemlich coole Option. Die Unterstützung in der Industrie ist bislang noch schwach. mbed gibt es auch, wird hier aber ausgelassen.
    In der Praxis wählt man bei RTOS meist das, was der SoC-Hersteller unterstützt. Bei Nordic also Zephyr, bei NXP FreeRTOS und so weiter, weil man dann besseren Support bekommt.

    • Kurz gefragt: Entwickelst du für ein Prototyping-Board oder baust du OEM-Geräte-Firmware?
      Bei Firmware-Projekten für OEM-Geräte habe ich noch nie erlebt, dass Entwickler mit Zephyr nicht zu kämpfen hatten. Ich habe auch noch keinen Entwickler getroffen, der echte Firmware für ein ausgeliefertes Produkt baut und meint, Zephyrs Hardware-Abstraktion sei dabei hilfreich.
      Das heißt nicht, dass es solche Leute nicht gibt, aber in den letzten etwa fünf Jahren ist mir keiner begegnet.
    • „Zephyr ist einfach zu benutzen“ deckt sich nicht mit meiner Erfahrung.
      Für mich hat Zephyr vor allem sehr hübsches Marketingmaterial. Hinter dem Glanz stecken aber übermäßige Aufblähung, sehr langsame Kompilierung und eine Umgebung, mit der man nur schwer loslegen kann.
    • Warum wird mbed ausgelassen? Das ist doch der Bereich, in dem es „am besten“ ist.
  • Toolchains systemweit zu installieren, wie im traditionellen UNIX-Stil, ist schmerzhaft und ehrlich gesagt keine besonders kluge Herangehensweise.
    Wenn man allein arbeitet, mag das noch funktionieren, aber sobald mehrere Entwickler an mehreren Projekten für unterschiedliche Targets arbeiten, verbringt man viel Zeit damit, Build- und Konfigurationsprobleme zu analysieren.
    Dass in den Tools ständig Python verwendet wird, hilft auch nicht. Es bringt seine eigenen Versionsprobleme mit, und ich verstehe nicht, warum man unbedingt eine Sprache verwenden will, die auf jedem Entwicklerrechner anders funktioniert.
    Ich mache Embedded-Entwicklung seit etwa zehn Jahren als Hobby und beruflich, und ich kann nicht nachvollziehen, dass man es nicht als Problem sieht, wenn in einem Projekt eine Woche darauf geht, die Umgebungen aller Beteiligten anzugleichen.
    Das ist ein reales Problem, es ist nervig, es verschwendet Zeit und es ist unnötig.
    Tools sollten statisch gelinkte Binärdateien sein. Ob sie in Rust, Go, C oder C++ geschrieben sind, ist mir egal, aber ich wünschte, man würde robuste Tools priorisieren, die sich unabhängig davon, was auf dem Rechner installiert ist, zuverlässig immer gleich verhalten, statt provisorischer Entwicklungslösungen.
    Python leistet das nicht, und es hilft auch nicht, auf Kritik daran wütend oder defensiv zu reagieren, statt das Problem ernster zu nehmen.
    Trotzdem sind Dinge wie PlatformIO ein Schritt in die richtige Richtung. Ich weiß, dass es ein Python-Projekt ist und das gelegentlich Probleme macht, aber weniger als bei anderen Tools, und die Grundidee stimmt.
    Toolchain, SDK und Bibliotheken müssen verwaltet werden, die Projektkonfiguration sollte einfach sein, und Builds sollten überall und jederzeit reproduzierbar sein.
    Ich wünschte, die Embedded-Branche hätte den Wert gemeinsamer Strukturierungsbemühungen stärker erkannt. Ich kenne viele Leute, die bei großen MCU-Herstellern arbeiten, und ich bin oft enttäuscht, weil sie meist so sehr damit beschäftigt sind, ihr unmittelbares Problem zu lösen, dass sie für die Anforderungen der Entwickler nur einen sehr engen Blick haben.

    • Ich verwende inzwischen nichts mehr, in dem Python-Tools stecken. Es ist viel zu selten, dass so etwas beim ersten Versuch sauber funktioniert.
      Ich habe ein Tastaturprojekt, das auf dem RP2040 läuft, und die Firmware ist in Rust geschrieben. Wenn man nur das Repository hat und noch keine Rust-Toolchain installiert ist, sieht der Flash-Vorgang so aus:
      (rustup installieren)
      $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
      $ rustup target add thumbv6m-none-eabi
      $ cargo install elf2uf2-rs
      * Tastatur in den Bootloader-Modus versetzen *
      $ cargo run --release
      Hier übernehmen rustup und Cargo den Großteil von Toolchain-Verwaltung und Build, und die beiden sind wirklich hervorragend. An Python-Projekte kommt das nicht einmal annähernd heran.
    • Wären Docker oder andere Container-Tools dafür nicht gute Kandidaten? Statt die Toolchain lokal zu installieren, könnte man in einem imagebasierten Container bauen, der genau die benötigte Toolchain enthält.
    • Durch die Android-App-Entwicklung sind meine Ansprüche in diesem Punkt gestiegen.
      Man führt nur einen Befehl aus, und lokal wie in CI wird alles mit denselben Versionen der Build-Tools und Bibliotheken vollständig gleich eingerichtet und ausgeführt.
      Deshalb ist es jedes Mal schmerzhaft, wieder mit CMake und Make zu hantieren und sich mit der Installation von Bibliotheken herumzuschlagen. Das ist etwas völlig anderes als ein Ansatz wie compile 'library-name-here'.
    • Ich glaube nicht, dass Leute Python wegen seiner Vorzüge als Tool-Sprache wählen. Aus dieser Perspektive ist es nicht großartig, und statisch gelinkte Binärdateien wären besser.
      Gewählt wird es stattdessen wegen seines Bibliotheks-Ökosystems. Für Datenanalyse, Visualisierung und wissenschaftliches Rechnen gibt es in anderen Sprachen nichts wirklich Vergleichbares.
      Das sind Bereiche, die man nicht von Grund auf neu implementieren möchte. Gerade bei Dingen wie numerischer Stabilität baut man leicht Fehler ein, sodass in 99 % der Fälle plausible Ergebnisse herauskommen, während in 1 % der Fälle etwas plausibel aussieht, aber vollständig falsch ist.
    • Ich habe ein Kommandozeilen-Tool, das ich 2011 in C# geschrieben habe, und es funktioniert immer noch einfach so.
  • Ich persönlich habe angefangen, meine RP2040-Projekte auf Rust und Embassy umzustellen.
    An Rust musste ich mich zwar etwas gewöhnen, aber es gefällt mir ziemlich gut. Es ist zwar kein RTOS, erfüllt aber viele Anforderungen, die sonst den Einsatz eines RTOS nötig machen.

    • Wenn man diesen Weg geht, würde ich empfehlen, zunächst mit dem rp2040-hal-Crate zu starten und sich Embassy oder RTIC anzusehen, wenn die Verwaltung mehrerer Tasks schmerzhaft wird.
      Rust und Cargo nehmen einem beim Bauen und Flashen für RP2040 oder STM32 viel Schmerz ab. Es war bisher die angenehmste Embedded-Umgebung, die ich benutzt habe.
    • Sehe ich ähnlich. Der Grund, warum Leute zu einem RTOS greifen, sind meist Bibliotheken sowie das Abhängigkeitsmanagement, und mit Rust, Cargo und crates.io bekommt man so etwas fast automatisch mitgeliefert.
      Viele Anwendungen verwenden keine MPU. Wenn man dazu Rusts Speichersicherheit und die geringere Gesamtkomplexität der Firmware ohne RTOS berücksichtigt, ergibt das ein gutes Gesamtbild.
    • Stimme vollkommen zu. Insgesamt war Embedded Rust für mich eine hervorragende Erfahrung.
      Auch die Asynchronität des Embassy-Executors funktioniert sehr gut und nimmt einem viel vom Schmerz des RTOS-Designprozesses ab.
    • Stimme zu 100 % zu. Embassy ist großartig und gefällt mir wirklich sehr.
      Wenn man noch das PIO-Interface für den RP2040 hinzunimmt, wird der Code sehr einfach und elegant, und es entsteht eine Konfiguration, die mit anderen Prozessoren schwer zu erreichen ist.
  • Der Pi Pico wird von Zephyr zu 100 % unterstützt. Hat die Person die Dokumentation unter https://github.com/zephyrproject-rtos/zephyr/tree/main/board... und https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi... nicht geprüft?
    Außerdem ist in vielen Fällen die beabsichtigte Nutzung nicht eine einzige „main“-Zephyr-Installation, sondern dass man die benötigten externen Module in das west.yml des Projekts aufnimmt.
    Dass mehrere Projekte sich eine gemeinsame Zephyr-Installation teilen, ist eine andere Diskussion, aber die Installation aller denkbaren Toolchains und HALs ist nicht der einzige mögliche Weg.

    • Wenn man das Zephyr SDK nicht installieren wollte, müsste das Bauen mit der GNU Arm Embedded-Toolchain doch trivial sein; ich verstehe nicht ganz, warum das nicht funktioniert hat.
  • Heutzutage wurde das Open-Source-ThreadX gar nicht erwähnt.
    https://github.com/eclipse-threadx/threadx/

    • RIOT könnte ebenfalls eine Alternative sein.
      https://github.com/RIOT-OS/RIOT
    • Ich verstehe nicht, warum ThreadX in solchen Listen nicht öfter erwähnt wird. Es ist relativ einfach zu verwenden und zu verstehen.
  • Der Vergleich der RTOS-Optionen war gut.
    Persönlich halte ich MicroPython für den einfacheren Weg. Kooperatives Multitasking auf Basis von async/await passt für mich gut.
    In einem aktuellen Projekt habe ich sechs Schrittmotoren, mehrere LEDs und das Scannen von Tasten verarbeitet, und für den Benutzer wirkte alles wie in Echtzeit.

    • Diese Mini-Computer sind weit leistungsfähiger als 8-Bit- und 16-Bit-Heimcomputer, daher kann MicroPython die BASIC-Anwendungsfälle früher Systeme problemlos ersetzen.
      Es ist immer noch erstaunlich, dass viele Menschen nicht wirklich begreifen, wie wenige Ressourcen wir damals zur Verfügung hatten und dass wir trotzdem Hochsprachen verwendet haben.
    • Wenn es keine harten Echtzeitanforderungen wie bei einem PTZ-Controller gibt und der Speicherverbrauch der Anwendung gering ist, scheint MicroPython eine produktive Wahl zu sein.
      Als ich MicroPython auf dem ESP32 verwendet habe, gefiel mir, dass Interrupt-Handler auf eine Python-typische Weise unterstützt werden. Ich gehe davon aus, dass der RP2040 das ähnlich unterstützt.
    • In diesem Fall sollte man doch wohl davon ausgehen, dass die Schrittmotorsignale nicht direkt vom Python-Code erzeugt werden, sondern von Hardware-Peripherie wie dem RMT des ESP32, oder?
      Bei meinem Mikroskop übernimmt ein FluidNC-Board die nahezu echtzeitnahe Schrittmotorsteuerung, und ich steuere es über ein leichtgewichtiges serielles Protokoll.
      Ich schaue mir allerdings https://pypi.org/project/micropython-stepper/ an, und das scheint Hardware-Timer und Python-Code zu verwenden.
    • Ja, das scheint ein einfaches MicroPython-Projekt zu sein.
  • Ich würde Hubris gern einmal in einem richtigen Projekt ausprobieren (https://hubris.oxide.computer/reference/).
    Der Architekturansatz passt ziemlich gut zu dem, was ich im Embedded-Bereich anstrebe. Ich mache mir das nur schmerzhafter mit C.
    Es ist auch nicht sehr anders als die Vorgehensweise mit Erlang/Elixir in gehosteten Umgebungen.
    Wenn der Speicher stärker begrenzt ist und man sich mehrere Stacks nicht leisten kann, scheint Embassy eine gute Wahl zu sein.

  • Neue Embedded-Projekte sollten immer, wirklich immer, in einer virtuellen Maschine beginnen. Man sollte Werkzeuge nicht auf demselben System vermischen.
    In meinen kommerziellen Projekten war das die Hauptursache für Qualitätsprobleme.
    Wenn man ein Projekt mit einem neuen Chipsatz oder einem neuen Anbieter beginnt, sollte man eine neue VM anlegen, nur die Werkzeuge dieses Anbieters darin installieren und dann dort bauen.
    Experimentelle Entwicklung kann man ruhig auf dem lokalen Rechner ohne VM machen. Aber Releases müssen unbedingt in der VM gebaut werden. Und bitte haltet VM und Entwicklungs-Workstation synchron.
    Ich erlebe gerade enormen Schmerz, weil ich einen Firmware-Build reparieren muss, der unbedingt behoben werden muss, während der ursprüngliche Entwickler im Urlaub ist. Niemand hat Zugriff auf dessen Workstation, die vorbereitete VM hängt sechs Monate hinterher, und der Kunde fragt, warum er für das gesamte Team bezahlen soll, wenn auf der ganzen Welt nur ein einziger besonderer Programmierer diese Aufgabe erledigen kann.

    • Noch besser wäre es, Container zu verwenden. Ich habe seit Jahren keine virtuellen Maschinen mehr benutzt und vermisse sie überhaupt nicht.
    • Würden Nix und flakes bei reproduzierbaren Build-Umgebungen helfen?
    • Diesen Schmerz kann ich fühlen.
      Meiner Meinung nach sollten Releases vom CI-System gebaut werden. Es sollte so laufen, dass man im Git ein Release-Tag setzt und nach bestandenen Tests die Binärdatei herausfällt.
  • Mit FreeRTOS liegt man kaum wirklich falsch. Zu diesem Zeitpunkt ist es de facto ein Industriestandard.

    • Gibt es irgendeine Lösung für das Problem, printf() zum Laufen zu bringen?
      Sieht ziemlich lästig aus
  • Ich hatte eine ähnliche Erfahrung wie im Originalbeitrag.
    Deshalb habe ich mir selbst einen einfachen Green-Thread-Timer gebaut.
    Er unterstützt weder echte Prozessverwaltung wie ein richtiger Kernel noch gibt er irgendwelche Garantien, aber er hat mich weiter gebracht als Bare-Metal-Scheduling und mich das Chaos eines RTOS vermeiden lassen.
    Man kann es sich wie JavaScript-Timer-Callbacks in C vorstellen, die optional eine Kontextstruktur entgegennehmen.
    Damit konnte ich das Abfragen verschiedener Sensoren, die Verarbeitung eingehender Signale, das Treffen von Regelungsentscheidungen und das Aussenden von Befehlen jeweils in unterschiedlichen Zyklen abarbeiten.
    Bevor man sich mit so einer langsamen und abstrakten Architektur das Leben schwer macht, würde ich sehr empfehlen, zuerst diesen Ansatz auszuprobieren.