2023年11月20日月曜日

ubuntu22.04にstm32f429zi向けのrustでの開発環境を作りプログラムを実行


背景

stm32マイコンには有志によって作られたrustのプログラム環境と関連機能呼び出しライブラリがあります。

stm32-rs

気になっていたのでubuntuに環境を構築してボタン認識とLED点灯をさせてみました。
備忘録として取り組んだ内容を記事に残します。

使ったもの


関連プログラムをインストール

開発環境に必要なプログラムとそれのインストール手順を紹介します。

VSCode

プログラム開発に便利な機能を備えたテキストエディタ(文章編集プログラム)です。

ubuntu22.04だとsnap経由でインストールできます。
sudo snap install --classic code

インストール後はVSCodeを開いて「Ctrl + Shift + p」を押してコマンド入力欄を出し、下記のコマンドで「Japanese Language Pack for Visual Studio Code」をインストールすれば、表示が日本語になります。
(自分が試したときは入力後に言語を手動で選択する画面が開いたので、コマンド実行後に選択操作が必要なのかもしれません。)
ext install MS-CEINTL.vscode-language-pack-ja

2022年頃まではsnap版のVSCodeは日本語を入力できない不具合がありましたが、2023/11/20に自分が試したときは日本語を入力可能になっていました。
何らかの制限でsnap板ではなくdeb版を使いたいという方は、debian系OS向けのインストール手順に従ってインストールしてください。

VSCode プラグイン cortex-debug rust-analyzer

今回の開発に便利な下記2つのプラグインをVSCodeのプラグイン一覧から検索してインストールしてください。

cortex-debug: デバッグ時にブレークポイントを置いて動作確認するため

rust-analyzer: rust編集時の構文解析

rust lang

プログラミング言語rustです。
公式のインストール手順に従ってインストールしてください。

PCをインターネットに繋げてインストール手順に示されているコマンドを実行して待機すれば済むはずです。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

rustをインストール済みならrustupコマンドで更新できます。
rustup upgrade

今回は1.74.0を利用しました
rustc --version
rustc 1.74.0 (79e9716c9 2023-11-13)

rustのクロスコンパイラ

今回利用するstm32f429ziはデータシートによると「Arm® 32-bit Cortex®-M4 CPU with FPU」です。


Cortex-M4はarm v7mなので、FPU(Floating point unit: 浮動小数点ユニット)付きのv7m向けクロスコンパイラthumbv7em-none-eabihfをインストールします。
rustup target add thumbv7em-none-eabihf

無いとビルドやデバッグ実行時に下記のようなエラーが出ます。
error[E0463]: can't find crate for `core`
|
= note: the `thumbv7em-none-eabihf` target may not be installed
= help: consider downloading the target with `rustup target add thumbv7em-none-eabihf`

エラーが長くて最初のエラーを確認しづらいときは、VSCodeでターミナルを立ち上げて下記のコマンドするとless(文章表示プログラム)で先頭から表示できます。
cargo test --color always 2>&1 | less -r

gdb-multiarch(旧: arm-node-eabi-gdb)

stm32f429ziとデバッガの連携に必要なプログラムです。
v10までは「arm-node-eabi-gdb」だったプログラムがv11あたりから複数のICに対応して「gdb-multiarch」に変わったようです。
sudo apt install -y gdb-multiarch

これが無いと下記のようなエラーが発生します。
GDB executable "arm-none-eabi-gdb" was not found.
Please configure "cortex-debug.armToolchainPath" or "cortex-debug.gdbPath" correctly.

参考:
How can I install "gdb-arm-none-eabi" on Ubuntu 18.04 (Bionic Beaver)?

openocd

基板に実装済みのICをデバッグするためのプログラムです。
下記のコマンドでインストールできます。
sudo apt install openocd

これが無いとデバッガ実行時に下記のようなエラーが出ます。
Launching gdb-server: openocd -c "gdb_port 50000" -c "tcl_port 50001" -c "telnet_port 50002" -s /home/asuki/rustprojects/stm32f429zi-test -f /home/asuki/.vscode/extensions/marus25.cortex-debug-1.12.1/support/openocd-helpers.tcl -f interface/stlink.cfg -f target/stm32f4x.cfg
Please check TERMINAL tab (gdb-server) for output from openocd
Finished reading symbols from objdump: Time: 32 ms
Finished reading symbols from nm: Time: 27 ms
Failed to launch OpenOCD GDB Server: Error: spawn openocd ENOENT

