ラズピコrustでmicro:bitと連携させてみた

ラズパイ財団プロダクト同士でなんか作ってみようと思って、micro:bitをフロントエンドとしてmic入力とLED出力を使った、音声のレベル表示(一応LED25個で25レベルの表示ができます)をやってみた

macro:bit (p1) –> ラズピコADC1(平均化処理)-> PWM出力およそ22KHzをrcでローパス -> micro:bit(p2)という流れ

<micro:bit側のコード>

from microbit import *

def show_bar(level):  # level: 0-25
    display.clear()
    height = level // 5  # 5段に分割
    width = level % 5    # 各段の幅
    
    # 下からバー積み上げ
    for y in range(5):
        if 4-y < height:
            for x in range(5):
                display.set_pixel(x, 4-y, 9)
        elif 4-y == height:
            for x in range(width):
                display.set_pixel(x, 4-y, 9)

while True:
    mic_level = microphone.sound_level()
    pin1.write_analog(mic_level * 4)
    
    control_level = pin2.read_analog()
    # 0-25に変換
    bar_level = min(control_level // 40, 25) 
    show_bar(bar_level)
    sleep(10)

<ラズピコ側>

Cargo.toml

embedded-halの1.0系は0.2と互換なし、embeded-halはobject指向言語で言うところのinterfaceでrp-235x-halは実装、つまりプロセッサが変わっても共通だろうinterfaceをembedded-halはtraitの集合として持っている


[package]
edition = "2024"
name = "rust_starter"
version = "0.1.0"
license = "MIT or Apache-2.0"


[dependencies]
cortex-m = "0.7.7"
cortex-m-rt = "0.7.5"
rp235x-hal = "0.3"
embedded-hal = "0.2"
#embedded-hal = "1.0.0" does not support rp235x-hal yet
defmt = "1.0.1"
defmt-rtt = "1.0.1"
panic-probe = { version = "1.0", features = ["print-defmt"] }

[build-dependencies]
regex = "1.11.0"

[target.'cfg( target_arch = "arm" )'.dependencies]
panic-probe = { version = "1", features = ["print-defmt"] }

[target."thumbv8m.main-none-eabihf".dependencies]
rp235x-hal = { version = "0.3", features = ["rt", "critical-section-impl"] }

<Rustコード>

Lチカコードを修正

#![no_std]
#![no_main]

use defmt_rtt as _;
use hal::pac;

use embedded_hal::adc::OneShot;
use embedded_hal::blocking::delay::DelayUs;
use embedded_hal::PwmPin;

#[cfg(target_arch = "riscv32")]
use panic_halt as _;
#[cfg(target_arch = "arm")]
use panic_probe as _;

// Alias for our HAL crate
use hal::entry;

#[cfg(rp2350)]
use rp235x_hal as hal;

#[cfg(rp2040)]
use rp2040_hal as hal;

// use bsp::entry;
// use bsp::hal;
// use rp_pico as bsp;

/// The linker will place this boot block at the start of our program image. We
/// need this to help the ROM bootloader get our code up and running.
/// Note: This boot block is not necessary when using a rp-hal based BSP
/// as the BSPs already perform this step.
#[unsafe(link_section = ".boot2")]
#[used]
#[cfg(rp2040)]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;

/// Tell the Boot ROM about our application
#[unsafe(link_section = ".start_block")]
#[used]
#[cfg(rp2350)]
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();

/// External high-speed crystal on the Raspberry Pi Pico 2 board is 12 MHz.
/// Adjust if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
const DELAY: u32 = 1000; // μs delay
const SAMPLES: u32 = 250;

/// Entry point to our bare-metal application.
///
/// The `#[hal::entry]` macro ensures the Cortex-M start-up code calls this function
/// as soon as all global variables and the spinlock are initialised.
///
/// The function configures the rp2040 and rp235x peripherals, then toggles a GPIO pin in
/// an infinite loop. If there is an LED connected to that pin, it will blink.
#[entry]
fn main() -> ! {
    // 1. Peripherals取得
    let mut pac = pac::Peripherals::take().unwrap();

    // 2. クロック・ウォッチドッグ初期化
    let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
    let clocks = hal::clocks::init_clocks_and_plls(
        XTAL_FREQ_HZ,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    // 3. GPIO初期化
    let sio = hal::Sio::new(pac.SIO);
    let pins = hal::gpio::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    let mut delay = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);

    // 4. ADC設定
    let mut adc = hal::Adc::new(pac.ADC, &mut pac.RESETS);
    let mut adc_pin = hal::adc::AdcPin::new(pins.gpio26).unwrap();

    // 5. PWM設定
    let pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
    let mut pwm = pwm_slices.pwm0;
    pwm.set_ph_correct();
    pwm.set_top(4095);
    pwm.enable();

    // GP0 = PWM Slice 0 Channel A(alomost 20KHz duty 99% @3.3v full scale)

    let mut pwm_channel = pwm.channel_a;
    let _pwm_pin = pins.gpio0.into_function::<hal::gpio::FunctionPwm>(); // GP0 as a PWM output

    loop {
        let mut sum: u32 = 0;

        // measure "samples" time and make average
        for _ in 0..SAMPLES {
            let v: u16 = adc.read(&mut adc_pin).unwrap();
            sum += v as u32;
        }

        let avg = (sum / SAMPLES) as u16;
        pwm_channel.set_duty(avg);
        delay.delay_us(DELAY);
    }
}

/// Program metadata for `picotool info`
#[unsafe(link_section = ".bi_entries")]
#[used]
pub static PICOTOOL_ENTRIES: [hal::binary_info::EntryAddr; 5] = [
    hal::binary_info::rp_cargo_bin_name!(),
    hal::binary_info::rp_cargo_version!(),
    hal::binary_info::rp_program_description!(c"Blinky Example"),
    hal::binary_info::rp_cargo_homepage_url!(),
    hal::binary_info::rp_program_build_attribute!(),
];

// End of file

動いてるところの動画は以下に、

まだ周辺回路サポートのcrateは途上ではあるけれども、組み込みでも普通に使えるようになってきたのは大きな進歩

 

admin

ラズピコでRust

ラズベリー財団がVScodeのpcio拡張機能でRust(実はZephyrも)サポートするようになったので動かしてみた

<構成と環境>

・ラズピコ2(無線なし)

・M4 MacBook Pro 32GB

・純正デバッグプローブ

 

<手順>

すでにインストール済みのpico拡張機ののメニューにはRustプロジェクト作成のメニューが出ています

ここでNew Rust Projectを選択するとLチカのサンプル、実は初代ラズピコやラズピコのRISCコア対応にもなってます、が開かれます

ラズピコ2にデバッガー接続、ピン立っていないので追加で半田付けして接続

接続確認は、

% probe-rs list
The following debug probes were found:
[0]: Debug Probe _CMSIS_DAP_ -- 2e8a:000c:E663AC91D3826F39 (CMSIS-DAP)

のように見えればつながっています

 

この状態でほぼすぐにデバッグができました、Runはファイルモードでしか機能しませんがデバッグは上位互換なので問題なし、デバッグだと.uf2のファイルも必要なくて、バイナリそのままがラズピコに書き込まれます

これ、デバッガーでブレークポイント設定して止めたとこ

 

めちゃくちゃ簡単に環境構築できるから、まだ無線関連のcrateは不備だけど、もうRustでできることはRust以外の選択は、ラズピコではないと思う

 

admin

golang/Rustのラズパイ/ラズピコ向けのクロス環境について

ラズパイ/ラズピコ限定の話になりますが、現時点での整理です

① golang : ラズパイ用にはcgoがあるとターゲットマシン用にgolangとc用に二種類のコンパイラが必要になるので、単純化のためにはcgo freeのライブラリだけ使って、(現時点ではcgoライブラリはほぼ回避手段があるはず)クロスコンパイルを実行する

たとえば、ラズパイzero用バイナリならば、以下のようなコンパイルオプションつけて実行できる

% GOOS=linux GOARCH=arm GOARM=6 go build -o rasp_zero

ラズピコで組み込み用にはgolangというのは選択肢にはならないしそもそも手段があるのか、golang使うならRustでしょう

② Rust:ラズパイ用はCross + Dockerが一番素直か、Intel MacならばVM上のUbuntuでもtoolchainが存在してるからできるけど

https://www.freecodecamp.org/news/embedded-rust-programming-on-raspberry-pi-zero-w/#heading-how-to-set-up-cross-compilation

ラズピコは組み込みだからクロスビルドしかなくて、Baker link. ENV + Rancher Desktop(docker)がCross + Dockerに相当する機能で使える、ラズピコはデバッガ(debug probe)を簡単に使えるという点でもBaker link. ENVが良さそう、おそらくBaker link. ENVと類似のツールはこの先出てくるかもしれないけど、いずれにしてもそれは仮想環境を使ったもので開発環境を自分で作ることが必要なケースはそれほどないはず(Docker用のイメージ作成は別にして)、いまだラズピコでRustはかなりニッチではあるから歩みは遅いかもしれないが

 

admin

CrossでRustのコンパイル時のパラメタ制限解除

Rustのクロスコンパイル環境でCrossを使う

以前の記事で、cross使う時には

CROSS_CONTAINER_OPTS=”–platform linux/amd64″

を先頭に付加しないと動作しなかったけれども、今日使ってみると、

% CROSS_CONTAINER_OPTS="--platform linux/amd64" cross build --target arm-unknown-linux-gnueabihf  —release 
The application panicked (crashed).
Message:  byte index 1 is not a char boundary; it is inside '—' (bytes 0..3) of `—release`
Location: /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/str/mod.rs:659

のようなエラーが出て起動できない、単純に削除して$ cross build *********で動作するようになってました(そこに至るまでにはcrossで–releaseを付加するとなぜがエラーは継続して、–releaseを削除すると動いて、その後に–release追加というこれも不可思議な現象を経由してます)

ちなみにIntel MacでDockerで環境インストして動かしてみると、なぜかDockerのuser権限なくてもコンパイルできてしまいます

 

admin

Baker link. 起動手順についての補足

Baker link. ENVは今少し不安定(Dockerの対応するコンテナを削除しないと動かない時がある)のように見えるので、手順を補足説明

<環境>

M1 MacBook Air sequoia

cargo/rustc 1.82.0

Rancher Desktop 1.16.0

<手順>

基本は、

https://baker-link.org/Blink/Baker_link_Env_page.html

ですが、途中いくつか鬼門あるので手順を記載

① historyから作成済みならば、作成済みプロジェクトの履歴からクリックして開く

② 「コンテナで再度開く」を選択

ここでコンテナにファイルが存在しない状態、つまりVScodeでソースコードが開かない時があって、その場合にはDockerのコンテナ(dockerという名前)を削除して最初からやるとうまくいく、imageはbaker-link-envという名前でこれが残っていればコンテナ展開されるだけ、このイメージがDockerに存在していなければBaker link. ENVがダウンロードするんだろう

③ probe-rs見つからないと言われる -> install/failどちらも無視

④ F5でデバッガ起動

⑤ 「cargo buildを見つけられません」のポップアップ -> 「このままデバッグ」を選択(すでに作成済みなので)

もし現在のソースファイルでビルドされていなければ、bash(Docker コンソール)でビルドする(qemu-system-aarch64使っているのでそこそこ遅い)

F5を押したタイミングでラズピコにDocker上のビルドされたバイナリを転送するようです

⑥ デバッグボタンが現れる

 

⑦ デバッグボタン列の一番左の青ボタンでデバッグが起動する

この時にはdfmtコンソール現れてデバッグ開始できる状態になってます

コンソールで前回の出力と連続しているけれども、INF0 Program start!がソースの22行目に埋め込まれてるinfo!(“Program start!”);からの出力でデバッグ開始の確認になります

 

admin

Baker link.で作成済みのプロジェクトを再度開くとき

作成したBaker link.のプロジェクトを再度開く時にどうするのかなと思って、再度作成をしてしまうとすでに作成されたプロジェクトに階層構造でつながって新たに作成されます

 

 

Baker link. Envのhistoryボタンをクリックすると過去に作成されたプロジェクトが出てくるのでそこをクリックすれば良いだけです、新規に階層構造で作成されたプロジェクトはFinderで削除実施

画像は削除した履歴(三階層の二番目と三番目)を指定しているのでLog出力で見つからないと言われてます

 

admin

ラズピコのRustデバッグ環境をBaker link.で作る

今年の九月ごろにリリースされていますが、Baker link.がdebug-probe(ラズパイ財団純正)でも動くという記述あったので使ってみた

<確認環境>

・M1 Mac Sequia 15.2

・debug-probe

<Baker link. tutorial>

https://baker-link.org/introduction.html

tutorial実行で必要な開発環境としては、

① Docker Desktop(suse版):Rancherなので実際はDockerが起動される

② VScode

③ probe-rs

開発コンソールには、Baker link.Envをインストールして、そこから起動できます

<つかえたところ>

なぜかVScode起動後の『コンテナでサイド開く』クリックでprobe-rs見つからないと言われ(ちゃんとインストしてるのに)たので再度コンソールからインスト、以下はVScode ポップアップメニューのインストールを選んだ後のメッセージ、サイドのインストでも同じメッセージ出たけど無視して進めたら通った

Installation failed. Go to https://probe.rs to check out the setup and troubleshooting instructions. baker link

probe-rsのインストコマンド、

% curl --proto '=https' --tlsv1.2 -LsSf https://github.com/probe-rs/probe-rs/releases/latest/download/probe-rs-tools-installer.sh | sh

F5起動(デバッグスタート)すると実行ファイル見つからないと言われる、ならばとDockerのコンソールからコマンドラインでビルドしてやるとF5でデバッガ起動して普通に使えるようになりました

ハードはHUB75 LEDアレイ駆動時そのままの接続、

コードエディタはVScodeそのまま、新規にウインドを開きます

現在までに種々のデバッグ環境が公開されてますが、Dockerを使う(クロス環境のCross + Podmanに似ている)のが一番筋が良さそうだからこれが今のデフォルト

P.S. リソースは大量消費しているようだけど宿命

 

admin

HUB75パネルをRustで駆動してみた

Arduino言語との速度比較のために、Rustでループ処理部分をベンチマークしてみた

プラットホームはembassyを使って、そのソースコードに埋め込み、表示パターンは階調表示のあるテストパターン、routine.rsは表示データの初期化を行うだけですが

コードは二つに分割

<main.rs>

//
// % cargo run --bin raspico

#![no_std]
#![no_main]

use embassy_executor::Spawner;
use embassy_rp::gpio::{Level, Output};
use {defmt_rtt as _, panic_probe as _};

mod routine;
use routine::DispData;

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let p = embassy_rp::init(Default::default());
    let mut r1 = Output::new(p.PIN_2, Level::High);
    let mut r2 = Output::new(p.PIN_5, Level::High);
    let mut g1 = Output::new(p.PIN_3, Level::High);
    let mut g2 = Output::new(p.PIN_8, Level::High);
    let mut b1 = Output::new(p.PIN_4, Level::High);
    let mut b2 = Output::new(p.PIN_9, Level::High);
    let mut a = Output::new(p.PIN_10, Level::Low);
    let mut b = Output::new(p.PIN_16, Level::Low);
    let mut c = Output::new(p.PIN_18, Level::Low);
    let mut d = Output::new(p.PIN_20, Level::Low);
    let _e = Output::new(p.PIN_22, Level::Low);
    let mut clk = Output::new(p.PIN_11, Level::Low);
    let mut lat = Output::new(p.PIN_12, Level::High);
    let mut oe = Output::new(p.PIN_13, Level::High);

    let a_array: [u8; 16] = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1];
    let b_array: [u8; 16] = [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1];
    let c_array: [u8; 16] = [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1];
    let d_array: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1];

    let mut disp_data = DispData {
        _array64: [0; 64],
        array4d: [[[[0; 64]; 32]; 3]; 2],
    };
    let new_disp_data = disp_data.new();

    loop {

        for i in 0..16 {
            // row number
            if a_array[i] == 0 {
                a.set_low();
            } else {
                a.set_high();
            };
            if b_array[i] == 0 {
                b.set_low();
            } else {
                b.set_high();
            };
            if c_array[i] == 0 {
                c.set_low();
            } else {
                c.set_high();
            };
            if d_array[i] == 0 {
                d.set_low();
            } else {
                d.set_high();
            };

            for b in 0..15 {
                // shading
                lat.set_high();
                for k in 0..64 {
                    // column data
                    clk.set_low();
                    //
                    if new_disp_data.array4d[0][2][i][k] > b {
                        r1.set_high();
                    } else {
                        r1.set_low();
                    }
                    if new_disp_data.array4d[0][2][16 + i][k] > b {
                        r2.set_high();
                    } else {
                        r2.set_low();
                    }
                    if new_disp_data.array4d[0][1][i][k] > b {
                        g1.set_high();
                    } else {
                        g1.set_low();
                    }
                    if new_disp_data.array4d[0][1][16 + i][k] > b {
                        g2.set_high();
                    } else {
                        g2.set_low();
                    }
                    if new_disp_data.array4d[0][0][i][k] > b {
                        b1.set_high();
                    } else {
                        b1.set_low();
                    }
                    if new_disp_data.array4d[0][0][16 + i][k] > b {
                        b2.set_high();
                    } else {
                        b2.set_low();
                    }
                    clk.set_high();
                }
                oe.set_high();
                lat.set_low();
                oe.set_low();
            }
        }
    }
}

