Kaluma: Javascript-Ausführungsumgebung für den RP2040

(Firma: Tamoggemon Holding k.s.) #7516451
Lesenswert?

Die Ausführung von Hochsprachen auf Mikrocontrollern trägt - seit jeher - zu einer Reduktion der Code-Koppelung in der Gesamtlösung bei. Mit Kaluma steht eine Runtime zur Verfügung, die auf die Bedürfnisse von Ebenezer Uptons Mikrocontrollerfamilie optimiert ist.

In diesem Artikel werden wir Experimente mit der Architektur und der Runtime durchführen, um mehr über Handling und internen Aufbau der Engine zu erfahren. Grundkenntnisse im Bereich der Mikrocontrollerhardware werden dabei als gegeben vorausgesetzt.

Auswahl der Zielarchitektur.

Der RP2040 wird - Drittanbieterboards wollen wir an dieser Stelle ignorieren - vor allem in zwei Varianten angeboten. Einerseits gibt es den alleinstehenden Raspberry Pi Pico, während sein später ausgelieferter und mit einem Infineon-WLAN-Modul ausgestattete Kollege Raspberry Pi Pico W mittlerweile ebenfalls gut verfügbar ist. Zum Zeitpunkt der Drucklegung dieses Artikels gilt dabei, dass Kaluma in Version 1.0 nur den „klassischen“ Pico unterstützt. Unterstützung für die WLAN-fähige Variante ist - siehe Abbildung - erst für die derzeit noch als Beta vorliegende Version 1.1 geplant.

Bildquelle: https://kalumajs.org/download/.

Von der Architektur

Nach dem Ende der (für die Javascript-Performance-Steigerung primär verantwortlichen) Browserkriege hat sich Node.JS und die diversen Projekte als quasi Standard für alles, was da Javascript interpretiert, herauskristallisiert. Im Fall von Kaluma gilt dabei, dass die eigentliche Javascript-Intelligenz durch das quelloffene Projekt JerryScript gestellt wird. Der Code der Runtime findet sich dann auf GitHub unter https://github.com/kaluma-project/kaluma und steht unter der Apache-Lizenz. Im Bereich der auf dem Mikrocontroller zur Ausführung gelangenden Software setzt man auf einen zweigleisigen Approach: Im ersten Schritt wird die in Form einer .UF2-Datei vorliegende Javascript-Runtime auf den Controller geladen. Sie kommuniziert danach über einen simulierten seriellen Port mit einer Node.JS-Anwendung, und legt die auszuführenden Javascript-Dateien im Remanentspeicher des Controllers ab. Dieser auf den ersten Blick pedantisch klingende Hinweis ist von wichtiger Bedeutung: Tötet eine Javascript-Datei die Runtime und blockiert die Kommunikation mit der Mater-Anwendung, so gilt, dass ein „reines“ Deployen der Runtime nicht zur Wiederherstellung eines funktionsfähigen Zustands ausreicht. Stattdessen ist unbedingt auch die Nutzung der unter der URL https://github.com/dwelch67/raspberrypi-pico/blob/main/flash_nuke.uf2 bereitstehenden Flash Nuke erforderlich; das Deployment der anderen .UF2 -Datei darf erst danach erfolgen. Apropos Deployment: Auf Seiten der Workstation ist die Installation des Pakets kaluma/cli erforderlich. Je nach Konfiguration Ihres Systems ist dazu eine der beiden folgenden Befehle zu verwenden:

1
tamhan@TAMHAN18:~$ npm install -g @kaluma/cli
2
tamhan@TAMHAN18:~$ sudo npm install -g @kaluma/cli

Analyse der inneren Architektur der Runtime.

Im nächsten Schritt bietet es sich an, folgendes Programm zur Ausführung zu bringen. Es enthält eine Endlosschleife, die permanent eine Rechteckwelle am GPIO-Pin ausgibt:

1
pinMode(2, OUTPUT);
2

