ラズピコでRust(2) 構成を確認する

  • 2023.09.22
  • IDE
ラズピコでRust(2) 構成を確認する

皆さん こんにちは。

今回は前回構築した構成を全体的に見ていきます。

前回の環境構築 により以下のディレクトリにパッケージ(プロジェクト)が構築されています。(xxxxは皆さんのユーザー名)

C:\Users\xxxx\pprp\rp2040

(pprpは Pi Pico Rust Projectの略です)

config.toml

C:\Users\xxxx\pprp\rp2040 の下に .cargo というディレクトリがあり、そこに config.toml というファイルがあります。

このファイルについて、わかる部分だけ簡単に説明します。

[build]
target = “thumbv6m-none-eabi”

これはラズピコのマイコンである RP2040 のARM cortex-M0+ アーキテクチャをビルド対象に指定しています。

確認するには ここ と ここ を照らし合わせてみてください。

rustflags = [] の中(コンパイルオプションの指定)
“-C”, “link-arg=-Tlink.x”,

ここではリンカスクリプトに link.x というファイルを指定しています。
link.x はこちらで用意する必要はなく cortex-m-rt クレートによって自動的につくられます。

それからもうひとつ

“-C”, “linker=flip-link”,

これはスタックのプロテクションツールだそうです。

一般的に静的メモリやヒープはアドレスの低い方から高い方に伸びていき、スタックはアドレスの高い方から低い方に伸びていきます。
これが衝突するとスタックオーバーフローが発生します。

何か警告が出るのかパニックするのか、後に勉強してトライしてみようと思います。

.vscode下のファイル

rp2040.svd

svdファイルはデバイスのレジスタを定義したものです。
組込みRustでは svd2rust により PAC のソースコードを自動生成してくれます。
PACは Peripheral Access Crate (ペリフェラル アクセス クレート) の略です。
このファイルは私がネットで探して来てパッケージ内に配置しました。

すでにビルドシステム内で用意されているかも知れませんが、念のために配置しました。

launch.json

VSCodeのデバッグ時の構成や設定を記述したファイルです。
Wio Terminal を使っている分には、ひな形のものをそのまま使って頂ければ良いと思います。
ただし複製をつくって、実行ファイル名が変わる場合には “executable” の部分を編集する必要があります。

sesttings.json

上の2行は皆さまの構成に合わせてパスを設定する必要があります。
openocd.exe と arm-none-eabi-gdb.exe それぞれについて設定します。

下の2行は、Windows環境で VSCode上の表示に警告が出ることがあったので付加してみました。
特に編集する必要はありません。

tasks.json

ビルド時などのタスクを記述しています。
特に変更する必要はありません。


それでは、main.rs について見ていきます。

main.rs

Rustのソースは拡張子が rs です。
パッケージの src フォルダ下に main.rs が置かれています。

no_stdなRust

no_stdなRustでコードを書くことになるので、以下のひな形部分はいつでも共通で、ここにコードをつけ足していくことになります。

ただし、(3)のuseは必要なクレート等を都度、記述する必要があります。

#![no_std] // (1)
#![no_main] // (2)

use bsp::entry; // (3)
use embedded_hal::digital::v2::OutputPin; // (3)
use panic_halt as _; // (3)
use rp_pico as bsp; // (3)
use bsp::hal::{ // (3)
    clocks::{init_clocks_and_plls, Clock},
    pac,
    sio::Sio,
    watchdog::Watchdog,
};

#[entry] // (4)
fn main() -> ! { // (5)
    loop { // (6)
    }
}

#![…] と #[…] について

これらはアトリビュート(属性)と言います。
…の部分がアトリビュートの名前です。

#![…]
こちらは内部属性と言いスコープ(範囲)を持ちます。
クレート(ファイル)単位で全体的に影響を受けます。

#[…]
対してこちらは外部属性と言い、そのすぐ下の要素だけが影響を受けます。

例えば

#[entry]
fn main()

の部分では、main()関数だけが entry だと言っています。

(1)#![no_std]

これは内部属性なので main.rs 全体が no_std であると言っています。
no_std は std (スタンダード) ではない の意味です。

Rustの標準ライブラリは core , alloc , std の3レベル構造になっています。
no_stdアトリビュートを指定するとRustコンパイラは stdクレートではなく coreクレートを使ってプログラムをビルドします。

OSが存在しないベアメタルな開発では no_std を使うようです。
stdクレートを使わない代わりにcoreクレートを使うことになります。

allocクレートはヒープメモリを利用する型を提供します。ヒープメモリを利用する Box や Vec 等の構造体が含まれています。
allocクレートを利用するにはメモリアロケータの実装が必要で alloc-cortex-mクレート等が利用できます。

(2)#![no_main]

こちらも内部属性なので main.rs 全体が no_main であると言っています。
stdクレートに実装したコードがmain()関数を呼び出すための前処理を行っています。
この前処理はOSの機能が必要ですが組込みRustでは同様の前処理を行わなえないため、このアトリビュートで処理不要であることを指示します。

(3)use

use で必要なクレートから構造体やクレート等を見えるようにします。

(4)#[entry]

これは外部属性ですぐ下の main()関数が entry であると言っています。
no_mainアトリビュートにより main()関数が呼ばれなくなります。
そこで cortex-m-rtクレートの entryアトリビュートを使います。
cortex-m-rtクレートはマイコンをリセットし、スタックポインタの初期化や必要最小限のハードウェアの初期化を行った後に entryアトリビュートのついた関数を呼び出します。

(5)main()

main()関数の戻り値は ! となっています。
これは発散する関数と呼ばれ、この関数から戻らないことを意味しています。

(6)loop {}

とは言え loop によりプログラムが繰り返し動作するようにします。

今回は全体の構成を眺めてみました。
次回はLチカのソースコードを見ていきます。

お疲れさまでした。

IDEカテゴリの最新記事