- 限界開発鯖 Advent Calender 2023, 1 日目です
- 最近 embedded に触れ始めたのでその体験録というか, 早い話駄文です
- 知識をお求めの方は go back
怪文書
アキバに行って念願の Raspberry Pi Pico を手に入れた Nanai10a はまるで手頃なオモチャを手に入れたが如く (元から for hobby use です) Raspberry Pi Pico (俗称 "ラズピコ" / 本記事では "Pico") を Linux と Rust と CLI の力で弄ぶ… べない!!! (知識不足) あああ何もわからない何もわからない!!! という訳で "Rust の Embedded は良いゾ" なんて触れ回っていた私が実は実機では初 (と言いつつ Arduino Uno にちょっと書き込もうとしたことはあるんですけどね!) となる Embedded Rust をちょっと体験したりラジバンダリ, 能動的な電子工作 (受動的な電子工作: 弊学の演習など) に身を浸し己の無力さを記し学びを忘れぬように memorial... な文章を遺す, そんなポエミー且つ完全無経験から Pico と戯れた, そんなアレコレを書き起こした記事がこちら, はーじまーるよー.
アキバ (東京, 秋葉原) でしたこと
某日, 諸用事により東京を訪れていたので送料をケチる為実店舗で買い物がしたいなあと思っていた秋葉原の秋月電気通商 (俗称 "秋月") に行ってきました. 目的は電子工作を諸々する為の諸々を買うこと! (計画性は皆無です) …まあ, 何事もなく ¥5k くらい飛ばしてきました. 多趣味はつらい (金銭的に).
ここでちょっと注意なのですが, '23/10 月末当時 Pico は店頭に配置されてない商品なので注意しましょう. 確か店頭の何処かに案内が書いてあったはずですが. 会計時に "Raspberry Pi Pico ください" って言わないと姿すら拝めません. ご注意を.
通過儀礼 blink をする
とりあえず手元には Pico と適当な PC (powered by Arch Linux), そして micro-USB Type-B のケーブルがあるので, まずはこのラズピコに灯りを灯す (あかりをともす) 所から始めるとしましょう. やっぱマイコンと言えばコレだよね [単純な課題だから?].
[PC: USB Type-A]
→ [Pico: micro-USB Type-B]
と繋いで, まずは… これ給電されてるのか? (※繋いでも何の応答も無い) 心配になってきた. まあきっと疎通してるやろ. 駄目だったらまた考えよう.
そして親切ご丁寧な記事を発見. 先っちょだけ読みます (熟読してなくてごめんなさい).
rustup に target として thumbv6m-none-eabi
の導入, cargo-install で flip-link (crates.io と elf2uf2-rs (crates.io) を導入すると便利というか good な様子. そして… 有志でこんな template がある様子?
ふむふむ. 前述のツールもここで紹介されてますね. あ, しかも公式の sdk がここに用意されてるんだ.
でこれが examples ね. 環境を構築するの面倒だし, 取り敢えずこれ動かすか…
> git clone https://github.com/raspberrypi/pico-sdk
> cd pico-sdk
> git submodule update --init
> cd ..
> git clone https://github.com/raspberrypi/pico-examples
> cd pico-examples
> cmake . -DPICO_SDK_PATH=$PWD/../pico-sdk
pico-sdk の submodules を落とすのは結構時間掛かった (8min).
さてさて, cmake の結果ですが:
ICO_SDK_PATH is /home/nanai/Workspace/rbpp/pico-sdk
Defaulting PICO_PLATFORM to rp2040 since not specified.
Defaulting PICO platform compiler to pico_arm_gcc since not specified.
-- Defaulting build type to 'Release' since not specified.
PICO compiler is pico_arm_gcc
CMake Error at /home/nanai/Workspace/rbpp/pico-sdk/cmake/preload/toolchains/find_compiler.cmake:28 (message):
Compiler 'arm-none-eabi-gcc' not found, you can specify search path with
"PICO_TOOLCHAIN_PATH".
Call Stack (most recent call first):
/home/nanai/Workspace/rbpp/pico-sdk/cmake/preload/toolchains/pico_arm_gcc.cmake:20 (pico_find_compiler)
/usr/share/cmake/Modules/CMakeDetermineSystem.cmake:148 (include)
CMakeLists.txt:8 (project)
CMake Error: CMake was unable to find a build program corresponding to "Unix Makefiles". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_ASM_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
ああはいはい, toolchain が入ってませんでしたね. yay arm-none-eabi
(-Y
) で 検索したら色々ヒットしたので, それっぽいのを導入 (pacman):
Package (3) New Version Net Change Download Size
extra/arm-none-eabi-binutils 2.41-1 19.10 MiB 3.65 MiB
extra/arm-none-eabi-gcc 13.2.0-2 1717.58 MiB 218.25 MiB
extra/arm-none-eabi-newlib 4.3.0.20230120-1 242.21 MiB 17.60 MiB
Total Download Size: 239.51 MiB
Total Installed Size: 1978.90 MiB
うわ, でっっっか. 下り >5Mbps の我が家にはちとキツいなあ. のんびり待とう.
ちなみに extra/armnone-eabi-gdb
は何故か入ってました. 何故?
導入が終わったので再挑戦. 特に言うことも無く, 正常終了.
次は make します. 何も考えずに pico-examples 直下で make -j8
(私の CPU Threads は 4 です!w).
どうでもいいけど, warning が出ない大規模 build って気持ちが良いよね. AUR の -git
package とか build してると warning は呼吸だから (?) ちょっと落ち着かないんだよね. 閑話休題.
built が終わり, 各 example の directory には なんか色々 な物が散乱している様子:
> lsd -l blink
.rwxr-xr-x nanai nanai 8.5 KB Sun Nov 5 13:16:41 2023 blink.bin
.rw-r--r-- nanai nanai 484 B Sun Nov 5 13:00:41 2023 blink.c
.rw-r--r-- nanai nanai 154 KB Sun Nov 5 13:16:41 2023 blink.dis
.rwxr-xr-x nanai nanai 41 KB Sun Nov 5 13:16:41 2023 blink.elf
.rw-r--r-- nanai nanai 219 KB Sun Nov 5 13:16:41 2023 blink.elf.map
.rw-r--r-- nanai nanai 24 KB Sun Nov 5 13:16:41 2023 blink.hex
.rw-r--r-- nanai nanai 18 KB Sun Nov 5 13:16:41 2023 blink.uf2
.rw-r--r-- nanai nanai 1.1 KB Sun Nov 5 13:16:00 2023 cmake_install.cmake
drwxr-xr-x nanai nanai 4.0 KB Sun Nov 5 13:16:37 2023 CMakeFiles
.rw-r--r-- nanai nanai 245 B Sun Nov 5 13:00:41 2023 CMakeLists.txt
drwxr-xr-x nanai nanai 4.0 KB Sun Nov 5 13:15:55 2023 elf2uf2
.rw-r--r-- nanai nanai 87 KB Sun Nov 5 13:16:00 2023 Makefile
入用なのは blink.uf2
のはずなので, コイツをどうにかしてラズピコに書き込みましょう.
何も考えずに Thunar を開くとそこには珍しく外部ストレージの項が見えましたが, CLI 狂信者なので無視 (なんで?).
多分きっと恐らく Thunar が余計なことをしたのでラズピコを再接続 (ケーブルを外して, 繋ぎ直す).
調べるの面倒なので… ええいままよ, Phind に訊いた (ref: cached).
lsblk
見たら弊環境では /dev/sdc1
として認識されている模様:
> lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 931.5G 0 disk
├─sda1 8:1 0 511M 0 part
├─sda2 8:2 0 32.5G 0 part [SWAP]
├─sda3 8:3 0 317G 0 part /
├─sda4 8:4 0 300G 0 part /share
├─sda5 8:5 0 512M 0 part /boot
├─sda6 8:6 0 512M 0 part
└─sda7 8:7 0 280.5G 0 part
sdb 8:16 0 238.5G 0 disk
├─sdb1 8:17 0 260M 0 part
├─sdb2 8:18 0 16M 0 part
├─sdb3 8:19 0 237.2G 0 part
└─sdb4 8:20 0 990M 0 part
sdc 8:32 1 128M 0 disk
└─sdc1 8:33 1 128M 0 part
sr0 11:0 1 1024M 0 rom
無心 mount して, 突っ込もう:
# 弊環境では `/mnt` 直下に `mount{0,1,...}` と sub-directory を設けて利用するようにしています
> sudo mount /dev/sdc1 /mnt/mount0
> sudo cp blink/blink.uf2 /mnt/mount0
何事もなく実行が終わり, そわそわしているうちに我がラズピコが光りだした. 文明の灯火 (電気) だ…!!!
なんとなく作業ルーチンは把握出来た気がする. ヨシ.
錆びたる blink で勝利する
さて, 先に実践した blink は公式 sdk と C-lang で書かれたものでした.
ならぬ. Rust でやらなければ気が済まぬ. という訳で先に挙げた文献を見つつ, Rust で blink を組んでみよう.
sdk と examples を clone した同階層にて作業開始. テンプレ.
> cargo new --bin blink
> cd blink
# まだやってなかった
> rustup target add thumbv6m-none-eabi
> cargo add cortex-m cortex-m-rt embedded-hal -F embedded-hal/unproven defmt defmt-rtt panic-probe -F panic-probe/print-defmt rp-pico
さて色々書いていこう. といって前述の template をパクってるだけですが.
#![no_std]
#![no_main]
use panic_probe as _;
use defmt_rtt as _;
#[rp_pico::entry]
fn main() -> ! {
use embedded_hal::digital::v2::OutputPin;
use rp_pico::hal::clocks::Clock;
let mut pp = rp_pico::hal::pac::Peripherals::take().unwrap();
let core = rp_pico::hal::pac::CorePeripherals::take().unwrap();
let sio = rp_pico::hal::sio::Sio::new(pp.SIO);
let pins = rp_pico::Pins::new(pp.IO_BANK0, pp.PADS_BANK0, sio.gpio_bank0, &mut pp.RESETS);
let mut led = pins.led.into_push_pull_output();
let mut watchdog = rp_pico::hal::watchdog::Watchdog::new(pp.WATCHDOG);
let clocks = rp_pico::hal::clocks::init_clocks_and_plls(
12_000_000,
pp.XOSC,
pp.CLOCKS,
pp.PLL_SYS,
pp.PLL_USB,
&mut pp.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
loop {
led.set_high().unwrap();
delay.delay_ms(500);
led.set_low().unwrap();
delay.delay_ms(500);
}
}
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main() -> Result<(), Box<dyn Error>> {
let out_dir = env::var_os("OUT_DIR").unwrap();
let out = Path::new(&out_dir);
File::create(out.join("memory.x"))?.write_all(include_bytes!("memory.x"))?;
println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=memory.x");
Ok(())
}
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}
EXTERN(BOOT2_FIRMWARE)
SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;
[build]
target = "thumbv6m-none-eabi"
[target.thumbv6m-none-eabi]
runner = "elf2uf2-rs"
rustflags = [
"-C", "linker=flip-link",
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
]
(↑ なんで syntax でキレられてるんだ?) 必要な tool を install し, いざ (鎌倉).
> cargo install elf2uf2-rs flip-link
> cargo run blink.uf2
> sudo cp blink.uf2 /mnt/mount0
…あれ!?いつの間にかラズピコが disk として認識されなくなってる. /dev/sdc
が居ない.
助けて Phind (ref: cached) ! …ああ, 一度書き込むと一旦認識されなくなるのね. 逆に書き込める状態のことを "BOOTSEL mode" と呼ぶらしい.
次書き込むには "BOOTSEL" を押しながら PC と接続すると BOOTSEL mode で接続できるんだ. 解決.
ラズピコを再 mount して, 再度書き込み…
✨✨✨ it works! ✨✨✨
良いね.
言い訳
本当ならもっと Pico を使って色々やりたいことあったんですが, 別記事のデバイス周りで死ぬ程 (言い過ぎ) 苦労したのでそちらに作業時間が吸われ, さらに最近クソ忙しかった (当社比) のでただの日記になってしまいました. そんな事があったんだな良かったねーくらいに思って下さい (お目汚し失礼しました). あ, あと予約投稿時に下書きのままですみませんでした. 動画付けるのに手間取りました…
では. Happy embedded hacking ;)