3
while(1==1)
4
{
5
        digitalWrite(2, HIGH);
6
        digitalWrite(2, LOW);
7
}

Speichern Sie den Javascript-Code in einer mehr oder weniger beliebigen Textdatei, und erledigen Sie die Auslieferung nach folgendem Schema über die Node.JS-Companionapplikation:

An einem angeschlossenen Digitalspeicheroszilloskop ist dann die gezeigte Wellenform zu sehen.

Bildquelle: Autor.

Die erfolgreiche Ausgabe der Wellenform informiert uns darüber, dass der Zugriff auf die Hardware in Kaluma synchron implementiert ist. Problematisch ist allerdings, dass eine Endlosschleife keine Rechenzeit an das Betriebssystem bzw. die zugrunde liegende Infrastruktur abtritt. Bei Annahme von kooperativem Multitasking gilt dann, dass die Kommunikation mit der CLI-Applikation nicht mehr möglich ist. Diese Annahme ist dadurch bestätigbar, dass die Ausführung des nächsten Flashbefehls scheitert – unter https://youtu.be/g9WbyE8tHYs findet sich ein Video, das dies en Detail demonstriert. Eine funktionsfähige Variante des Programms würde nach folgendem Schema auf SetInterval setzen:

1
pinMode(2, OUTPUT);
2
var timerId = setInterval(function () {
3
        digitalWrite(2, HIGH);
4
        digitalWrite(2, LOW);
5
}, 1);

Zu beachten ist allerdings, dass die von dieser Variante ausgegebene Wellenform wesentlich langsamer ist.

Interaktion mit Hardware

Die Durchführung von Bit Banging-Experimenten erlaubt interessante Rückschlüsse auf die Architektur des zugrunde liegenden Systems. In der Praxis gilt aber, dass Hardware-Zugriff heute - normalerweise - über die diversen im Controller implementierten Hardware-Peripheriegeräte erfolgt, die die verschiedenen Bus-Protokolle ohne permanente Überwachung des Hauptprozessors umsetzen. Die Kaluma-Ausführungsumgebung implementiert schon zum Zeitpunkt der Drucklegung dieses Artikels so gut wie alle am RP2040 befindlichen Interfaces. Unter der URL https://kalumajs.org/docs findet sich dabei die umfangreiche Dokumentation, während unter https://github.com/kaluma-project/examples schlüsselfertige Beispiele verfügbar sind.

Fazit

Trotz des noch vergleichsweise frühen Entwicklungsstands gilt, dass Kaluma die Ausführung von Javascript am RP 2040 ermöglicht. Wer in seinem Unternehmen Javascript-IP hält, kann durch Nutzung dieses Systems Duplikation im Gesamtsystem reduzieren und die Wartbarkeit erhöhen. Dies ist ökonomisch sinnvoll - dass man als am Achtbitter mit Assembler aufgewachsener Entwickler dabei eine große und dichte Nasenklammer braucht, gibt der Autor allerdings vollumfänglich zu.

Angehängte Dateien:

Kommentare

(Firma: Tamoggemon Holding k.s.) #7516477
Lesenswert?

Benedikt M. schrieb:

JavaScript auf Embedded tut mir in der Seele weh :/

Da ein Produkt funktionssicher zu bekommen klingt nach einem Albtraum. Keine Typisierung, fehlende Performance und Anwendungsentwickler die noch nie von Embedded gehört haben.

Stimme völlig zu.

Aber: wenn es um eine unkritische Aufgabe geht? Oder man eine MCU nachschaltet, die die kritischen Aufgaben regelt?

Die Reduktion der Koppelung ist und bleibt leider ein nicht zu vernachlässigendes Argument...

#7516717
Lesenswert?

Tam H. schrieb:

wenn es um eine unkritische Aufgabe geht? Oder man eine MCU nachschaltet, die die kritischen Aufgaben regelt?