プロジェクトを作成してstm32f429zi向けに設定変更

今回は「rust-stm32f429zi-test」というプロジェクトを作り、それをstm32f429zi向けに変更します。

解説するプロジェクトはgithubに上げています。
https://github.com/asukiaaa/rust-stm32f429zi-test

下記コミットの変更内容を解説します。
Succeeded in controlling a led with a button

テンプレートからプロジェクトを作成

プロジェクトのディレクトリを置きたいディレクトリで下記のコマンドを実行します。
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart.git

プロジェクト名を入力するとその名前のディレクトリが作成され、その中に関連ファイルが置かれます。
今回は「rust-stm32f429zi-test」というプロジェクトを作成しました。

プロジェクトができたらVSCodeでそのディレクトリを開き、次の手順からファイルの編集などを行います。

.cargo/config.tomlの変更

プロジェクトのアーキテクチャ変更

stm32f429ziのthumbv7em-none-eabihfに変えます。
変更前
[target.thumbv7m-none-eabi]
変更後
[target.thumbv7em-none-eabihf]

runner有効化

gdb-multiarchを利用するrunner設定のコメントを有効化します。
変更前
# runner = "gdb-multiarch -q -x openocd.gdb"
変更後
runner = "gdb-multiarch -q -x openocd.gdb"

古いbuild target無効化

元々書かれている利用しないtargetを無効化します。
変更前
target = "thumbv7m-none-eabi"
変更後
# target = "thumbv7m-none-eabi"

thumbv7em-none-eabihfのbuild target有効化

stm32f429ziのアーキテクチャthumbv7em-none-eabihfをbuild targetとして指定します。
変更前
# target = "thumbv7em-none-eabihf"
変更後
target = "thumbv7em-none-eabihf"

.vscodeに開発対象のマイコンのSVDファイルをダウンロード

SVDファイルとはSystem View Descriptionの略で、Crotex-Mマイコンが備える機能へのメモリ一覧などが含まれるファイルです。
VSCodeのデバッガがそれを参照するので、実行対象のマイコンのSVDファイルをダウンロードして.vscodeディレクトリに配置します。

stm32向けのSVDファイルは下記のページにあります。
https://github.com/cmsis-svd/cmsis-svd/blob/main/data/STMicro

今回はstm32f429zi向けなので、下記のファイルをダウンロードしました。
https://github.com/cmsis-svd/cmsis-svd/blob/main/data/STMicro/STM32F429.svd

githubページの右側のボタンを押すとダウンロードできます。

ダウンロードしたら.vscodeディレクトリ内に置きます。

.vscode/launch.jsonの変更

device config svdFileを利用するマイコン向けに変更

stm32f429zi向けにマイコンの設定を変えます。
stlinkのconfigは「stlink-v2-1.cfg」だと廃止予定警告が出たので「stlink.cfg」に変えました。
SVDファイルは先程配置したものを使うパスにします。
変更前
            "device": "STM32F303VCT6",
"configFiles": [
"interface/stlink-v2-1.cfg",
"target/stm32f3x.cfg"
],
"svdFile": "${workspaceRoot}/.vscode/STM32F303.svd",
変更後
            "device": "STM32F429ZI",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"svdFile": "${workspaceRoot}/.vscode/STM32F429.svd",

周波数を利用するマイコンに合わせて変更

stm32f429ziのデータシートによると工場出荷状態だと16MHzの内蔵発振子を利用して動作するので、設定を16MHzにします。

変更前
                "cpuFrequency": 8000000,
変更後
                "cpuFrequency": 16000000,

Cargo.tomlの変更

関連ライブラリを最新版に変更

crate.ioで確認しつつ各ライブラリを最新版にします。
変更前
[dependencies]
cortex-m = "0.6.0"
cortex-m-rt = "0.6.10"
cortex-m-semihosting = "0.3.3"
変更後
[dependencies]
cortex-m = "0.7.7"
cortex-m-rt = "0.7.3"
cortex-m-semihosting = "0.5.0"

対象マイコンのHALを設定

