組込みRustドキュメントを和訳したお話
はじめに
組込みRustの(勝手に主要と思っている)ドキュメント3つの和訳が、一通り完了しました。 今後は、upstream変更に対するメンテンナンスをやっていきます。
節目なので、整理しておこうと思います。
和訳も、大本になる文章があるからできるわけで、素晴らしいドキュメントを作成しているRust Embeddedチームに対して、尊敬の念に堪えません。
Rustは簡単な言語ではないので、どうしてもドキュメントが必要です。 ありがたいことに、Rustではドキュメントを書く文化が色濃いです。 今後も、Rust好きな一人として、ドキュメントの和訳や、自身の理解を解説するドキュメントを書いて行こうと思います。 (当面、大きな和訳はやらないと思いますが)
偉大な本家
和訳
和訳レポジトリは下記です。和訳に関するフィードバックはこちらにお願いします。
各ドキュメントの紹介
The embedded Rust book
マイクロコントローラのような「ベアメタル」の組込みシステムでRustを使うための入門書です。
少し注意が必要なのは、Rustの入門書でも組込み開発の入門書でもない、ということです。 Rustの基本文法とがわかった上で、マイコンでRustを使う方法を学ぶためのものです。 手を動かす要素は少なめです。
すでにRustをある程度学んでいて、組込み経験もあるのであれば、本書から入るのがおすすめです。
内容は多岐に渡ります。
Discovery
Rustを使った組込みシステム初心者向けのドキュメントです。 多少Rustを知っていれば、組込みシステムの前提知識はあまり必要ありません。 逆に、組込みシステムを知っていれば、Rustの知識は少しだけで困らないと思います。
STMF3Discoveryボードを使って、ひたすら手を動かすため、The embedded Rust bookより、こちらを先に読むと良いかもしれません。
UARTでpinrt!マクロを作る部分は、組込み以外の方も一度見てみる価値があるかと思います。
Rust、組込み、両方とも中級者だと、物足りない内容かと思います。
Embedonomicon
ひたすらリンカのセクションをいじくり回すドキュメントです。 こちらは、組込みに限らず、ベアメタルでRustを使う方々にとって有用な内容になっています。 特に、メモリレイアウト、mainインタフェースの作り方、はOS自作勢にとって必須科目ですね。
Rustでのセクションやシンボルの扱い方が解説されています。 行数としては大した量を書かないですが、細かくクレートを切ることで、うまくRustプログラミングする方法の参考にもなります。
よもやま話
ポエムです。
和訳を始めたきっかけ
2018年の年末あたり、Rustを仕事にしたいと考えていました。 Rustの勉強ができて、売名できて、普及用のリソースもできる、というやらない理由が見つからない状況でした。
ちょうど年末年始に時間があったので、見切り発車で和訳を開始しました。
tomo-wait-for-it-yuki.hatenablog.com
和訳の進め方
文章が長かったり、構造がわかりにくい時だけ、一度google翻訳に突っ込んで、文脈の理解に役立てました。 驚くほど良い文章が出て来ることがありますが、基本的には、自分で作った訳の方が自然な日本語になります。
たまに出てくるジョークや、洒落た言い回しが厄介でした。 技術的に難しい部分はありましたが、おおよそ、平易な英語で書かれており、それほど読むのに困らない文章でした。
YoctoでRust②〜cargo-bitbake〜
はじめに
組込みLinuxでRustする場合、普通にホストマシンで開発して、普通にホストマシンのRustコンパイラでクロスビルドしたものをターゲットに持って行っています。 これで事足りているのですが、前々から興味があったため、YoctoでRustアプリケーションをビルドします。
今回は、CargoプロジェクトからYoctoのレシピを生成してくれるcargo-bitbakeを試してみます。
cargo-bitbakeのインストール
libssl-dev
が必要なのでインストールします。
$ sudo apt install libssl-dev
$ cargo install cargo-bitbake
ripgrepでお試し
ripgrepをYoctoでビルドしてみます。 構築している環境のRustのバージョンが1.24.0なので、そのコンパイラでビルド可能なbranchを引っ張ってきます。
なんかそんな感じでしたねw
— みつきん (@yusuke_mitsuki) 2019年4月30日
どうやらmasterブランチを使うのが正解のようです。
こっちもぼちぼち書きます。
meta-rustはmaster branchを使うのが良いらしいです。確かに、1.33まで対応されていました。
$ git clone https://github.com/BurntSushi/ripgrep.git -b 0.9.0 $ ripgrep $ cargo bitbake $ ls *.bb ripgrep_0.9.0.bb
レシピができました。
$ cat ripgrep_0.9.0.bb # Auto-Generated by cargo-bitbake 0.3.10 # inherit cargo # If this is git based prefer versioned ones if they exist # DEFAULT_PREFERENCE = "-1" # how to get ripgrep could be as easy as but default to a git checkout: # SRC_URI += "crate://crates.io/ripgrep/0.9.0" SRC_URI += "git://github.com/BurntSushi/ripgrep.git;protocol=https" SRCREV = "6799dcfc0ee63d741cd721c3311852a1b01449d8" S = "${WORKDIR}/git" CARGO_SRC_DIR="" # please note if you have entries that do not begin with crate:// # you must change them to how that package can be fetched SRC_URI += " \ crate://crates.io/aho-corasick/0.6.6 \ crate://crates.io/ansi_term/0.11.0 \ crate://crates.io/atty/0.2.11 \ crate://crates.io/bitflags/1.0.3 \ crate://crates.io/bytecount/0.3.1 \ crate://crates.io/cfg-if/0.1.4 \ crate://crates.io/clap/2.32.0 \ crate://crates.io/crossbeam/0.3.2 \ crate://crates.io/encoding_rs/0.8.4 \ crate://crates.io/encoding_rs_io/0.1.1 \ crate://crates.io/fnv/1.0.6 \ crate://crates.io/fuchsia-zircon-sys/0.3.3 \ crate://crates.io/fuchsia-zircon/0.3.3 \ crate://crates.io/glob/0.2.11 \ crate://crates.io/lazy_static/1.0.2 \ crate://crates.io/libc/0.2.42 \ crate://crates.io/log/0.4.3 \ crate://crates.io/memchr/2.0.1 \ crate://crates.io/memmap/0.6.2 \ crate://crates.io/num_cpus/1.8.0 \ crate://crates.io/rand/0.4.2 \ crate://crates.io/redox_syscall/0.1.40 \ crate://crates.io/redox_termios/0.1.1 \ crate://crates.io/regex-syntax/0.6.2 \ crate://crates.io/regex/1.0.2 \ crate://crates.io/remove_dir_all/0.5.1 \ crate://crates.io/same-file/1.0.2 \ crate://crates.io/simd/0.2.2 \ crate://crates.io/strsim/0.7.0 \ crate://crates.io/tempdir/0.3.7 \ crate://crates.io/termcolor/1.0.1 \ crate://crates.io/termion/1.5.1 \ crate://crates.io/textwrap/0.10.0 \ crate://crates.io/thread_local/0.3.5 \ crate://crates.io/ucd-util/0.1.1 \ crate://crates.io/unicode-width/0.1.5 \ crate://crates.io/unreachable/1.0.0 \ crate://crates.io/utf8-ranges/1.0.0 \ crate://crates.io/void/1.0.2 \ crate://crates.io/walkdir/2.1.4 \ crate://crates.io/winapi-i686-pc-windows-gnu/0.4.0 \ crate://crates.io/winapi-x86_64-pc-windows-gnu/0.4.0 \ crate://crates.io/winapi/0.3.5 \ crate://crates.io/wincolor/1.0.0 \ " # FIXME: update generateme with the real MD5 of the license file LIC_FILES_CHKSUM=" \ file://Unlicense OR MIT;md5=generateme \ " SUMMARY = "ripgrep is a line-oriented search tool that recursively searches your current directory for a regex pattern while respecting your gitignore rules. ripgrep has first class support on Windows, macOS and Linux" HOMEPAGE = "https://github.com/BurntSushi/ripgrep" LICENSE = "Unlicense OR MIT" # includes this file if it exists but does not fail # this is useful for anything you may want to override from # what cargo-bitbake generates. include ripgrep-${PV}.inc include ripgrep.inc
なんかライセンス関連のところが変、というかFIXME
と書いてありますね。
ということで、ちょろっと直しておきます。
LIC_FILES_CHKSUM=" \ file://COPYING;md5=034e2d49ef70c35b64be514bef39415a \ "
ビルドしてみる
面倒くさいので、meta-rustのrecipes-exampleに生成されたレシピを突っ込みます。
meta-rust/recipes-example/ripgrep$ ls ripgrep_0.9.0.bb
$ bitbake ripgrep ERROR: ParseError at /home/tomoyuki/others/01.rust/yocto/layers/meta-rust/recipes-example/ripgrep/ripgrep_0.9.0.bb:103: unparsed line: 'SUMMARY = "ripgrep is a line-oriented search tool that recursively searches your current'
サマリの説明部分でエラーが出ます。レシピを確認してみます。
SUMMARY = "ripgrep is a line-oriented search tool that recursively searches your current directory for a regex pattern while respecting your gitignore rules. ripgrep has first class support on Windows, macOS and Linux"
改行入ってます。
SUMMARY = "ripgrep is a line-oriented search tool that recursively searches your current directory for a regex pattern while respecting your gitignore rules. ripgrep has first class support on Windows, macOS and Linux"
改行をなくします。
$ bitbake ripgrep WARNING: Host distribution "ubuntu-18.04" has not been validated with this version of the build system; you may possibly experience unexpected failures. It is recommended that you use a tested distribution. Loading cache: 100% |############################################| Time: 0:00:00 Loaded 2785 entries from dependency cache. NOTE: There are 1 recipes to be removed from sysroot cortexa7hf-neon-vfpv4, removing... NOTE: Resolving any missing task queue dependencies Build Configuration: BB_VERSION = "1.36.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "universal" TARGET_SYS = "arm-poky-linux-gnueabi" MACHINE = "raspberrypi3" DISTRO = "poky" DISTRO_VERSION = "2.4.4" TUNE_FEATURES = "arm armv7ve vfp thumb neon vfpv4 callconvention-hard cortexa7" TARGET_FPU = "hard" meta meta-poky meta-yocto-bsp = "rocko:5f660914cd7eec8117efccdf1eb29c466b4e74f7" meta-oe meta-python meta-networking = "rocko:eae996301d9c097bcbeb8046f08041dc82bb62f8" meta-raspberrypi = "rocko:8e4c537d84fdde8e3b4642d0dda2c0f4af76d52f" meta-rust = "rocko:a4797129e2ab7f11671f817653b11ed876c2b43c" Initialising tasks: 100% |#######################################| Time: 0:00:00 NOTE: Executing SetScene Tasks NOTE: Executing RunQueue Tasks WARNING: ripgrep-0.9.0-r0 do_populate_lic: ripgrep: No generic license file exists for: Unlicense in any provider NOTE: Tasks Summary: Attempted 564 tasks of which 549 didn't need to be rerun and all succeeded. Summary: There were 2 WARNING messages shown.
はい、OKです。
YoctoでRust①〜meta-rustのhello-worldビルド〜
はじめに
組込みLinuxでRustする場合、普通にホストマシンで開発して、普通にホストマシンのRustコンパイラでクロスビルドしたものをターゲットに持って行っています。 これで事足りているのですが、前々から興味があったため、YoctoでRustアプリケーションをビルドします。
やってみてわかったことは、アプリケーションを複数個、ディストリビューションとして一括管理したい場合でなければ、RustアプリケーションをYoctoでビルドするうまみはないように思えました。 環境だけYoctoで構築し、sysrootをCargoの設定ファイルで読み込んで開発するのが良さそうに思えます。
ターゲット
ハードはラズパイ3 & Yoctoのバージョンはrockoです。
bitbake
前準備
sudo apt install gawk wget git-core diffstat unzip texinfo gcc-multilib \ build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \ xz-utils debianutils iputils-ping libsdl1.2-dev xterm
ソースダウンロード
git clone -b rocko git://git.yoctoproject.org/poky.git git clone -b rocko git://git.yoctoproject.org/meta-raspberrypi git clone -b rocko git://git.openembedded.org/meta-openembedded git clone -b rocko https://github.com/meta-rust/meta-rust.git
NOTE: sumoではビルドが失敗します。rockoではビルドが成功することがわかっています。
環境設定
source layers/poky/oe-init-build-env build
レイヤ追加
bitbake-layers add-layer ../layers/meta-openembedded/meta-oe bitbake-layers add-layer ../layers/meta-openembedded/meta-python bitbake-layers add-layer ../layers/meta-openembedded/meta-networking bitbake-layers add-layer ../layers/meta-raspberrypi bitbake-layers add-layer ../layers/meta-rust
local.conf修正
MACHINEをラズパイ3にします。
MACHINE = "raspberrypi3"
rust-hello-worldのビルド
Rustのサンプルプロジェクトであるrust-hello-world
がビルドできるかどうか、試してみます。
bitbake rust-hello-world
i7-8565Uで2時間ほどかかりました。
rustコンパイラのバージョンを確認してみます。 ビルド生成物のnative用ツールチェインにRustコンパイラがあります。
$ build/tmp/work/x86_64-linux/rust-cross-arm$ ls 1.24.1-r0
1.24.1…。 古いですねぇ…。
Rustのツールチェイン関係では、RustコンパイラとLLVMがビルドされています。
$ ls rust* rust-cross-arm: 1.24.1-r0 rust-llvm-native: 1.24.1-r0 rust-native: 1.24.1-r0
そして、LLVMが27GB、Rustコンパイラが13GBと、ものすごい容量を占めていました。 ビルド時間も、LLVMとRustコンパイラをビルドしてる時間が長く、その割に、ツールチェインが古いので、割に合わない感じです。 Rustはデフォルトでクロスコンパイルできるので、どうしてもYoctoでビルドしてdistributionとして配布したい、という状況でなければ、わざわざYoctoでビルドするうまみはなさそうです。
muslでビルドして、完全に独立したバイナリとして作る方が、移植性が高くて良いのではないですかね?
参考
注意
どうもsumoでのビルドが失敗します。
続きはないかもしれません。
実践Rust入門
はじめに
著者の皆様から本書をいただきました。本当にありがとうございます。
- 作者: κeen,河野達也,小松礼人
- 出版社/メーカー: 技術評論社
- 発売日: 2019/05/08
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
本の大まかな構成は次の通りです。
- 第1部基礎編:Rustの特徴や文法
- 第2部実践編:
パーサ
、パッケージ
、Webアプリケーション
、FFI
の実践的な使い方の例と解説
全体を通して、動くサンプルコードで学べるようになっている点が、本書の大きな特徴だと思います。
println!
かテスト(assert!
, assert_eq!
マクロ)ですぐに動作を確認できるコードが多いです。
また、Rustに入門するにあたり、エラーとの格闘はつきものですが、 本書では、こう書くと、このようなエラーが出て、その理由はこうで、直し方は〜、というエラーの解説まであり、入門者に親切な作りになっています。
Rust入門のための1冊として、自信を持って推奨することができます!
以下、個人的に特筆したいと思った2点について書きます。
- なぜRustなのか?
- FFI
なぜRustなのか?
第1章では、Rustの特徴が記載されています。 その中には、なぜRustなのか?という節があります。
Rustを導入していく際に、説得材料にできるような内容がまとめられています。 私個人でも、なぜRustが良いのか、という部分は資料を集めに時間をかけたため、Rust普及活動したい方がそこにかける時間が減らせる本書が出たことは、非常に意義深いです。
FFI
C言語との連携について書かれた章です。 現状、同様の日本語ドキュメントはないと思います。
私が主に活動している組込みに限らず、C言語の資産を活用することは避けて通れない道です。 C言語との連携の話をすると、多くの場合「unsafe地獄にならないですか?」という質問を頂きます。
章の冒頭に書かれている通り、RustとC言語の橋渡しを作ることは、Rust単体やC言語単体のプログラミングよりも困難なことが多々あります。 動的確保したメモリを、RustとC、どちらで解放するか、を意識しながらラッパーを書く部分など、慎重な設計が必要で、デバッグも難しいです。
ただ、1度unsafe
を閉じ込めたAPIが作れると、Rustらしい安全で生産性の高いコードを記述することが可能になります。
FFIの章では、Rust風のラッパAPIを作っていく手順が丁寧に説明されており、多くのRustユーザーにとって有用な内容になっています。
本書で書かれているレベルのことができるようになるまで、自分で色々調べたり、試行錯誤が必要だった状況が大幅に改善されると思います。
他の書評など
私は興味のある部分がニッチですので、ここだけでは判断できない!という方々は、ぜひ他の方の書評を読んで頂ければ、幸いです。
- 著者の一人であるκeenさんの記事
- Rust勉強会でよくLTされているyukiさんの記事
- Rust LTなどを主催されているdorayakikunさんの記事
KiCadで基板を作ってみよう①〜基板を描くまで〜
はじめに
技術書典で入手した基板を作ってみよう 技術書典6特装版 -KiCad 5による基板作成-
を参考に基板を作ってみます。
書籍内で詳細が記述されていない部分 (インストール方法など)のみ、メモとして記載します。
私は、電子回路(LSI)設計は経験がありますが、基板設計は未経験で、電気回路は素人です。
KiCadインストール
ダウンロードページからUbuntuのリリースビルドバイナリを入手します。 aptによるインストール方法が書いてあるため、手順に従います。
sudo add-apt-repository --yes ppa:js-reynaud/kicad-5.1 sudo apt update sudo apt install --install-suggests kicad
sudo apt install kicad
中々回線が細くて、時間がかかります。
起動
適当にディレクトリを作成し、KiCadを起動します。
# working directory kicad
circuit-tester
というプロジェクトを作成し、作業を進めて行きます。
回路図
Eeschema
を起動して、回路図を書いていきます。
操作に慣れないながらも、なんとか回路図を作っていきます。 回路の意味を完全に理解できているわけではないのですが、とにかくやってみるの精神です。
フットプリントと対応付け
おぉ、これは大変です…。 ちょっと自分で経験積まないと、実装側で対応、とかそういった応用ができなさそうです。
基板を描こう
トランジスタの物理レイアウト設計したいた頃を思い出します。 こういう配線は、パズル要素があって面白いですね。
今回は、書籍の配線を真似して、サクっと仕上げて終了です。
区切りが良いので、発注は別途やります。
インラインアセンブリだけの関数の最適化でハマった
はじめに
Cortex-Mのコンテキストスイッチを書いています。 引数有りで、インラインアセンブリだけを実行する関数を作り、threadのディスパッチを書いていました。
このような場合、適切なconstraintを書いてインラインアセンブリを呼び出さないと、リリースビルドの最適化で意図せぬ挙動になります。
問題を起こしたdispatch関数
まず、デバッグビルドでのみ動作する実装です。
/// A dispatcher of Cortex-M. /// Parameters: /// sp: stack pointer pub extern fn dispatch(sp: *usize) void { asm volatile ( \\ ldr sp, [r0] \\ pop {r4-r12,lr} \\ mov r0,r12 \\ bx lr ); }
第一引数は、r0
に格納されるため、そのままバイナリが出力されれば、問題なく動き、スレッドが起動します。
症状
上記プログラムをリリースビルドすると、HardFaultが発生し、スレッドが正常に起動しません。
dispatch
のシンボルを強制的にexportし、break pointを作ってデバッグします。
その結果、dispatch
に到達した時点で、r0
(引数のsp)に0
が格納されていることがわかりました
(補足ですが、ここでの期待値は、RAM領域なので、0x200xxxxx
です)。
dispatch
関数のインライン化を抑制して、明示的に関数呼び出しするようにしても、症状が改善しませんでした。
調査を進めたところ、dispatch
内で明示的に引数のspを使用すると、正常に動作することがわかりました。
解決策
input constraintを使って、sp
を利用することを明示的に示します。
/// A dispatcher of Cortex-M. /// Parameters: /// sp: stack pointer pub extern fn dispatch(sp: *usize) void { // **Note** Need explicit constraint to prevent compiler from mis-optimizing. asm volatile ( "ldr sp, [%[sp_i]]":: [sp_i] "r" (sp) ); asm volatile ( \\ pop {r4-r12,lr} \\ mov r0,r12 \\ bx lr ); }
これで、リリースビルドでも、意図通り動きます。
せめて、インライン化を抑制したら、引数くらいはちゃんと渡して欲しいです…。
技術書典6の戦利品を読む①〜OS Girls / 組込みエンジニアの教科書 / Rust on Bare-metal Raspberry Pi / Atmelさんちの消失〜
はじめに
1つ1つは短めです。 少しでも、宣伝、フィードバック、になれば幸いです。
OS Girls
8086やIntel SDMの紙媒体が転がっている不思議な部室で繰り広げられる女子高生たちのOS自作物語です。
物語の導入として、PCを使っていて湧いた疑問から、低レイヤに入っていくのは良いなぁ、と思いました。 OSってなんだろう、でOSの概念を説明しているのも、手を動かす一辺倒にならないように工夫されているように感じました。
次の階層でお会いしましょう、とのことですが、ringを使い切っているので、次はVMXですかね。
組込みエンジニアの教科書
- 作者: 渡辺登,牧野進二
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2019/04/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
技術書典で先行販売していたので、入手しました。 座学的な内容と、手を動かす内容とが、両方入っています。
座学的な内容は、エンベデッドスペシャリストの参考書に似たような感じでした。
組込みLinuxの章があり、ここでは、著者の経験から組込みLinuxをやる上で気をつけないといけないことが書かれています。 現場で痛い目を見ないと中々実感できない内容であり、組込み初心者の方にも知っておいて欲しい情報が書かれていました。 炎上しないように良いモノ作ろうとすると、ハードもソフトも学ばねばなりません。 一気には無理なので、できるところから守備範囲を広げましょう。 良い組込み開発の上司を見分ける基準として、使うのも良いと思います。
Rust on Bare-metal Raspberry Pi
Rustに限らず、ベアメタルプログラミングをやろうとすると、ハードウェアの説明が必要不可欠です。
そこが面倒で中々本の執筆ができていないわけなのですが。
本書では、そこの前提知識が丁寧に書かれていました。 そのため、少し、Rust成分は控えめです。 次回作で、Rustがたくさん出てくると良いなぁ、と思いました。
Atmelさんちの消失
こういうマイコンおよび製造メーカが辿った変遷は、非常に興味深いです。 が、自分では、中々実際の調査までしないため、まとまったものがあるととてもありがたいです。
自分がまだプログラマやっていなかった時代の空気も感じることができて、大変おもしろかったです。