Visual Programming with Embedded Rust on Super Blue Pill: https://medium.com/swlh/super-blue-pill-like-stm32-blue-pill-but-better-6d341d9347da

Visual Programming with Embedded Rust? Yes we can with Apache Mynewt and Google Blockly!

Lup Yuen Lee 李立源
Jul 11 · 9 min read

I gotta admit — Embedded Programs are getting darned hard to code on modern microcontrollers, sensors and networks. Faced with the ultra-daunting task of coding a readable, reusable, open-source NB-IoT application for STM32, I asked myself… Could Visual Programming with Embedded Rust solve this problem? Like this…

Visual Programming with Embedded Rust

Try it for yourself here:

Let’s talk about the components necessary for this visual Rust solution…

1️⃣ Google Blockly, the visual coding tool

2️⃣ Apache Mynewt, the embedded OS

3️⃣ And all the integration bits: Custom code blocks, code generation, safe wrappers, …

The source code is available here…

Google Blockly

Blockly is an awesome open-source tool for visual coding, as shown in the above demo. It’s used by kids for BBC micro:bit programming, also used by makers for creating Embedded JavaScript apps on the MakeCode platform.

It’s easy to clone the Blockly repository, open in a web browser and test the visual programming tool ourselves. Unfortunately Blockly doesn’t generate Rust code today. We’ll discuss Rust code generation in a while.

Apache Mynewt

Recall the problem we are solving… Creating Embedded Apps easily for Bare Metal microcontrollers (like STM32 Blue Pill). Our Embedded Rust Apps will have to access Bare Metal functions like GPIO, I2C, SPI, … And network peripherals like ESP8266, nRF24L01, BC95-G, …

Can we use Rust drivers to access these functions? Not quite — today we don’t have a comprehensive collection of Embedded Rust drivers. Given that the Embedded Rust platform is still in flux, it may be risky to adopt Embedded Rust drivers now.

So let’s pick a modern embedded real-time OS (built with C) and build Rust wrappers around it. I have chosen Apache Mynewt. We’ll talk about the Rust Safe Wrappers in a while. Meanwhile find out how I integrated Rust with Mynewt in this article.

Blockly Blocks

A visual program in Blockly consists of Blocks connected together.

The screenshot here shows three GPIO Blocks that we have created specially for creating Embedded Rust apps.

How are Blocks created? Through the Block Factory, which looks like another Blockly app. The Block Library we have created is located at

After building the Blocks, we click the Block Exporter to export the Blocks into two files…

1️⃣ : Block Definitions in JSON

2️⃣ : Code Generator Functions for the Blocks

Block Exporter
From https://github.com/lupyuen/blockly-mynewt-rust/blob/master/generators/rust/mynewt_blocks.js#L1

Block Definition

Here’s the Block Definition for the Block. The Block toggles a GPIO pin from Low to High and vice versa. The Block was exported by the Block Exporter.

The Block is defined with one input named : a dropdown for a list of pins (like ), which will be dynamically populated in the real visual programming tool.

In the Block Factory, the Block was defined as . Which means that it’s meant to be used like a program statement, with (optional) Statement Blocks preceding and following the Block.

Each Block requires a Code Generation Function to generate the code for the Block. More about this…

Copying the Code Generator from Dart to Rust

Rust Code Generation

When this demo was created, Blockly did not have a Rust Code Generator. So I copied the Dart Code Generator into these locations…

: Main Code Generator for Rust

: Rust Code Generators for the Standard and Custom Blocks

The Main Code Generator for Rust looks like this (yes Blockly runs on JavaScript)…

From https://github.com/lupyuen/blockly-mynewt-rust/blob/master/generators/rust.js

We have seen this code earlier in the demo — this is the function that’s generated before all other Blocks.

Code Generators are really simple text processors in Blockly. We see here that it’s appending the function to another chunk of code that was generated by other Blocks…

Blocks like and will use a similar Code Generator that embeds an inner chunk of code.

Every Block in Blockly needs a Code Generator Function to emit Rust code for the Block, even Common Blocks like , , , …. Here’s the Code Generator Function for

From https://github.com/lupyuen/blockly-mynewt-rust/blob/master/generators/rust/mynewt_functions.js#L73-L83

Remember that the Block accepts one parameter , the GPIO pin to be toggled? Here’s how we fetch the parameter and embed it into the code. The output looks like this…

//  Toggle the GPIO pin
gpio::toggle(MCU_GPIO_PORTC!(13)) ? ;