<routine.rs>

表示データの作成をするだけ、


static ARRAY64: [u8; 64] = [
    0, 1, 1, 2, 3, 5, 8, 13, 13, 8, 5, 3, 2, 1, 1, 0, 0, 1, 1, 2, 3, 5, 8, 13, 13, 8, 5, 3, 2, 1,
    1, 0, 0, 1, 1, 2, 3, 5, 8, 13, 13, 8, 5, 3, 2, 1, 1, 0, 0, 1, 1, 2, 3, 5, 8, 13, 13, 8, 5, 3,
    2, 1, 1, 0,
];

pub struct DispData {
    pub _array64: [u8; 64],
    pub array4d: [[[[u8; 64]; 32]; 3]; 2],
}

impl DispData {
    pub fn new(&mut self) -> Self {
        let mut dis_data = DispData {
            _array64: ARRAY64,
            array4d: [[[[0; 64]; 32]; 3]; 2],
        };
        for j in 0..3 {
            for i in 0..32 {
                dis_data.array4d[0][j][i] = ARRAY64;
            }
        }
        dis_data
    }
}

<実行速度>

およそ10ms(Arduino言語ではおよそ14msだから3割程度高速化)、繰り返し(メモリ読み出しとgpio書き込み)回数は一回のリフレッシュループで、