Aber wäre das nicht ein Fall, in dem die BOM durch die Verwendung von JavaScript unnötig aufgebläht werden würde, da eine zweite oder leistungsfähigere CPU verwendet werden würde, als mit C/C++/Rust erforderlich wäre?

In der Serie sind meiner Ansicht nach die evtl. leicht höheren Entwicklungskosten durch eine stärkere Kopplung vmtl. vernachlässigbar gegenüber den gestiegenen Kosten pro Einheit oder einer höheren Ausfallwahrscheinlichkeit des Produktes.

#7516726
Lesenswert?

Benedikt M. schrieb:

Da ein Produkt funktionssicher zu bekommen klingt nach einem Albtraum.

Es richtet sich vermutlich nicht an Produktentwickler, sondern an Bastler, die eh schon mit JS und Frameworks (die Anlehnung an Node.js wird ja deutlich herausgestellt) basteln. Dass denen Funktionssicherheit nicht übermäßig wichtig ist, sieht man ja an vielen ihrer Webseiten.

#7517146
Lesenswert?

Jack V. schrieb:

Benedikt M. schrieb:

Da ein Produkt funktionssicher zu bekommen klingt nach einem Albtraum.

Es richtet sich vermutlich nicht an Produktentwickler, sondern an Bastler, die eh schon mit JS und Frameworks (die Anlehnung an Node.js wird ja deutlich herausgestellt) basteln. Dass denen Funktionssicherheit nicht übermäßig wichtig ist, sieht man ja an vielen ihrer Webseiten.

Naja, leider nimmt frickelware immer mehr zu bei Entwicklern die auch "richtiges" Zeuch entwickeln.

#7517173
Lesenswert?

Wenn von 130MHz nur noch 46,5kHz übrig bleiben für einen einfachen Pin toggle und eine "funktionsfähige Variante" auch noch "deutlich langsamer" ist, dann zeigt mir das hier vorgestellte zumindest dass brutal viel Ressource verbrannt wird dabei.

Ich bin kein Hochsprachen-Hater wie andere hier, im Gegenteil. Aber das ist doch einfach am Ziel vorbei. Ein Embedded Controller mit so wenig Ressourcen dafür zu missbrauchen ist für mich das gleiche Kaliber wie manche Linux auf einen ATMEGA portieren. Einfach eine Machbarkeitsstudie, nicht mehr.

Das einzige Argument für so eine Umsetzung wäre für mich der Preis, wenn ich keinen Embedded Entwickler habe und gleichzeitig sehr sehr sehr hohe Stückzahlen habe. Wobei ich das nicht als realistisch empfinde. Wenn ich Stückzahl habe, dann leiste ich mir einen richtigen Embedded Entwickler. Alleine schon die Plattform Abhängigkeit wäre Wahnsinn...

Edit: Bezogen auf Preis /Javascript Abhängigkeit gemeint.

#7517349
Lesenswert?

Naja, leider nimmt frickelware immer mehr zu bei Entwicklern die auch "richtiges" Zeuch entwickeln.

Naja, solange es nur fuer irgendeinen Testaufbau oder ein Produktiontool ist, ist das ja IMHO auch okay. Auch man sich fragt schon "wieso" weil man nicht Entwickler sein kann ohne C zu koennen und dann muss man sich sowas ja sicher nicht mehr antun.

Vanye

#7518331
Lesenswert?

1
pinMode(2, OUTPUT);
2
var timerId = setInterval(function () {
3
        digitalWrite(2, HIGH);
4
        digitalWrite(2, LOW);
5

6
}, 1);

Diese Version ist eh nicht gut, da dann der Wechsel von HIGH -> LOW sehr schnell geht und dann bis zum nächsten Aufruf der Pin auf LOW bleibt. Besser wäre (gibt es das?) ein "digitalWrite(2,TOGGLE)"

N. M. schrieb:

Aber das ist doch einfach am Ziel vorbei.

