Documentation

Rust on Tessel

Looking to do some Rust development on Tessel? You’ve found the right place.

Get in touch: the team working on Rust for Tessel is all on the #rust-lang channel of the Tessel Slack . Join the conversation!

tessel-rust

This repo hosts the Tessel library that provides the hardware API (gpio.high(), spi.transfer(), etc.) to user applications. It is currently incomplete (see gist above for current status) and could use your help to finish it up. The API should end up being very similar to the JavaScript API.

Overview for using Rust on Tessel

tl;dr We are working on getting Rust deployment finalized and merged into the command line interface. Rust can be compiled on a remote cross-compilation server or locally using rustup on OSX and Linux. We can deploy simple scripts that output to the console but cannot yet control the module ports or network APIs (see the bottom section for what kind of contributions would be useful).

Quick Start with Remote Compilation (git, and Node 4.x` are requirements)

  • Install the CLI if you haven't already: npm install t2-cli -g
  • Create a Rust project with a blinky example: t2 init --lang=rust (or cargo new hello --bin)
  • Deploy to your Tessel with the CLI: t2 run Cargo.toml

Quick Start with Local Compilation based on @badboy's work (rustup, git and Node 4.x are requirements)

  • mkdir tessel-rust && cd tessel-rust to create a folder for Rust projects
  • Next we'll setup the linker.

For Linux, first download the OpenWRT SDK with:

wget https://s3.amazonaws.com/builds.tessel.io/t2/OpenWRT+SDK/OpenWrt-SDK-ramips-mt7620_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2
tar -xf OpenWrt-SDK-ramips-mt7620_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2

Then add the SDK linker to your path:

export PATH=$(readlink -f ./OpenWrt-SDK-ramips-mt7620_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/):$PATH

For OSX, first download the OpenWRT SDK with:

wget https://s3.amazonaws.com/builds.tessel.io/t2/OpenWRT+SDK/OpenWrt-SDK-ramips-mt7620_gcc-4.8-linaro_uClibc-0.9.33.2.Darwin-x86_64.tar.bz2
tar -xf OpenWrt-SDK-ramips-mt7620_gcc-4.8-linaro_uClibc-0.9.33.2.Darwin-x86_64.tar.bz2

Then add the linker to your path: export PATH=$(pwd)/openwrt/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/):$PATH

  • Create a test project
cargo new --bin hello-rust
cd hello-rust
  • Create a .cargo/config file and add details for cross compilation:
[target.mipsel-unknown-linux-gnu]
linker = "mipsel-openwrt-linux-gcc"

[build]
target = "mipsel-unknown-linux-gnu"
  • Force this project to use the nightly version of Rust so we can use an unstable feature to compile properly (temporary)
rustup override add nightly
  • Add the mipsel target for compilation:
rustup target add mipsel-unknown-linux-gnu
  • At the top of src/main.rsadd the following code to ensure we can use the system allocator instead of jmalloc which currently has issues:
#![feature(alloc_system)]
extern crate alloc_system;
  • Build the project (in release mode to optimize the size of the binary)
cargo build --release
  • You can now scp it over to your Tessel and run it!
scp target/mipsel-unknown-linux-gnu/release/hello-rust root@192.168.1.101:/tmp
ssh -i ~/.tessel/id_rsa root@YOUR_TESSEL_IP ./tmp/hello-rust

Developing on the Remote Cross Compilation Server (Docker, git and Node 4.x are requirements)

  • Clone the cross-compilation server repo and checkout the jon-1.0.0 branch.
  • Build the Docker image with docker build -t rustcc ., then run it with docker run -p 49160:8080 rustcc.
  • Clone or install the command line interface: npm install t2-cli -g
  • Make a new directory and inside, create a new Rust project with t2 init --lang=rust (it contains a blinky example)
  • Deploy the project with t2 run Cargo.toml --rustcc=$(docker-machine ip):49160
  • To make changes to the server, open two shell. In the first, get access to the shell of the Docker server with docker attach DOCKER_ID (you can get your DOCKER_ID from docker ps. Make changes to index.js and then run docker cp index.js DOCKER_ID:/usr/src/app. If you make changes to the Dockerfile, run docker build ..

Entire Rust Integration Process

In order to use Rust on Tessel, there are several components that need to be built out to integrate with the existing system:

  1. Cross Compilation Capabilities - Tessel runs a MIPS architecture which means we have to compile for MIPS instead of our host computer CPU
  2. Command Line Interface Deployment - The same CLI used for deploying JS needs a plugin built for deplying to Rust
  3. Tessel Standard Library (this repo) - The Tessel-specific library that gives access to the LEDS, button, and module ports
  4. Module Libraries - Each Tessel Module needs its library ported from JS to Rust and released as a Cargo Crate

Cross Compilation Capabilities

We got started on building a cross-compilation server several months ago. @kevinmehall did a bunch of work to figure out exactly how to build a Rust binary for the MIPS architecture and that work has been automated into this Docker script. The cross compilation server includes that Dockerfile as well as Node server that presents an single API endpoint for cross-compilation. It receives a POST request that sends a tarred project directory, cross compiles that project, then sends the tarred binary back down to the client. The server is awaiting v1.0 to land. To run it, clone this directory and checkout the jon-1.0.0 branch, build the Docker image (requires Docker to be installed) with docker build . -t rustCC, then run it with docker run -p 49160:8080 rustCC.

We would eventually like to use rustup for cross compilation within the CLI. It's better suited for the task because it's an easy pathway for local cross-compilation rather than depending on an internet connection and a long-lived remote cross-compilation server. It is better integrated into existing Rust tools like Cargo. We are at a point where we have rustup functional with a single workaround and are in the process of integrating into the CLI. We do not have rustup functional on Windows.

Command Line Inteface Deployment

Tessel projects have traditionally been deployed using a command line tool written in JavaScript (with Node.js). In order to bootstrap Rust development on Tessel, we plan to start deploying Rust as well with the same tool (it can be installed with npm install t2-cli -g). Eventually, we'd love to build most of the core functionality in Rust and link to that binary with JavaScript (or in whatever language is being deployed) but that's a stretch goal. In order to integrate with the CLI, we need to write a deployment plugin. This plugin outlines how to detect Rust programs, any pre-deployment steps and any post-deployment steps. A basic version of this integration has been completed and is awaiting review. This plugin has only been tested with simple programs (ie cargo new hello --bin) and can certainly use more testing. The CLI will detect a Rust project, bundle it into a tarball, send it to the cross compilation server, and then deploy the resulting binary to an available Tessel.

Tessel Standard Library

The Tessel Standard Library (this repo) is the library that gets 'loaded' into a user program (runs on T2) and presents an API for configuring the hardware (LEDs, module ports, network interfaces, etc.). You can see the JavaScript version of the Tessel Standard Library here. The most important function is communication with module ports which takes places by writing to a Unix Domain Socket always running on OpenWRT. See the technical overview or previously linked JS Standard Library for more detailed information on how that works. Everything sent to the domain socket gets sent to the microcontroller. There is a simple protocol between the MediaTek (running OpenWRT) and the coprocessor to coordinate hardware operations.

Module Libraries

Every Tessel (hardware) Module has a corresponding software module with the driver code that calls the Standard Library API. The module is managed and installed via a package manager (ie npm for Node and cargo for Rust). You can see an example of a JS driver here with the accelerometer module. Every hardware module we've made needs to get ported to Rust and deployed to crates.io

Ways you can help right now (not in any particular order)

  • Get another pair of eyes on the cross-compilation server (it's quite simple)
  • Help deploy the cross-compilation server to a Digital Ocean droplet
  • Try out the CLI branch that enables Rust deployment with more complicated projects
  • Review the CLI branch code
  • Figure out how to use rustup with Tessel on Windows
  • Integrate local deployment with rustup into the CLI
  • Start writing a Tessel CLI core library in Rust
  • Build out the Tessel Standard Library to allow use of the module ports
  • Figure out how to store the Tessel Standard Library permanently in memory on T2
  • Release the standard library on Crates.io when it's ready
  • Start porting each of the module libraries from JavaScript to Rust (dependent on building out the standard library for Rust)
  • Write documentation for Rust usage on Tessel 2