64*3*16*32 = 98,304(16行*3色*パネル上下*16階調)ということで一回のr/g/bデータの書き込みでおよそ1μs費やしている勘定で、クロック数ではおよそ130クロックとなります、階調処理での条件分岐が処理時間では大きそうですね

写真は行アドレス信号のDなので一周期がリフレッシュ周期

結果だけ見るとRustの優位性はそれほど無いように見えるかもしれないけど、メモリ管理やコンパイラの出来の良さ、複数タスク管理をasync/awaitで簡単に実現できるから他の言語で実現(Arduino言語ならRTOS使うことになるけれども、async/awaitのほうが軽量だと)するよりもアドバンテージはあると思う

P.S. 2024/12/24

この程度(3割)の改善ならば、pico 2を使えば簡単に逆転できそうだよね、消費電力とか別にすればね、ハードの進化は偉大なりか

 

admin

 

Rustでの非同期処理(async/await)

Rustの組み込み用のフレームワークにembassyがありますが、そのサンプルコードの中では非同期処理が使われているので、概略を見てみる

https://qiita.com/Kumassy/items/fec47952d70b5073b1b7

参考はちょっと古いですが、上記のリンクですが、tokioのバージョンでタイマー待ちの処理が変わっているので最新に合わせてコードを変えています

