{"version":1,"type":"rich","provider_name":"Libsyn","provider_url":"https:\/\/www.libsyn.com","height":90,"width":600,"title":"episode 34: Rust, coroutines and cohosting","description":"Finally, the &quot;we&quot; in announcements doesn't just mean the royal we \/ majestic plural, but there's an actual co-host! Introduction is in the audio contents, so I guess you'll just have to listen. &amp;lt;\/clickbait&amp;gt; We talk about first contact with the Rust programming language, coroutines for implementing lightweight tasks\/threads, various smaller topics and some upcoming events.&amp;nbsp; Links:  Rust programming language:  Discover the world of microcontrollers through Rust! The Embedded Rust Book LLVM Intermediate representation   Coroutines \/ protothreads:  Coroutines&amp;nbsp;and simpler&amp;nbsp;protothreads&amp;nbsp;for building stackless cooperative tasks Protothreads under the hood:&amp;nbsp;Duff's device&amp;nbsp;or&amp;nbsp;GCC's computed goto  convoluted example: 6502 asm + Tcl = protothreads   short video of&amp;nbsp;VGA generator board in action RetroChallenge 2019\/03&amp;nbsp;(whole month of March) is open Maker Faire Ruhr&amp;nbsp;(DASA, Dortmund, DE): 23+24&amp;nbsp;March HCC!retro meeting&amp;nbsp;(Bilthoven, NL): 16&amp;nbsp;March  Here's a code snippet hopefully illustrating what I called &quot;coroutines&quot; and should probably have been called &quot;protothreads&quot;. Function &quot;print_2nd_word&quot; is a protothread. It can be called repeatedly passing a character each time. Only the 2nd word is printed, one character at a time.       void print_2nd_word( char c )    {        CR_BEGIN;                    while ( c != ' ' )           CR_YIELD;           CR_YIELD; \/\/ skip space           while ( c != ' ' ) {            putchar( c );            CR_YIELD;        }    }   To do this, the function keeps track of where it exited last time it was called, using a number of macros:       #define CR_BEGIN static void *jmp = &amp;amp;&amp;amp;lbl_crstart; goto *jmp; lbl_crstart: ( void )jmp;    #define CR_YIELD do { jmp = &amp;amp;&amp;amp;GLUE( lbl, __LINE__ ); return; GLUE( lbl, __LINE__ ): ( void )jmp; } while ( 0 )   &quot;CR_BEGIN&quot; is basically setup-code. &quot;CR_YIELD&quot; is the simplest primitive in this context, and does: exit the protothread function, and resume at this point next time it's called. More advanced macros - e.g. to repeatedly wait for an event - can be built on top of, or in the same way as &quot;CR_YIELD&quot;. Note that these macros use GCC's &quot;computed gotos&quot; (i.e. take the address of a C label, and jump to that address using &quot;goto&quot;). Here's an implementation of both macros using ANSI C:       #define CR_BEGIN static int cr_st = 0; switch( cr_st ) { case 0: ;    #define CR_YIELD do { cr_st = __LINE__; return; case __LINE__: ; } while( 0 )    #define CR_END CR_YIELD; }   (In this case, an additional macro &quot;CR_END&quot; is necessary as glue to conform to C syntax\/nesting.) &amp;nbsp; Funfact: it's a bit of a PITA to add sourcecode to this page. ","author_name":"CBA Podcast","author_url":"http:\/\/podcast.cba.si","html":"<iframe title=\"Libsyn Player\" style=\"border: none\" src=\"\/\/html5-player.libsyn.com\/embed\/episode\/id\/8624468\/height\/90\/theme\/custom\/thumbnail\/yes\/direction\/forward\/render-playlist\/no\/custom-color\/88AA3C\/\" height=\"90\" width=\"600\" scrolling=\"no\"  allowfullscreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen><\/iframe>","thumbnail_url":"https:\/\/assets.libsyn.com\/secure\/item\/8624468"}