1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【備忘録】STM32 × RustでLチカしてみよう【IDEはEclipse】

Last updated at Posted at 2021-09-23

はじめに

以前GR-PEACH × RustでLチカしてみよう【とにかくやってみる編】という記事を書いたのですが、その時「今度はスタートアップからスクラッチで書いてみたい」ということを書きました。
この記事は上記作業の備忘録となります。備忘録なので記載が雑な部分がありますがご容赦ください。
ちなみにボードはGR-PEACHのROMがシリアルフラッシュだったりとスタートアップの工程がめんどくさそうだったので、まずは簡単なSTMのNucleoボードでチャレンジしました。

本記事の環境は以下にまとめてあります。

環境

  • OS
    • Windows 10 Pro 2004(64bit)
  • rustc・cargo
    • 1.55.0-nightly
  • rustup
    • 1.24.3
  • Eclipse
    • Pleiades All in One Eclipse 2020-12(Platform)
  • Rust DT
    • 0.8.1.v201612291856
  • OpenOCD
    • v0.11.0-1
  • GNU Arm Embedded Toolchain
    • Version 9-2019-q4-major
  • ボード

環境構築

Eclipseのインストール

以下URLから取得します。

JavaでもC++でもないのでパッケージはPlatformでOKです。私はちょっと古い2020-12版を使っていますが、最新版(私が確認したときは2021-04版)はダークテーマに背景も文字も真っ黒になってしまうバグがあり使っていないだけなので、おそらく最新版でも問題ないはずです。

RustDTのインストール

以下URLを参考にインストールします。

GNU Arm C/C++ OpenOCD Debuggingのインストール

Rust用のOpenOCDデバッグ環境はなさそうなので、C/C++用をインストールします。
最新のEclipse Embedded CDThttps://download.eclipse.org/embed-cdt/releases/6.1.2/p2/にあるのですが、ここからインストールしようとしたら、RustDTと相性が悪いようでRustDTをアンインストールするよう促されたので、仕方なくhttp://sourceforge.net/projects/gnuarmeclipse/files/Eclipse/updatesから(古めのやつ?を)インストールしました。
インストール方法は先程のRustDTと同じく新規ソフトウェアのインストール...から行います。OpenOCDでデバッグしたいだけなので、インストールするのはGNU Arm C/C++ OpenOCD DebuggingだけでOKです。

OpenOCDのインストール

推奨インストール方法はxpmによるインストールのようですが、めんどくさかった(MSYS2がインストールされていなかった)ので公式サイトにリンクされていた以下の非公式バイナリパッケージを取得しました。インストーラではないので適当なところに展開してください。

余談ですが、過去にGR-PEACHのデバッグにv0.10.0を使っていたのでそれを使いまわそうとしたのですが、エラーで起動しなかったので最新版をインストールしました。

GNU Arm Embedded Toolchainのインストール

GDBを使うのでインストールします。

ST-Linkドライバのインストール

以下URLからドライバを取得します。

プロジェクト作成

プロジェクト・エクスプローラーで右クリック → 新規作成 → プロジェクト → Rust → Rust Cargo Projectからプロジェクトを作成します。

コーディング

以下のようなLチカコードを書きました。

main.rs
#![no_main]
#![no_std]
#![feature(llvm_asm)]

#[link_section = ".vector_table.reset_vector"]
#[no_mangle]
pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset;

#[no_mangle]
pub unsafe extern "C" fn Reset() -> ! {
    let rcc_ahb1enr = 0x4002_3830 as *mut usize;
    let gpioa_moder = 0x4002_0000 as *mut usize;
    let gpioa_odr   = 0x4002_0014 as *mut usize;

    set_bit(rcc_ahb1enr,  0, true);
    set_bit(gpioa_moder, 10, true);

    let mut flg: bool = true;
    loop {
        flg = !flg;
        set_bit(gpioa_odr, 5, flg);

        for _ in 0..24_000 {
            llvm_asm!("" :::: "volatile")
        }
    }
}

unsafe fn set_bit( addr: *mut usize, bit: usize, is_set: bool ) {
    if is_set {
        *addr |= 1 << bit;
    }
    else {
        *addr &= !(1 << bit);
    }
}


use core::panic::PanicInfo;
#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
    loop {}
}

ビルド

ビルドコマンドの変更

プロジェクトを右クリック → プロパティ → Rust Build Target → ビルド・ターゲット(build)からビルドコマンドを変更できます。デフォルトだと${CARGO_TOOL_PATH} test --no-run --message-format=json(テスト用のコマンド)となっているので、cargo buildに書換えます。

ターゲットの追加

以下のコマンドでターゲットを追加します。