<環境>

・M1 Macbook Air

・rustc 1.82.0

・tokio = { version = “1.42”, features = [“full”] }
#[tokio::main]はコンパイル時に展開されて、
Rustがデフォルトでは持っていない非同期処理を可能とする
<サンプルコード>
//
// original from https://qiita.com/Kumassy/items/fec47952d70b5073b1b7
//
// [dependencies]
// tokio = { version = "1.42", features = ["full"] }
use std::{thread, time};
use tokio::time::{sleep, Duration};

async fn hello() -> String {
    let one_sec = time::Duration::from_millis(1000);
    // in case of async application, it looks better to use tokio::time crate
    // delay_for : before tokio 0.2
    sleep(Duration::from_millis(1000)).await;
    thread::sleep(one_sec);

    "hello, async fn".to_string()
}

// tokio: to support async runtime
#[tokio::main]
// the async keyword of the fn main() is necessary
async fn main() {
    // excute sysnc function and wait completion
    let greeting: String = hello().await;
    println!("{}", greeting);

    // new task create(spawn)
    // return the type Result
    // 
    let handle = tokio::spawn(async {
        sleep(Duration::from_millis(1000)).await;
        "spawn thread elapsed one second".to_string()
    });

    // define async block
    //
    let world = async {
        let one_sec = time::Duration::from_millis(1000);
        thread::sleep(one_sec);

        println!("hello, async block");
    };

    // rcv spwan thread return
    let result: String = handle.await.unwrap();
    println!("{}", result);

    // async block call and wait
    world.await;

    // wait to avoid main thread terminate before spawn task complete
    sleep(Duration::from_millis(1500)).await;
}

