浅葱輪業

Programming & Bicycle

RustをEV3RT上で動かす話

はじめに

この記事は、ETロボコン&EV3 Advent Calendar 2018 - Qiitaの16日目の記事です。
昨年はEV3RTとC++ETロボコンに参加していましたが、今年はRustをEV3RTで動作させる実験をしたので、その話を書きます。

ETロボコンにおけるRustの利点

Rustは「速度、平行性、安全性を言語使用として保証するC/C++に代わるシステムプログラミングに適したプログラミング言語」を目指しています。

Rust (プログラミング言語) - Wikipedia

Rustはコンパイル基盤にLLVMを用いており、EV3のCPU(ARM)に対応しています。後述するアプローチで、C言語の関数と同様にEV3RT上で実行することができます。
個人的に、以下に示すRustの長所は、ETロボコンに適用するにあたり非常に有用であると感じています。

  • モダンな言語が備えていてほしい機能を有している(Pattern Maching / Traits 等)
  • C/C++と同等の実行速度であり、リアルタイムOSであるEV3RT上で実行できる
  • C/C++や他言語と連携が可能な仕組みがあり、公式APIを含む資産を活用できる
  • 標準環境で単体テストを実行できる(cargo test)
  • Bare-metalまたはRTOS上で動作させるための標準ライブラリを使用しない設定ができる(no-std)

今回の記事ではRustそのものの有用性については割愛しますが、ETロボコンC/C++の置き換えを検討するに値すると感じています。

RustをEV3RT上で実行するためのアプローチ

以下の方式で、Rustで書いたコードをEV3RT上で実行することができました。

EV3用バイナリの出力方法

前述の通り、RustはEV3のCPUであるARM向けにバイナリを出力することができます。(target=armv5te)
ビルドオプションを使用することで、EV3RTのappバイナリとリンク可能なオブジェクトファイルを出力することができます。

$ cargo rustc --target armv5te-unknown-linux-gnueabi -- -C panic=abort  -O 

targetがarmv5te-unknown-linux-gnueabi となっていますが、-Oオプションを用いるとオブジェクトファイルを出力することができます。
また、ソースコード内で#![no_std]宣言を行うことにより、OSの機能を使用しないバイナリとなるため、EV3RTとリンクさせて動作させることができます。
標準ライブラリーの不使用

エントリポイント

FFIにより、lib.rsに以下の用に記述した関数を、C言語の関数のように呼び出させることができます。

#[no_mangle]
pub extern "C" fn main_task(_exinf: i32) {
	// Rustのエントリポイント
}

この関数をEV3RTのタスクとして起動するためのapp.cfgファイルは以下の通りです。

INCLUDE("app_common.cfg");
#include "app.h"

DOMAIN(TDOM_APP) {
	CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TMIN_APP_TPRI + 1, STACK_SIZE, NULL });
}

ATT_MOD("app.o");
ATT_MOD("rust.o");

EV3RT APIの呼出し

FFIの機能を用いて、EV3RTが提供するセンサやモータの操作関数をRustから呼び出すことができます。
以下のコードで、カラーセンサの値を読み出すことが可能です。

#[repr(C)]
#[derive(Default, Debug)]
pub struct RGBRaw {
	pub red: u16,
	pub green: u16,
	pub blue: u16,
}

pub fn color_sensor_get_rgb_raw(port: &SensorPort, rgb_raw: &mut RGBRaw) {
	let port = get_sensor_port(&port);
	unsafe {
		ev3_color_sensor_get_rgb_raw(port, &mut *rgb_raw);
	}
}

extern "C" {
	fn ev3_color_sensor_get_rgb_raw(port: u8, raw: *mut RGBRaw) -> i32;
}

サンプルプロジェクトのビルド

以上をまとめて、EV3RTのディレクトリに放り込める形のソース一式を作成しました。
github.com
以下のデバイスについて、動作検証を行いました。
ev3rt\hrp2\sdk に含まれるファイルを、上記リポジトリのファイルで置き換えてください。
あとはETロボコン参加者の皆さんにはお馴染みのコマンドでビルドできます。

$ cd sdk_rust/workspace/
$ make app=rust-sample

f:id:tk-r:20181214000255j:plain
デデーン

上記のリポジトリのソースファイルでは、以下のデバイスを検証した際のコードを含めています。

  • モータ(L / M)
  • カラーセンサ
  • 超音波センサ
  • ジャイロセンサ
  • タッチセンサ
  • 本体機能( LCD / LED / Button / Battery)

本記事の検証は以下の環境で実施しました。

最後に

この記事を読んで、少しでもRustに興味を持ってもらえればと思います。
それでは、来年ETロボコンに参加される皆さん、どうかご安全に。