> rustup target add thumbv7em-none-eabihf

STM32F401REマイコンのコアはCortex-M4Fなので、thumbv7em-none-eabihfを追加します。他のコアのマイコンを使用している場合は

  • thumbv6m-none-eabi → M0, M0+
  • thumbv7m-none-eabi → M3
  • thumbv7em-none-eabi → M4, M7
  • thumbv7em-none-eabihf → M4F, M7F

を追加してください。

リリースチャネルをNightlyに変更

Eclipseのプロジェクトを作成したディレクトリで以下のコマンドを実行しNightlyに変更します。

> rustup override add nightly

configファイルの作成

Eclipseのプロジェクトを作成したディレクトリに.cargoというディレクトリを作成し、その中に以下のconfigファイルを作成します。

[target.thumbv7em-none-eabihf]
rustflags = [
	"-C", "link-arg=-Tlinker.ld",
]

[build]
target = "thumbv7em-none-eabihf"

リンカ・スクリプトの作成

Eclipseのプロジェクトを作成したディレクトリ直下に以下のlinker.ldファイルを作成します。

MEMORY {
    FLASH : ORIGIN = 0x08000000, LENGTH = 512K
    RAM   : ORIGIN = 0x20000000, LENGTH =  96K
}

ENTRY(Reset);
EXTERN(RESET_VECTOR);

SECTIONS {
    .vector_table ORIGIN(FLASH) : {
        LONG(ORIGIN(RAM) + LENGTH(RAM));        /* スタックポインタ */
        KEEP(*(.vector_table.reset_vector));    /* リセットベクタ   */
    } > FLASH

    .text : {
        *(.text .text.*);
    } > FLASH

    .rodata : {
        *(.rodata .rodata.*);
    } > FLASH

    /DISCARD/ : {
        *(ARM.exidx .ARM.exidx.*);
    }
}

STM32F401REマイコンのROMは0x08000000から512KB、RAM0x20000000から96KBです。

やっとビルド

Eclipseで作成したプロジェクトのBuild Targetsbuild check cleanという項目が並んでいると思います。buildをダブルクリックするだけでビルドは完了します。Cのビルドに慣れていると一瞬で終わりすぎて、ちゃんとビルドできたのかとちょっと焦ります:sweat_smile:

書込み及びデバッグ

メニューから実行 → デバッグ構成を選択し、デバッグ構成ウィンドウを開きます。
次にGDB OpenOCD Debuggingを右クリック → 新規作成でデバッグ構成を作成します。

各タブの設定内容は以下のとおりです。

  • メイン
    • プロジェクト
      • 通常なら紐付けるプロジェクトが選択できるのですが、C/C++プロジェクトではないのため選択肢がありません。したがって空欄にします。
    • C/C++ アプリケーション
      • ELFファイルを指定します。プロジェクトディレクトリ内のtarget/thumbv7em-none-eabihf/debug/nucleo_blinkyにあって、拡張子はありません。ファイル名はプロジェクト名によって異なります。
  • デバッグ
    • OpenOCD Setup
      • 実行可能ファイル
        • OpenOCDの実行ファイルを指定します。
        • 私の場合は${openocd_path}/bin/${openocd_executable}です。変数の値が期待してるものと違ってた気がするので、うまく実行できない場合は見直してください(多分絶対パスで指定するのが確実)。
      • Config options
        • ターゲットボードのコンフィグファイルを指定します。
        • 私の場合は-s ${openocd_path}/scripts -f board/st_nucleo_f4.cfgです。パスについては上記と同様です。
    • GDB Client Setup
      • 実行可能ファイル
        • GDBの実行ファイルを指定します。
        • 元々何かの変数が指定してあった気がしますが、なんかうまくいかなかったので私は絶対パスを指定してしまっています。
  • 始動
    • Run/Restart Commands
      • Set breakpoint at
        • mainが指定されていますが今回main関数は無いのでチェックを外しておきます。

以上で設定は完了(のはず)です。

デバッグを押すとデバッグが開始され、Reset関数の先頭でブレークしているはずです。F8で実行します。

blinky.gif

おわりに

以前の記事から1年近く経ってしまいましたがようやくスタートアップからスクラッチでLチカすることができました。
相変わらず割込み等使ってませんが、ようやく組込みRustっぽくなってきた気がします。cortex-m-quickstartテンプレートやstm32f4クレートを使えば一発なんだとは思いますが、一つ一つ理解しながらやっていこうと思います。
記事を書いている途中でRustDTはもう古い(更新が止まってる)ことに気付いたり、Eclipseの変数が全然使えなかったりと色々ありましたが、また時間ができたらアップデートしていこうと思います。
次回は割込みに挑戦しようと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?