やっていること、

① async fn hello()での非同期処理

② asyncブロック(let world)での非同期処理

③ async非同期タスク(tokio::spawn)からの戻り値(let result: String)の取得

<実行結果>

hello, async fn
spawn thread elapsed one second
hello, async block

複数箇所に時間待ちを入れているので、その時間待ちが入って出力されます

let one_sec = time::Duration::from_millis(1000); 
sleep(Duration::from_millis(1000)).await;

tokioには時間街のためのsleep()関数がありますが、std::time::Durationとの違いはsleep()関数自体がasyncブロックの如く機能するということなので使い分けは必要です

 

admin

ラズピコ wでのLチカから始める

すでにもう1年以上経過しましたが、

ラズパイPico WのRust

のフォローで、embassyを使ったサンプルプログラムでLチカを動かしてみた、とはいっても、ほぼ

https://qiita.com/Azi/items/422c654bb476e0abf118

の手順に則っています、Cargo.tomlのライブラリ版数を最新にしたのと、ソースファイルは通常通りsrcディレクトリ直下に配置しています

全体的に感じるのは、Lチカだけなのに環境構築は作業項目多いし、コードの分量も結構あるということで、MicroPyhtonやArduino言語に比較すると事前の手間がかかるということ

ディレクトリ構成はこんな感じで、config.tomlのrunnerはデバッガ使わないときには修正必要です

今回はデバッグプローブ使うのでデフォルト(対象部分だけ抜き出し)のまま、

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip RP2040"

build.rsの役割は、

//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.

memory.xはテキストファイルで、picoのメモリの使い方(マッピング)を指定するファイルに見えます

pico用のサンプルプログラムは、

https://github.com/embassy-rs/embassy/tree/main/examples/rp

に他の機能用のサンプルも存在するのでやってみるか

気づきは、① ビルドのオプションで–releaseを指定してもバイナリサイズは変わらないということ、組み込み用のバイナリだとそうなるのかもしれない、② targetディレクトリのサイズが巨大であること、今回の事例でも2.3GB程度の容量になっています

いずれにしろサンプルプログラム動かしてみるのはまだしも、実際にオリジナルのコードを書いたときにはデバッグ環境が必須だから、そこも当たり始めないと組み込みでは使い物にはならない

一番ポピュラーなのはラズパイ財団から出ているデバッグプローブを使うことだろう、今回はバイナリの転送にデバッグプローブ使ってるだけですが、

https://www.switch-science.com/products/8708

 

admin