Naja, früher hat man auch prof. Steuerungen z.B. mit dem Basic des 8052AH gemacht, oder mit dem MSR BASIC des Z80. Hat von der Geschwindigkeit ja oft gereicht. Natürlich haben trotzdem viele diese CPUs in Assembler programmiert. Ich sehe das eher als Ergänzung zu Python oder MMBasic auf dem RP2040. Das entscheidende wird sein, wie stabil dass dann läuft und wie gut die Doku ist bzw. ob damit Sachen gehen, die mit µPython nicht möglich sind. Inzwischen kann man doch viele Probleme mit µPython "erschlagen". Es gibt z.B. eine Art "Compiler", den Viper Code Emitter für zeitkritische Funktionen. Das geht dann teilweise deutlich flotter: https://forums.raspberrypi.com/viewtopic.php?t=313023. und https://docs.micropython.org/en/v1.9.3/pyboard/reference/speed_python.html#the-viper-code-emitter

N. M. schrieb:

Einfach eine Machbarkeitsstudie, nicht mehr.

So ist es.

Gast #7518828
Lesenswert?

Ich verstehe jetzt auch irgendwie nicht den Sinn einer weiteren Scriptsprache neben Micropython. Zumal Mikrocontroller mit Script-Interpreter bisher immer seltene Sonderlocken waren. Kennt noch jemand C-Control?

#7518896
Lesenswert?

Thomas T. schrieb:

Wenn tatsächlich bei einem "frei laufenden" Pin-Togggler nur 46,5kHz übrigbleiben

Wie schnell läuft denn ein "frei laufender" Pin-Toggler auf dem RP2040, wenn er z.B. in C oder Assembler geschrieben wird?

Mit welchem Takt läuft der Bus, an dem die I/O-Pins hängen, kann der konfiguriert werden, müssen CPU-Zugriffe auf diesen Bus synchronisiert werden?

Gast #7518903
Lesenswert?

Harald K. schrieb:

Wie schnell läuft denn ein "frei laufender" Pin-Toggler auf dem RP2040, wenn er z.B. in C oder Assembler geschrieben wird?

Fast 18 Megahertz. Was mich zu der Behauptung verleitet, dass dieser Script Interpreter verglichen mit anderen extrem schlecht ist.

Mit DMA und unter Ausnutzung der speziellen HW Features geht es noch sehr viel schneller. https://forums.raspberrypi.com/viewtopic.php?t=318251

#7518915
Lesenswert?

Harald K. schrieb:

Wie schnell läuft denn ein "frei laufender" Pin-Toggler auf dem RP2040, wenn er z.B. in C oder Assembler geschrieben wird?

Wenn man den PIO-Assembler nimmt maximal mit dem halben Systemtakt, also 62,5MHz bei 133MHz Systemtakt. Und man hat dann noch beide Prozessor-Cores und die anderen PIO State Machines frei. Und dann kann man den Controller noch übertakten, 250MHz sind möglich. Darüber funktioniert dann das Lesen aus dem Flash nich mehr.

#7519355
Lesenswert?

Stefan K. schrieb:

Und dann kann man den Controller noch übertakten, 250MHz sind möglich. Darüber funktioniert dann das Lesen aus dem Flash nich mehr.

Kleiner Tipp: erhöhe die Anzahl der Wartezyklen für's Flash. Dann laufen die Programme auch mit 350 - 400 MHz, wenn man es braucht. Diese Wartezyklen "stören" eh nur beim Nachladen in den internen Programm-Cache. Es gibt Berichte über Laufzeitunterschiede, wenn ein Flash nicht per QSPI sondern nur mit einfach SPI betrieben wird: Die Laufzeit wird nur unwesentlich erhöht.

Beim BASIC PicoMite für den RP2040 beispielsweise kann man den Takt bis zu 378 MHz einstellen: Handbuch Seite 10. Das scheint alle Erfahrungswerte zu bestätigen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren