{"id":1525,"date":"2025-01-14T20:10:36","date_gmt":"2025-01-14T19:10:36","guid":{"rendered":"https:\/\/janus.rs\/?p=1525"},"modified":"2025-01-14T20:10:41","modified_gmt":"2025-01-14T19:10:41","slug":"the-unusual-festive-days-asynchronous-embedded-programming","status":"publish","type":"post","link":"https:\/\/janus.rs\/en\/2025\/01\/the-unusual-festive-days-asynchronous-embedded-programming\/","title":{"rendered":"The unusual festive season"},"content":{"rendered":"\n<p>Eine Revolution: Entdecke Asynchrone eingebettete Programmierung in Rust in Embassy mit STM32, Sensoren und Praxistipps.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Liebe Leser, ich hoffe ihr hattet erholsame Feiertage und seid gut ins neue Jahr 2025 gekommen. Ich m\u00f6chte keinen typischen Neujahrs Motivation-Artikel schreiben, sondern wieder etwas Wissen mit euch teilen. Ok, den ein oder anderen Kommentar konnte ich mir nicht verkneifen. Viel Spa\u00df mit meinem &#8222;etwas anderen&#8220; Neujahrsartikel \u00fcber Asynchrone eingebettete Programmierung.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Ich habe \u00fcber die Festtage etwas Zeit freischaufeln k\u00f6nnen um ein Bastelprojekt in dem Rust Embedded Framework &#8211; <a href=\"https:\/\/embassy.dev\/\">Embassy<\/a> zu beginnen. Ihr findet den aktuellen Stand, mit einigerma\u00dfen guten Dokumentation, auf <a href=\"https:\/\/github.com\/DarthB\/rust_embedded\">GitHub<\/a>. <\/p>\n\n\n\n<p class=\"has-medium-font-size\">Was euch im Artikel erwartet:<\/p>\n\n\n\n<ul class=\"wp-block-list has-medium-font-size\">\n<li class=\"has-medium-font-size\">Entwicklung eingebetteter Systeme!<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Asynchrone Programmierung!<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Was ist eigentlich Nebenl\u00e4ufigkeit und Parallelit\u00e4t?<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Den ein oder anderen &#8222;schwarzen&#8220; Kommentar zu Vors\u00e4tzen und \u00c4nderungsbereitschaft!<\/li>\n\n\n\n<li class=\"has-medium-font-size\">und nat\u00fcrlich ganz viel zu Rust!<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><div class=\"wp-block-image is-style-rounded\">\n<figure class=\"aligncenter size-medium\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"225\" height=\"300\" src=\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS.jpg?resize=225%2C300&#038;ssl=1\" alt=\"\" class=\"wp-image-1544\" srcset=\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS-scaled.jpg?resize=225%2C300&amp;ssl=1 225w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS-scaled.jpg?resize=768%2C1024&amp;ssl=1 768w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS-scaled.jpg?resize=1152%2C1536&amp;ssl=1 1152w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS-scaled.jpg?resize=1536%2C2048&amp;ssl=1 1536w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS-scaled.jpg?resize=9%2C12&amp;ssl=1 9w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/20241228_120637307_iOS-scaled.jpg?w=1920&amp;ssl=1 1920w\" sizes=\"auto, (max-width: 225px) 100vw, 225px\" \/><\/figure>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><div class=\"wp-block-image is-style-rounded\">\n<figure class=\"aligncenter size-medium\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"225\" height=\"300\" src=\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board.jpg?resize=225%2C300&#038;ssl=1\" alt=\"\" class=\"wp-image-1529\" srcset=\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?resize=225%2C300&amp;ssl=1 225w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?resize=768%2C1024&amp;ssl=1 768w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?resize=1152%2C1536&amp;ssl=1 1152w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?resize=1536%2C2048&amp;ssl=1 1536w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?resize=9%2C12&amp;ssl=1 9w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?w=1920&amp;ssl=1 1920w\" sizes=\"auto, (max-width: 225px) 100vw, 225px\" \/><\/figure>\n<\/div><\/div>\n<\/div>\n\n\n\n<p class=\"has-text-align-center has-white-color has-black-background-color has-text-color has-background has-link-color has-medium-font-size wp-elements-a6997d36ddc9e50524aba175b0023703\">Ist Rust Lernen ein guter Vorsatz f\u00fcr 2025? Ja, aber es ist nur ein Vorsatz! <br><strong>Taten sind mehr als Worte &#8211;&gt; <a href=\"https:\/\/www.rust-lang.org\/learn\">Zum Rust lernen hierhin<\/a>!<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">Du liest noch? Super: Der Artikel gliedert sich wie folgt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\">Die Projektidee<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Eingebettete Programmierung mit Rust<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Was ist asynchrone Programmierung?<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Asynchrone eingebettete Programmierung mit Embassy<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Fazit<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Die Projektidee<\/h2>\n\n\n\n<p class=\"has-medium-font-size\">Mein letztes Projekt im Bereich Embedded liegt schon einige Jahre zur\u00fcck. Inzwischen hat man die M\u00f6glichkeit mittels <a href=\"https:\/\/www.kicad.org\/\">KiCAD<\/a> eine Platine zu designen und dann f\u00fcr wenig Geld eine Produktion, z.B. bei <a href=\"https:\/\/portal.multi-circuit-boards.eu\/\">multi-cb<\/a>, in Auftrag zu geben. Sowas l\u00e4sst mein Bastlerherz h\u00f6her schlagen. Das war aber nicht der einzige Grund, dieses Projekt zu starten.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Bei einem Kundenprojekt habe ich einen Freelancer kennengelernt, der auch an eingebetteten Systemen gearbeitet hat und \u00fcber ihn habe ich Einblicke zum aktuellen Stand der eingebetteten C-Programmierung erhalten.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Dazu kommt, dass ich seit einiger Zeit interessiert die Entwicklung von Embedded Rust beobachte. Insbesondere des Frameworks <a href=\"https:\/\/embassy.dev\/\">Embassy<\/a>, das auf dem Konzept der asynchronen Programmierung basiert. Falls man von asynchroner Programmierung geh\u00f6rt, dann am ehesten im Zusammenhang mit Web-Services anstatt mit bare-metal Entwicklung.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Aber auch ohne Embassy bringt Rust einen tollen Mehrwert in die Welt der eingebetteten Programmierung: Zur \u00dcbersetzungszeit \u00fcberpr\u00fcft Rust die Hardwarekonfiguration. Cooler ist nat\u00fcrlich Asynchrone eingebettete Programmierung.<\/p>\n\n\n\n<p class=\"has-text-align-center has-white-color has-black-background-color has-text-color has-background has-link-color has-medium-font-size wp-elements-da6afd7344d04a3e4c152b1d5f84b68e\">Ja das ist anspruchsvoll aber Rust lernen willst du eigentlich nicht?<br><strong>Dann lies stattdessen \u00fcber meine Erfahrungen bei der <a href=\"https:\/\/janus.rs\/2024\/06\/achema-2024-bruecken-zwischen-chemie-und-it\/\">ACHEMA <\/a>und der <a href=\"https:\/\/janus.rs\/2024\/04\/rust-nation-uk-2024-review-for-engineers\/\">Rust Nation UK 2024<\/a>!<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading has-medium-font-size\">Jetzt geht es auf Shopping-Tour<\/h3>\n\n\n\n<p class=\"has-medium-font-size\">So kam es eine Woche vor den Feiertagen zu einer kleinen Einkaufstour bei <a href=\"http:\/\/reichelt.de\/\">Reichelt<\/a> (ein g\u00fcnstiger und beliebter Elektronikh\u00e4ndler in Deutschland). Ich wollte eine kleine Sensorplattform aufbauen, mit der ich Temperatur und Helligkeit messen und per UART an den PC schicken kann. Dazu Mein Einkauf:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\"><a href=\"https:\/\/www.reichelt.de\/de\/de\/shop\/produkt\/nucleo-144_arm_cortex_m4f_stm32_f7-serie-357469?PROVID=2788&amp;gad_source=1&amp;gclid=Cj0KCQiAkJO8BhCGARIsAMkswygAMdzhdek-7oQZoK3QJK5O9uwg1_6s8AVl-0169abH_idu5waubGIaAnkMEALw_wcB&amp;q=%2Fnucleo-144-arm-cortex-m4f-stm32-f7-serie-nucleo-f767zi-p357469.html\">STM32 NUCLEO-144<\/a> mit einem STM32F767ZI Chip<\/li>\n\n\n\n<li class=\"has-medium-font-size\"><a href=\"https:\/\/www.reichelt.de\/de\/de\/shop\/produkt\/digital_thermometer_1-wire_-_0_5_c_to-92-58169?PROVID=2788&amp;gad_source=1&amp;gclid=Cj0KCQiAkJO8BhCGARIsAMkswyhfiJc_xRJ-NaUu_cF5JjIBRgEW0P55DEs048mFugZugkqeEi0suZUaAkgxEALw_wcB&amp;q=%2Fdigital-thermometer-1-wire--0-5-c-to-92-ds-18b20-p58169.html\">DS18B20<\/a> Programmable Resolution 1-Wire Digital Thermometer<\/li>\n\n\n\n<li class=\"has-medium-font-size\"><a href=\"https:\/\/www.reichelt.de\/de\/de\/shop\/produkt\/entwicklerboards_-_lichtsensor-modul_bh1750fvi-282559\">BH1750FVI<\/a> &#8211; Digital 16bit Serial Output Type Ambient Light Sensor IC <\/li>\n\n\n\n<li class=\"has-medium-font-size\">Ein <a href=\"https:\/\/www.reichelt.de\/de\/de\/shop\/produkt\/experimentier-steckboard-set_830_kontakte_power-modul-282601\">Breadboard Set<\/a> mit Power und einigen Kabeln<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-font-size\">Die Ziele der &#8222;Sensorplattform&#8220; und den Status QUO findet ihr auf <a href=\"https:\/\/github.com\/DarthB\/rust_embedded\">GitHub<\/a>.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Nat\u00fcrlich hatte ich einiges vergessen. Zum Beispiel ein 4,7k Ohm Widerstand f\u00fcr den I2C Bus. Vielen Dank an meinen Vater, der flei\u00dfig und pflichtbewusst auf die Suche ging um meine alten Elektronik-Teile auszugraben, so dass ich sie nach den Festtagen mitnehmen konnte. Nun gut, zur\u00fcck zum Thema: Was ist eingebettete Programmierung und warum mit Rust? Das erfahrt ihr im n\u00e4chsten Abschnitt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\"><strong>Eingebettete<\/strong> Programmierung mit RUst<\/h2>\n\n\n\n<p class=\"has-medium-font-size\">Im Grunde basiert eingebettete Programmierung darauf das man die Spannung von PINs steuert. Das Ganze ist nat\u00fcrlich viel komplizierter denn neben Pins gibt es weitere Hardware-Komponenten wie: Speicher, Busse, Timer. Es werden zum Beispiel Kommunikationsprotokolle wie <a href=\"https:\/\/www.nxp.com\/docs\/en\/user-guide\/UM10204.pdf\">I2C<\/a> eingesetzt, die mit Funktionen wie Direct-Memory-Access (<a href=\"https:\/\/wiki.st.com\/stm32mcu\/wiki\/Getting_started_with_DMA\">DMA<\/a>) betrieben werden k\u00f6nnen. <\/p>\n\n\n\n<p class=\"has-medium-font-size\">DMA erm\u00f6glicht kontinuierlichere Datenstr\u00f6me und h\u00f6herer Performance. Beispiel: Wird ein Sensor per I2C angesteuert, kann DMA daf\u00fcr sorgen, dass Messwerte ohne CPU-Eingriff in den Speicher wandern, w\u00e4hrend die CPU noch andere Aufgaben erledigt. Das ist besonders bei zeitkritischen Anwendungen vorteilhaft.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Gl\u00fccklicherweise stellen die meisten Hardware Hersteller sogenannte SVD Dateien zur Verf\u00fcgung, die beschreiben im Detail die Register einer MCU, also die Speicheradresse zum Mapping, Registeradressen und Bitfelder. Diese Informationen wurden schon im C-Ecosystem f\u00fcr die automatische Generierung von low-level Code verwendet. Stichwort <a href=\"https:\/\/arm-software.github.io\/CMSIS_5\/SVD\/html\/index.html\">CMSIS-SVD<\/a>. F\u00fcr Rust ist das Kommandozeilen-Tool <a href=\"https:\/\/docs.rs\/svd2rust\/latest\/svd2rust\/\">svd2rust <\/a>entstanden: Doch Rust, bzw. svd2rust, bietet noch mehr.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"303\" src=\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/good_errors_via_traits.png?resize=1024%2C303&#038;ssl=1\" alt=\"\" class=\"wp-image-1528\" srcset=\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/good_errors_via_traits.png?resize=1024%2C303&amp;ssl=1 1024w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/good_errors_via_traits.png?resize=300%2C89&amp;ssl=1 300w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/good_errors_via_traits.png?resize=768%2C227&amp;ssl=1 768w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/good_errors_via_traits.png?resize=18%2C5&amp;ssl=1 18w, https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/good_errors_via_traits.png?w=1407&amp;ssl=1 1407w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-medium-font-size\">Im Rust-Ecosystem bestehen neben den Hardware-Abstraction-Layers (HALs) auch Peripherie-Access-Crates (PACs). Letztere werden automatisch mittels <a href=\"https:\/\/docs.rs\/svd2rust\/latest\/svd2rust\/\">svd2rust<\/a> generiert. PACs nutzen Rust Traits um bei der \u00dcbersetzung sicherzustellen, dass Peripherie mit Treiber und DMA in der richtigen Art und Weise verkn\u00fcpft wird.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Im Bild oben sieht man z.B. eine Rust Compilermeldung, die ich erhalten habe als ich eine falsche Peripherie auf das serielle UART Protokoll mappen wollte. Der Hinweis zur L\u00f6sung ist gelb hervorgehoben. <\/p>\n\n\n\n<p class=\"has-text-align-center has-white-color has-black-background-color has-text-color has-background has-link-color has-medium-font-size wp-elements-2f3e3e65cbad7f51dddb1a52aeaa5987\">Setzt ihr auf C f\u00fcr eingebettete Systeme? Toll, andere haben einst aufs Pferd gesetzt! <br><strong>&#8222;Ich setze aufs Pferd!&#8220; &#8211; Kaiser Wilhelm II.<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">Der Fehler war, dass ich PA1 statt PA9 als Peripherie ausgew\u00e4hlt habe. In C h\u00e4tte ich zur Laufzeit irgendwas beobachtet, oder wahrscheinlicher: Ich h\u00e4tte nichts beobachtet, und mich dann voller Verwunderung auf die Fehlersuche begeben. Danke Rust! <\/p>\n\n\n\n<p class=\"has-medium-font-size\">Asynchrone eingebettete Programmierung also, aber was ist asynchrone Programmierung, \u00fcberhaupt?<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Was ist asynchrone Programmierung<\/h2>\n\n\n\n<p class=\"has-medium-font-size\">Anstatt asynchrone Programmierung zu definieren, legen wir erst fest was synchrone Programmierung bedeutet. Und zwar, dass ein Funktionsaufruf blockiert &#8211; also der Funktionsaufruf wird abgeschlossen und dann wird der n\u00e4chste Funktionsaufruf ausgef\u00fchrt. Der Code unten l\u00e4uft von oben nach unten ab, also so wie er gelesen wird. Das ist so intuitiv, das diese Erkl\u00e4rung wohl eher verwirrt.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Nehmen wir an Funktionen fragen Datenbanken ab, laden eine Datei herunter oder warten auf einen Sensorwert, der \u00fcber den I2C Bus gesendet wird. Die CPU hat nichts zutun, aber man wartet auf Speicher oder Kommunikation. In der Zeit w\u00e4re es sch\u00f6n die CPU-Zeit in eine andere Aufgabe zu stecken.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error&gt;&gt; {\n    let reval_a = my_func_a();\n    let reval_b = my_func_b();\n    printnln!(\"A={}, B={}\", reval_a, reval_b);\n}<\/code><\/pre>\n\n\n\n<p class=\"has-medium-font-size\">Bei der asynchronen Programmierung st\u00f6\u00dft ein asynchroner Funktionsaufruf eine Aufgabe an, die zu einem gegebenen Zeitpunkt von einem Executor ausgef\u00fchrt wird. So kann es sein dass in dem Code unten die Funktion my_async_b zuerst berechnet wird. Wichtig ist: Im asynchronen Rust findet der Funktionsaufruf nur statt wenn das Ergebnis explizit angefragt wird.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Im Code unten wird die asynchrone Laufzeit von <a href=\"https:\/\/tokio.rs\/\">Tokio<\/a> verwendet. Man sieht so etwas meistens im Zusammenhang mit Server\/Client Anwendungen. Durch den Aufruf der beiden Funktionen passiert erstmal nichts. Damit etwas passiert muss mittels await oder dem join! Makro das Future explizit angefragt werden (Das ist anders als in C++). F\u00fcr die eingebettete Programmierung, die meist nur einen Rechenkern verwendet, ist es sinnvoll den Unterschied zwischen Parallelen und Nebenl\u00e4ufigen Programmfluss zu erkl\u00e4ren.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#&#91;tokio::main]\nasync fn main() -&gt; Result&lt;(), Box&lt;dyn std::error::Error&gt;&gt; {\n    let future_a = my_async_func_a();\n    let future_b = my_async_func_b();\n\n    let (reval_a, reval_b) = join!(future_a, future_b);\n    println!(\"A={}, B={}\", reval_a, reval_b);\n\n    let reval_c = my_async_func_c().await;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading has-medium-font-size\">Nebenl\u00e4ufigkeit und Parallelit\u00e4t<\/h3>\n\n\n\n<p class=\"has-medium-font-size\">Eine Asynchrone Runtime erzeugt eine nebenl\u00e4ufige Ausf\u00fchrung. Wichtig: Dies ist auch mit einem einzigen Thread oder einem einzigen Rechenkern m\u00f6glich. Insbesondere in eingebetteter Hardware wird h\u00e4ufig ein Chip mit nur einem Rechenkern verbaut. Dies ist auch der Fall f\u00fcr den STM32 Chip auf dem hier verwendeten NUCLEO-Board.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Eine parallele Ausf\u00fchrung ist erst m\u00f6glich sobald mehr als einen Rechenkern verf\u00fcgbar ist. In dem Fall k\u00f6nnte ein Executor Funktion a und b gleichzeitig auf verschiedenen Kernen ausf\u00fchren. Im Falle eines Single-Cores verh\u00e4lt es sich wie in den Betriebssystemen in den 90igern. Das bedeutet ein Arbeiter wechselt die Aufgaben und weil CPUs und MCUs so schnell sind wirkt es auf uns gleichzeitig oder parallel. Dabei entspricht der Prozess-Scheduler eines Betriebssystems hier einer asynchronen Runtime, z.B. Tokio oder Embassy. Die Bearbeitung der Aufgaben\/Funktionen kann sich \u00fcberlappen, es ist aber weder Gleichzeitigkeit n\u00f6tig noch garantiert.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Das typische Einsatzszenario f\u00fcr asynchrone Programmierung ist ein Webserver mit vielen Anfragen und langen Wartezeiten aufgrund von Ein und Ausgaben, wie das Auslesen einer Datenbank oder der Zugriff auf eine Datei auf einem anderen Server.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Jedoch wird genau dieses Prinzip von Embassy f\u00fcr eingebettete Systeme genutzt, um z. B. mehrere Sensoren und Kommunikationsaufgaben zeitgleich zu organisieren, ohne einen echten Betriebssystem-Scheduler zu ben\u00f6tigen. Wir erhalten also einige Features eines Echtzeit-Betriebssystem (RTOS). <\/p>\n\n\n\n<p class=\"has-medium-font-size\">Das ist asynchrone eingebettete Programmierung. Danke Embassy!<\/p>\n\n\n\n<p class=\"has-text-align-center has-white-color has-black-background-color has-text-color has-background has-link-color has-medium-font-size wp-elements-5c4663d6a8df0e4863450349cffed1ec\">Mit Rust durchstarten? Wir unterst\u00fctzen euch gerne! Vereinbart ein <a href=\"https:\/\/cal.com\/timjanus\/25min\">unverbindliches Erstgespr\u00e4ch<\/a>.<br><strong>Oder gebt uns <a href=\"https:\/\/www.paypal.com\/paypalme\/TimJanus\">unverbindlich ein Mittagessen<\/a> aus!<\/strong><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h3 class=\"wp-block-heading has-medium-font-size\">Synchrone Programmierung<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\">Funktion kehrt erst nach Abschluss der Berechnung zur\u00fcck<\/li>\n\n\n\n<li class=\"has-medium-font-size\">R\u00fcckgabewert ist tats\u00e4chlicher R\u00fcckgabe<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Reihenfolge der Aufrufe wohldefiniert<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Programmfluss ist deutlich einfacher nachzuvollziehen<\/li>\n<\/ul>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h3 class=\"wp-block-heading\">Asynchrone Programmierung<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"has-medium-font-size\">Funktion kehrt sofort zur\u00fcck<\/li>\n\n\n\n<li class=\"has-medium-font-size\">R\u00fcckgabewert ist &#8222;In Arbeit&#8220; oder &#8222;Erledigt&#8220;, der tats\u00e4chliche R\u00fcckgabewert ist nur im Zustand &#8222;Erledigt&#8220; abrufbar.<\/li>\n\n\n\n<li class=\"has-medium-font-size\">Funktion b k\u00f6nnte ihre Berechnung vor Funktion a abschlie\u00dfen<\/li>\n<\/ul>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Asynchrone eingebettete Programmierung mit Embassy<\/h2>\n\n\n\n<p class=\"has-medium-font-size\">Anders als Tokio ist Embassy auf bare-metal Hardware ausgelegt. Anstatt klassischer Threads, die vom Betriebssystem verwaltet werden, greift Embassy auf eine eigene Scheduler Implementierung zur\u00fcck, die auf Hardware Interrupts oder nutzerspezifischen Synchronisierungen, wie Timer oder Signale, reagiert um aufzuwachen. Dies bietet eine hervorragende Grundlage um Energie zu sparen, denn dank dieser Konzepte ist klar wann die CPU in den Sleep geschickt werden darf und sollte.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Weitere wichtige Konzepte sind die Tasks, die dem Scheduler \u00fcbergeben werden. Tasks sind letztendlich asynchrone Rust Funktionen. Synchronisationsprimitiven wie Signale, Channels und Mutexes, erm\u00f6glichen es Tasks Daten auszutauschen. Damit erh\u00e4lt man Features wie in einem RTOS (Echtzeit-Betriebssystem) aber mit einem deutlich geringeren Footprint. <\/p>\n\n\n\n<p class=\"has-medium-font-size\">Im Gegensatz zu einem klassischen RTOS wie FreeRTOS oder Zephyr nutzt Embassy rein Rust-eigene Konzepte wie async\/await, Channels, Signals und Timer. Nat\u00fcrlich gibt es Anwendungsf\u00e4lle bei denen man nicht um ein RTOS herumkommt, da das kooperative Scheduling auch mit einer High-Priority Variante immer erst auf einen Task-Abschluss warten muss, so dass absolut harte Echtzeit-Anforderungen im ms Bereich gegebenfalls nicht gehalten werden k\u00f6nnen.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Nun gut, aber wie nutzt man Embassy?<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-medium-font-size\">Aufsetzen der Peripherie, Interrupts und Tasks<\/h3>\n\n\n\n<p class=\"has-medium-font-size\">Embassy Nutzer k\u00f6nnen in der Main Funktion Tasks &#8222;spawnen&#8220; und diese werden standardm\u00e4\u00dfig kooperativ in einem Scheduler ausgef\u00fchrt. F\u00fcr Echtzeitkritische Module ist der Einsatz eines weiteren High-Priority Schedulers m\u00f6glich.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Aber lasst uns das Code-Snippet unten untersuchen. Die Main Funktion wird wie bei Tokio, nur diesmal mit #[embassy_executor::main], annotiert. Zuerst wird eine Representation der STM32 Peripherie mit einem init Aufruf erzeugt. Dann verkettet das Makro <code>bind_interrupts!<\/code> unsere Peripherie (USART, I2C) mit den entsprechenden Interrupt-Routinen von Embassy. <\/p>\n\n\n\n<p class=\"has-medium-font-size\">Bei usart handelt es sich um einen Treiber f\u00fcr die serielle Kommunikation mit einem Computer. Im Falle des NUCLEO Boards wird hierf\u00fcr die USB-Verbindung verwendet. Mit der Funktion split k\u00f6nnen Empf\u00e4nger und Transmitter an unterschiedliche Tasks \u00fcbergeben werden. Falls mehr als ein Task senden oder Transmitten soll ist die Sicherstellung der Synchronisierung, z.B. mittels Mutex, n\u00f6tig. Anderenfalls wird der Rust-Compiler eine Fehlermeldung ausgeben.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Wir konzentrieren uns in diesem Artikel Ausschnitte f\u00fcr mehr Details schaut euch den kompletten Code in <a href=\"https:\/\/github.com\/DarthB\/rust_embedded\/tree\/main\">GitHub <\/a>an. Der Task uart_status_report_transmitter verwendet den uarts Transmitter tx um Status-Reports zu senden. Der zweite Task uart_receiver_and_cmd_forwarder wird eingesetzt um Nachrichten von einem Rechner zu empfangen. Bisher haben wir die Channel und Signale im Code ignoriert. Dabei sind diese, neben Timer, unsere Werkzeuge um Nebenl\u00e4ufigkeit zu verwenden, <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#&#91;embassy_executor::main]\nasync fn main(spawner: Spawner) {\n    let p = embassy_stm32::init(Default::default());\n    \/\/...\n     \/\/ bind interrupts\n    bind_interrupts!(struct Irqs {\n        USART3 =&gt; embassy_stm32::usart::InterruptHandler&lt;embassy_stm32::peripherals::USART3&gt;;\n        I2C1_EV =&gt; embassy_stm32::i2c::EventInterruptHandler&lt;embassy_stm32::peripherals::I2C1&gt;;\n        I2C1_ER =&gt; embassy_stm32::i2c::ErrorInterruptHandler&lt;embassy_stm32::peripherals::I2C1&gt;;\n    });\n    let mut usart = setup_usart_developer_console!(p, Irqs, UsartConfig::default());\n    \/\/ ...\n    \/\/ spawn a task for uart sending and receiving each\n    let (tx, rx) = usart.split();\n    spawner.spawn(uart_receiver_and_cmd_forwarder(rx, CHANNEL_COMMANDS.sender())).unwrap();\n    spawner.spawn(uart_status_report_transmitter(tx)).unwrap();\n    \/\/ ...\n    spawner.spawn(process_light_sensor(\n        &amp;LIGHT_SENSOR_SIGNAL,\n        i2c\n    )).unwrap();\n    \/\/ ...\n    loop {\n        button.wait_for_rising_edge().await;\n     CHANNEL_COMMANDS.sender().send(Commands::LightSensor(LightSensorCommands::SingleMeasurment)).await;\n        Timer::after(Duration::from_millis(50)).await;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"has-medium-font-size\">Bisher wissen wir nur wie Tasks aufgesetzt werden, der Vorteil Asynchrone eingebettete Programmierung spielt sich jedoch durch die Interaktion der Tasks aus.<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-medium-font-size\">Interaktion zwischen Tasks<\/h3>\n\n\n\n<p class=\"has-medium-font-size\">Mit der Hilfe von Channels und anderen Synchronisationsmechanismen, wie Signal, ist eine Event-artige Kommunikation zwischen den Tasks m\u00f6glich. Weiterhin ist das Teilen von Daten, die mittels eines Mutexes synchronisiert werden, m\u00f6glich.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Im Code-Block oben sind die Variablen CHANNEL_COMMANDS und LIGHT_SENSOR_SIGNAL  f\u00fcr die Abgabe des Kontrollflusses und somit die Steuerung des Schedulers und der Kommunikation zwischen Tasks zust\u00e4ndig.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">So werden Kommandos von dem uart Empf\u00e4nger Task uart_receiver_and_command_forwarder an einem Task zur Verarbeitung von Kommandos weitergeleitet (nicht im Ausschnitt zu sehen). Es ist m\u00f6glich mehrere Sender zu verwenden, wie unten in der Schleife, die pr\u00fcft ob der User-Button bet\u00e4tigt wurde. Wenn das der Fall ist wird erst der Kommando Prozessor informiert, der dann ein LIGHT_SENSOR_SIGNAL ausl\u00f6st um einen einzelnen Sensorwert zu ermitteln. <\/p>\n\n\n\n<p class=\"has-text-align-center has-white-color has-black-background-color has-text-color has-background has-link-color has-medium-font-size wp-elements-cfe73eb7c78838ade482ed14358c6a66\"><a href=\"https:\/\/doc.rust-lang.org\/book\/ch16-02-message-passing.html\">Channels<\/a> sind ein wichtiges Konzept f\u00fcr die Angstfreie Nebenl\u00e4ufigkeit und Parallelit\u00e4t in Rust.<br><strong>Gerade den \u00e4ngstlichen Deutschen w\u00fcrde etwas Angstfreiheit gut tun! Was denkst du?<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\">Im folgendem untersuchen wir wie LIGHT_SENSOR_SIGNAL die Abgabe des Programmflusses zur\u00fcck an den Scheduler an im process_light_sensor Task umsetzt. Der Code-Block unten illustriert zwei F\u00e4lle: Im einfacheren Fall, wenn nur ein Messwert ausgelesen wird auf ein Signal gewartet. <\/p>\n\n\n\n<p class=\"has-medium-font-size\">Im zweiten Fall, wird entweder auf neue Werte auf dem I2C Bus gewartet oder reagiert wenn das LIGHT_SENSOR_SIGNAL ausgel\u00f6st wird. Weiter wird noch illustriert wie man Timer verwenden kann um den Kontrollfluss zur\u00fcck an den Scheduler zu geben. <\/p>\n\n\n\n<pre class=\"wp-block-code has-medium-font-size\"><code>\/\/ in non-continuous modes:\nLightSensorState::PowerOff | LightSensorState::SingleMeasurement =&gt; signal.wait().await,\n\/\/ ...\n\/\/ in continuous sending mode\nlet f1 = i2c.read(BH1750_ADDR_L, &amp;mut rx_buf);\nlet f2 = signal.wait();\nselect(f1, f2).await \n\/\/ ...\nTimer::after(Duration::from_millis(150)).await;<\/code><\/pre>\n\n\n\n<p class=\"has-medium-font-size\">Ein Embassy Nutzer kann also dem Scheduler mittels await mitteilen, dass die aktuelle Funktion warten muss und so modularen Code aufgeteilt in verschiedene Tasks schreiben, die mittels Events wie Channels oder Signals untereinander kommunizieren.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">Fazit<\/h2>\n\n\n\n<p class=\"has-medium-font-size\">Rust und das Embassy Framework denken eingebettete Programmierung neu und machen so asynchrone eingebettete Programmierung Salon-f\u00e4hig. Embassy ist Teil der no_std-Welt und setzt auf die Rust Embedded-HAL auf, um Treiber (I2C, SPI, UART) asynchron anzubinden.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">Das Framework wird erfolgreich von der <a href=\"https:\/\/akiles.app\/en\">Firma Akiles<\/a> eingesetzt und hat das Potenzial viele Anwendungsf\u00e4lle in eingebetteten System besser umzusetzen als eine reine C-L\u00f6sung. <\/p>\n\n\n\n<p class=\"has-medium-font-size\">F\u00fcr absolut harte Sicherheitsrelevante Echtzeitanforderungen im kleinen Millisekunden Bereich ist Embassy nicht geeignet und es wird ein echtes RTOS ben\u00f6tigt. Die meisten Use-Cases werden nicht so strikte Anforderungen haben und k\u00f6nnen dank Embassy Features eines RTOS mit kaum Overhead erhalten. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Eine Revolution: Entdecke Asynchrone eingebettete Programmierung in Rust in Embassy mit STM32, Sensoren und Praxistipps. Liebe Leser, ich hoffe ihr hattet erholsame Feiertage und seid gut ins neue Jahr 2025 gekommen. Ich m\u00f6chte keinen typischen Neujahrs Motivation-Artikel schreiben, sondern wieder etwas Wissen mit euch teilen. Ok, den ein oder anderen Kommentar konnte ich mir nicht [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1529,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ocean_post_layout":"right-sidebar","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"","ocean_second_sidebar":"","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"","ocean_custom_header_template":"","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"","ocean_menu_typo_font_family":"","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"","_jetpack_memberships_contains_paid_content":false,"ocean_post_oembed":"","ocean_post_self_hosted_media":"","ocean_post_video_embed":"","ocean_link_format":"","ocean_link_format_target":"self","ocean_quote_format":"","ocean_quote_format_link":"post","ocean_gallery_link_images":"on","ocean_gallery_id":[],"footnotes":""},"categories":[9],"tags":[26,13,39],"class_list":["post-1525","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-entwicklung","tag-effizienz","tag-rust","tag-sicherheit","entry","has-media"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Asynchrone eingebettete Programmierung - \u00fcber die Festtage - Janus IT<\/title>\n<meta name=\"description\" content=\"Eine Revolution: Entdecke Asynchrone eingebettete Programmierung in Rust in Embassy mit STM32, Sensoren und Praxistipps.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/janus.rs\/en\/2025\/01\/the-unusual-festive-days-asynchronous-embedded-programming\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Asynchrone eingebettete Programmierung - \u00fcber die Festtage - Janus IT\" \/>\n<meta property=\"og:description\" content=\"Eine Revolution: Entdecke Asynchrone eingebettete Programmierung in Rust in Embassy mit STM32, Sensoren und Praxistipps.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/janus.rs\/en\/2025\/01\/the-unusual-festive-days-asynchronous-embedded-programming\/\" \/>\n<meta property=\"og:site_name\" content=\"Janus IT\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-14T19:10:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-01-14T19:10:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"2560\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tim Janus\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@DarthB86\" \/>\n<meta name=\"twitter:site\" content=\"@DarthB86\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tim Janus\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/\"},\"author\":{\"name\":\"Tim Janus\",\"@id\":\"https:\/\/janus.rs\/en\/#\/schema\/person\/a4844f3174ecb193eccd444867233aef\"},\"headline\":\"Die etwas anderen Festtage\",\"datePublished\":\"2025-01-14T19:10:36+00:00\",\"dateModified\":\"2025-01-14T19:10:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/\"},\"wordCount\":2268,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/janus.rs\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1\",\"keywords\":[\"Effizienz\",\"Rust\",\"Sicherheit\"],\"articleSection\":[\"Software Entwicklung\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/\",\"url\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/\",\"name\":\"Asynchrone eingebettete Programmierung - \u00fcber die Festtage - Janus IT\",\"isPartOf\":{\"@id\":\"https:\/\/janus.rs\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1\",\"datePublished\":\"2025-01-14T19:10:36+00:00\",\"dateModified\":\"2025-01-14T19:10:41+00:00\",\"description\":\"Eine Revolution: Entdecke Asynchrone eingebettete Programmierung in Rust in Embassy mit STM32, Sensoren und Praxistipps.\",\"breadcrumb\":{\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1\",\"width\":1920,\"height\":2560},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/janus.rs\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Die etwas anderen Festtage\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/janus.rs\/en\/#website\",\"url\":\"https:\/\/janus.rs\/en\/\",\"name\":\"Janus IT\",\"description\":\"Software Engineering\",\"publisher\":{\"@id\":\"https:\/\/janus.rs\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/janus.rs\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/janus.rs\/en\/#organization\",\"name\":\"Janus IT\",\"url\":\"https:\/\/janus.rs\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/janus.rs\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2023\/01\/logo_only_color_nobg.png?fit=900%2C900&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2023\/01\/logo_only_color_nobg.png?fit=900%2C900&ssl=1\",\"width\":900,\"height\":900,\"caption\":\"Janus IT\"},\"image\":{\"@id\":\"https:\/\/janus.rs\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/DarthB86\",\"https:\/\/www.linkedin.com\/in\/tim-janus-07523b13\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/janus.rs\/en\/#\/schema\/person\/a4844f3174ecb193eccd444867233aef\",\"name\":\"Tim Janus\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/janus.rs\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c10bd363a36d45bc7a93771d86419edde82a41a77360c739a3eded5b41592c20?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c10bd363a36d45bc7a93771d86419edde82a41a77360c739a3eded5b41592c20?s=96&d=mm&r=g\",\"caption\":\"Tim Janus\"},\"sameAs\":[\"http:\/\/s916043165.online.de\"],\"url\":\"https:\/\/janus.rs\/en\/author\/darthb86\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Asynchronous embedded programming - over the festive season - Janus IT","description":"A revolution: Discover asynchronous embedded programming in Rust in Embassy with STM32, sensors and practical tips.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/janus.rs\/en\/2025\/01\/the-unusual-festive-days-asynchronous-embedded-programming\/","og_locale":"en_US","og_type":"article","og_title":"Asynchrone eingebettete Programmierung - \u00fcber die Festtage - Janus IT","og_description":"Eine Revolution: Entdecke Asynchrone eingebettete Programmierung in Rust in Embassy mit STM32, Sensoren und Praxistipps.","og_url":"https:\/\/janus.rs\/en\/2025\/01\/the-unusual-festive-days-asynchronous-embedded-programming\/","og_site_name":"Janus IT","article_published_time":"2025-01-14T19:10:36+00:00","article_modified_time":"2025-01-14T19:10:41+00:00","og_image":[{"width":1920,"height":2560,"url":"https:\/\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg","type":"image\/jpeg"}],"author":"Tim Janus","twitter_card":"summary_large_image","twitter_creator":"@DarthB86","twitter_site":"@DarthB86","twitter_misc":{"Written by":"Tim Janus","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#article","isPartOf":{"@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/"},"author":{"name":"Tim Janus","@id":"https:\/\/janus.rs\/en\/#\/schema\/person\/a4844f3174ecb193eccd444867233aef"},"headline":"Die etwas anderen Festtage","datePublished":"2025-01-14T19:10:36+00:00","dateModified":"2025-01-14T19:10:41+00:00","mainEntityOfPage":{"@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/"},"wordCount":2268,"commentCount":0,"publisher":{"@id":"https:\/\/janus.rs\/en\/#organization"},"image":{"@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1","keywords":["Effizienz","Rust","Sicherheit"],"articleSection":["Software Entwicklung"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/","url":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/","name":"Asynchronous embedded programming - over the festive season - Janus IT","isPartOf":{"@id":"https:\/\/janus.rs\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage"},"image":{"@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1","datePublished":"2025-01-14T19:10:36+00:00","dateModified":"2025-01-14T19:10:41+00:00","description":"A revolution: Discover asynchronous embedded programming in Rust in Embassy with STM32, sensors and practical tips.","breadcrumb":{"@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#primaryimage","url":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1","contentUrl":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1","width":1920,"height":2560},{"@type":"BreadcrumbList","@id":"https:\/\/janus.rs\/2025\/01\/die-etwas-anderen-festtage-asynchrone-eingebettete-programmierung\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/janus.rs\/"},{"@type":"ListItem","position":2,"name":"Die etwas anderen Festtage"}]},{"@type":"WebSite","@id":"https:\/\/janus.rs\/en\/#website","url":"https:\/\/janus.rs\/en\/","name":"Janus IT","description":"Software Engineering","publisher":{"@id":"https:\/\/janus.rs\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/janus.rs\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/janus.rs\/en\/#organization","name":"Janus IT","url":"https:\/\/janus.rs\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/janus.rs\/en\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2023\/01\/logo_only_color_nobg.png?fit=900%2C900&ssl=1","contentUrl":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2023\/01\/logo_only_color_nobg.png?fit=900%2C900&ssl=1","width":900,"height":900,"caption":"Janus IT"},"image":{"@id":"https:\/\/janus.rs\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/DarthB86","https:\/\/www.linkedin.com\/in\/tim-janus-07523b13\/"]},{"@type":"Person","@id":"https:\/\/janus.rs\/en\/#\/schema\/person\/a4844f3174ecb193eccd444867233aef","name":"Tim Janus","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/janus.rs\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/c10bd363a36d45bc7a93771d86419edde82a41a77360c739a3eded5b41592c20?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c10bd363a36d45bc7a93771d86419edde82a41a77360c739a3eded5b41592c20?s=96&d=mm&r=g","caption":"Tim Janus"},"sameAs":["http:\/\/s916043165.online.de"],"url":"https:\/\/janus.rs\/en\/author\/darthb86\/"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/janus.rs\/wp-content\/uploads\/2025\/01\/nucleo_and_bread_board-scaled.jpg?fit=1920%2C2560&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/posts\/1525","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/comments?post=1525"}],"version-history":[{"count":12,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/posts\/1525\/revisions"}],"predecessor-version":[{"id":1545,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/posts\/1525\/revisions\/1545"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/media\/1529"}],"wp:attachment":[{"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/media?parent=1525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/categories?post=1525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/janus.rs\/en\/wp-json\/wp\/v2\/tags?post=1525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}