Finally, the "we" 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.
We talk about first contact with the Rust programming language, coroutines for implementing lightweight tasks/threads, various smaller topics and some upcoming events.
Links:
- Rust programming language:
- Discover the world of microcontrollers through Rust!
- The Embedded Rust Book
- LLVM Intermediate representation
- Coroutines / protothreads:
- Coroutines and simpler protothreads for building stackless cooperative tasks
- Protothreads under the hood: Duff's device or GCC's computed goto
- convoluted example: 6502 asm + Tcl = protothreads
- short video of VGA generator board in action
- RetroChallenge 2019/03 (whole month of March) is open
- Maker Faire Ruhr (DASA, Dortmund, DE): 23+24 March
- HCC!retro meeting (Bilthoven, NL): 16 March
Here's a code snippet hopefully illustrating what I called "coroutines" and should probably have been called "protothreads".
Function "print_2nd_word" 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 = &&lbl_crstart; goto *jmp; lbl_crstart: ( void )jmp; #define CR_YIELD do { jmp = &&GLUE( lbl, __LINE__ ); return; GLUE( lbl, __LINE__ ): ( void )jmp; } while ( 0 )
"CR_BEGIN" is basically setup-code.
"CR_YIELD" 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 "CR_YIELD".
Note that these macros use GCC's "computed gotos" (i.e. take the address of a C label, and jump to that address using "goto"). 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 "CR_END" is necessary as glue to conform to C syntax/nesting.)
Funfact: it's a bit of a PITA to add sourcecode to this page.