For more details on Blockly Code Generation, check this article.

Customising Blockly

We isolate any changes to the Blockly source code so that we may enjoy future Blockly upgrades (via )…

1️⃣ contains the Rust Code Generator

2️⃣ is the Blockly demo in HTML that we have customised for Rust

From https://github.com/lupyuen/blockly-mynewt-rust/blob/master/demos/code/index.html#L16-L31

3️⃣ has been updated to load our Rust Code Block Definitions and Rust Code Generator

Safe Wrappers in Rust

What makes a great Embedded Programming experience? Safe and simple coding…

1️⃣ Safe Coding: We shall prevent programmers from falling into traps that they don’t know how to escape. Pointers in Embedded C is a very serious trap.

2️⃣ Simple Coding: Coding shall look intuitive, even though in reality it’s complicated. Like automatically ensuring that all strings passed from Rust to C functions are null-terminated.

The solution: Create Safe Wrappers in Rust to wrap up the risky, complex parts of the Mynewt API. It’s possible to generate Safe Wrappers for Mynewt APIs automatically via and Rust Procedural Macros. Learn more about this here.

And once we have implemented Visual Programming in Embedded Rust, coding can’t get any simpler!

Safer and Simpler Coding: Why do this (left)… when we can do that (right)? From https://medium.com/@ly.lee/safer-simpler-embedded-rust-with-apache-mynewt-on-stm32-blue-pill-d8fcb41969ac

Rusty Round Trip

“When she’s coming round the mountain… will she be the same?”

Ever since the 1980s, software engineers have been concerned about Round-Trip Engineering… If we make any changes to the generated Rust source code, can the Visual Programming Tool apply the same changes back into the original Visual Program? Such that both Visual and Textual Programs are always synchronised?

It’s a difficult problem — there are so many Rust Programs that can’t possibly be expressed as a Visual Program!

But it’s easier to solve in Rust. In my previous article I wrote about the Crate that parses Rust source code. This could be used to discover changes in the generated Rust source code and (hopefully) make (sensible) updates (automatically) to the Visual Program.

This might work by embedding as a WebAssembly module inside the Blockly JavaScript code! How cool is that?!

MakeCode has some support (though not perfect) for JavaScript Round-Tripping. Try it here

Why Visual Rust?

Why not Visual JavaScript? Visual MicroPython? Visual C?

I have experimented with Visual Embedded Programming in JavaScript (here, here, here, here, here, here and here)… It’s just too darned hard!

1️⃣ Embedded JavaScript (and Static TypeScript) is way too bloated to run on popular but constrained microcontrollers like STM32 Blue Pill. Same for MicroPython.

2️⃣ Embedded JavaScript (and MicroPython) needs to be hosted on a proper realtime operating system (RTOS). Which adds to the bloat.

3️⃣ Embedded C, hosted on a suitable RTOS, has zero bloat but it’s too unsafe for today’s embedded programmers.

Visual Programming with Embedded Rust + Apache Mynewt is the perfect compromise: safe and simple coding, compiles into compact Arm machine code, very little bloat. Yet it’s sufficiently sophisticated to support Round-Tripping, NB-IoT with CoAP and CBOR, …

So why aren’t we doing Visual Rust Programming today and moving out of Embedded C forever…?

Run The Demo

To run the Visual Rust demo, click here:

To make your own changes, clone this repository…

Then edit the files in Visual Studio Code and open the local copy of in a web browser.

For this visual program…

The Rust code generated is below. The code calls the following C functions imported from Mynewt…

  1. : Configure a GPIO pin for output
  2. : Write to a GPIO pin
  3. : Toggle a GPIO pin from Low to High and vice versa
  4. : Sleep a while and switch to other tasks
  5. : Start a background task
  6. : Initialise Mynewt OS
  7. : Event loop for Mynewt OS
Embedded Rust code generated for the visual program

Are We There Yet?

This is the third article in the long journey for Embedded Rust on Apache Mynewt…

There is still some work to be done to make Visual Programming with Embedded Rust a reality: complete the Rust code generators, generate safe wrappers for the entire Mynewt API, automate the Rust build, test, test and test, …

This article outlines the remaining tasks, I welcome you to join me in making Visual Embedded Rust Programming a reality. Isn’t Visual Rust so darned cool and useful? Drop me a note today!

NB-IoT programming in progress…

Lup Yuen Lee 李立源

Written by

Techie and Educator in IoT 物聯網教師