HALとは「Hardware Abstraction Layer」の略で、ハードウェア抽象化層などと呼ばれる周辺機能を使いやすくするための呼び出し口です。
srm32-rsで各マイコンのhalが提供されているので、利用するマイコンに合わせて呼び出すHALを変えます。
今回はstm32f429zi向けに変更しました。
featuresの配列の2番目(0始まりで数えるなら1番目)の「rt」はstm32-rsのinterrupt呼び出しを有効にする機能なので、それを使う場合はマイコン名の後半2文字ではなく「rt」を記述します。
バージョンは記事を書いている時点で最新の0.17.1を利用します。
変更前
# [dependencies.stm32f3]
# features = ["stm32f303", "rt"]
# version = "0.7.1"
変更後
[dependencies.stm32f4xx-hal]
features = ["stm32f429", "rt"]
version = "0.17.1"

memory.xの変更

stm32f429ziのデータシートによると、flashメモリの開始位置は0x08000000、flashの大きさは2048KB ((0x08200000-0x08000000)/1024)と分かります。
ramの開始位置は0x1000000、大きさは64KBと分かります。
しかし、0x20000000から始まる192KBのramも使って良いのか、使うならどう書けば良いかは謎です。
指定方法をご存知の方がいらっしゃれば、コメントなどで教えていただけると嬉しいです。

変更前
  FLASH : ORIGIN = 0x00000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 64K
変更後
  FLASH : ORIGIN = 0x08000000, LENGTH = 2048K
RAM : ORIGIN = 0x10000000, LENGTH = 64K

openocd.cfgの変更

stm32f429ziを使うのでstm32f4x向けの設定ファイルに変更します。
openocdで設定可能なcfgファイルはopenocdのリポジトリのtcl/targetで確認できます。
変更前
source [find target/stm32f3x.cfg]
変更後
source [find target/stm32f4x.cfg]

src/main.rsの変更

nucleo-stm32f429ziはPB7に真ん中の青色LED、PC13にボタンが繋がっているので、それらを利用して、ボタンを押すとLEDの点灯状態が変わるプログラムで動作確認します。
参考にした記事の利用するピンが違う板のプログラムです。
src/main.rs
#![deny(unsafe_code)]
#![no_std]
#![no_main]

use cortex_m_rt as rt;
use hal::prelude::*;
use panic_halt as _;
use stm32f4xx_hal as hal;

#[rt::entry]
fn main() -> ! {
if let Some(peripherals) = hal::pac::Peripherals::take() {
let gpiob = peripherals.GPIOB.split();
let mut led = gpiob.pb7.into_push_pull_output();
let gpioc = peripherals.GPIOC.split();
let button = gpioc.pc13;

loop {
if button.is_high() {
led.set_low();
} else {
led.set_high();
}
}
}
}

動作確認

nucleo-stm32f429ziにプログラムを書き込んで動作確認します。

まず、PCにnucleo-stm32f429ziを接続します。

プロジェクトのディレクトリをVSCodeで開き、VSCcode左上に表示されているあろうデバッグ機能でOpenOCDを選びます。

デバッグボタンが表示されていない場合は、実行 -> デバッグの開始 を選ぶと実行されて出てくると思います。
出てきたら先程説明したとおりOpenOCDを選びます。

デバッグが始まると、USBの横のLEDが緑と赤を交互に切り替える光り方をします。
眩しいです。

処理が進むと「rt::entry」で停止状態になるので、続行ボタンを押してプログラムを動かします。


ボタンを押していないと青いLEDが光ります。

ボタンを押すと青いLEDが消えます。

期待通りに動きました。

停止ボタンを押してデバッグを止めるとマイコンも動作を停止しますが、リセットボタンを押したりUSBを抜き差ししたりするとデバッガと連携せず単体で動きます。

おわり

以前から気になっていたstm32のrustでの環境を構築してプログラムを書き込んで動かせました。
思っていたより設定項目が多かったですが、期待通りに動かせて良かったです。

参考

全体の流れを参考にした記事です。
STM32 NUCLEOボードによる組み込みRust開発環境構築
組み込みRust開発環境構築【STM32 NucleoとVSCodeで構築】 Hello_Rust_World

今回の記事で作成したプロジェクトです。
https://github.com/asukiaaa/rust-stm32f429zi-test


0 件のコメント :