iT邦幫忙

1

Rust + nRF54L15:Raytac AN54LV-DB-15 開發

  • 分享至 

  • xImage
  •  

紀錄使用 Rust + Embassy 撰寫第一個 nRF54L15 LED 閃爍程式,並透過 nRF5340-DK 的 J-Link / SWD 介面燒錄與除錯 Raytac AN54LV-DB-15 的流程。


1. Setup environment

硬體

開發板

最近想嘗試開發低功耗藍牙(Bluetooth Low Energy, BLE)應用,因此選擇了 Nordic 的 nRF54L15 SoC。

由於未來如果想把模組直接整合到自己的 PCB 上,選擇已經整合天線與 RF 電路的模組,可以省去自行設計 RF 與天線的麻煩,也能降低硬體設計的複雜度。

一開始原本想使用 u-blox 的開發板,不過 u-blox 的開發板價格比較高,雖然模組本身的價格還可以接受,而且還需要從國外運送到台灣,整體上比較麻煩。

後來發現 Raytac 是台灣的廠商,可以直接在露天拍賣上購買。相較之下,Raytac 的開發板便宜不少,而且收到開發板時還發現裡面附了一條 10-pin SWD debug cable (如果沒有這條線可以省一些錢)。

所以最後選擇 Raytac 的 AN54LV-DB-15,算是價格比較實惠。
https://ithelp.ithome.com.tw/upload/images/20260910/20158828oxq07uB0Bm.png

  • Raytac AN54LV-DB-15 (露天拍賣 NT 525)
  • MCU:Nordic nRF54L15
  • Processor:128 MHz ARM Cortex-M33
  • RISC-V Coprocessor:128 MHz RISC-V FLPR
  • Flash:1.5 MB
  • RAM:256 KB
  • 內含AN54LV-15 陶瓷天線模組

Debugger

由於手邊沒有專用的 Debugger,剛好有一張 nRF5340-DK,因此直接使用 nRF5340-DK 上的 onboard J-Link,透過 Debug Out 來燒錄與除錯 AN54LV-DB-15。
https://ithelp.ithome.com.tw/upload/images/20260910/201588284h1hIQimOb.png

連接方式:
https://ithelp.ithome.com.tw/upload/images/20260910/20158828RcCRNBwbq9.png


確認 nRF5340-DK 的電源設定

nRF DK 的開發板有一些開關需要設定,一開始 USB 接上 nRF5340-DK 後,板子上的 LED 都沒有亮,也沒有被 Mac 正確看到,找了很久問題才發現我的 Power 開關切在 OFF 的地方。

使用前要確認 nRF5340 DK 的開關:

  • POWER ON/OFFON
  • nRF POWER SOURCEVDD

這樣設定後 MacOS 可以看到 nRF5340-DK 上的 J-Link。

可以使用 ioreg 命令檢查:

ioreg -p IOUSB | grep -i -E "nordic|segger|j-link|nrf"

確認 USB 裝置。

看到類似:

  |   | | +-o **J-Link**@01122400  <class IOUSBHostDevice, id 0x10010fafb, registered, matched, active, busy 0 (325 ms), retain 41>

代表 J-Link USB interface 已經被 MacOS 偵測到。


軟體

安裝 Nordic Command Line Tools

一開始我以為我會用到 Nordic Command Line Tools 但後來發現完全不需要使用。
我當時安裝的是在 Nordic 下載的最新版本 nrf-command-line-tools-10.24.2-darwin.dmg,Nordic 網路超慢下載速度大概 20 KB/s 下載超久,安裝之後由於我是要使用 Rust 開發所以只有用到 J-Link ,但這個 package 內的 J-Link 版本(v7.94e)太舊,沒有 nRF54L15 的選項可以用,也許可以用相同 CPU (Cortex-M33)的選項替代,但我直接到 J-Link 抓最新的版本。
https://ithelp.ithome.com.tw/upload/images/20260910/20158828XT3CEgPpks.png
安裝 Nordic Command Line Tools 後,可以使用 nrfjprog 確認 J-Link ID,確認電腦有正常識別 nRF5340 DK:

nrfjprog --ids

得到:

1050042847

nrfjprog 這裡只是用來確認 J-Link 是否被 macOS 正確識別,後續 Rust 開發流程並不需要使用 nrfjprog。


安裝新版本的 J-Link

原本 J-Link:

J-Link Software V7.94e

segger.com 下載最新的 J-Link

更新後:

J-Link Software V9.74

更新後 JLinkExe 已經可以正確選擇:

nRF54L15 Cortex-M33

2. 開發測試程式

由於我是第一次使用 Rust 開發 Raytac AN54LV-DB-15 的應用程式,我不確定我可以正確的使用 Rust 開發並且燒錄。所以我要寫一個燈光閃爍的程式來測試這樣是可行的。

找出 AN54LV-DB-15 LED Pin Mapping

查看 Raytac AN54LV-DB-15 schematic
![[Raytac_AN54LV-DB-15_LEDs.png]]

LED nRF54L15 GPIO
LED0 P2.09
LED1 P1.10
LED2 P2.07
LED3 P1.14

這幾個 GPIO 是 AN54LV-DB-15 上的 LED 實際連接腳位。


建立 Rust Project

參考 Embassy Github example nRF54L15-app 建立專案:

cargo new nrf54l15-led
cd nrf54l15-led

nRF54L15 Application Core 使用的 Rust thumbv8m.main-none-eabihf target,先檢查:

rustup target list --installed

檢查是否有這個 target

thumbv8m.main-none-eabihf

如果沒有加入這個 target:

rustup target add thumbv8m.main-none-eabihf

設定 Cargo.toml

[package]
name = "nrf54l15-led"
version = "0.1.0"
edition = "2024"

[dependencies]
embassy-futures = { version = "0.1.2"}
embassy-executor = { version = "0.10.0", features = ["platform-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
embassy-time = { version = "0.5.1", features = ["defmt", "defmt-timestamp-uptime"] }
embassy-sync = { version = "0.8.0", features = ["defmt"] }
embassy-nrf = { version = "0.11.0", features = ["defmt", "nrf54l15-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] }
embedded-io = { version = "0.7.0", features = ["defmt"]  }
embedded-io-async = { version = "0.7.0", features = ["defmt"] }

rand = { version = "0.9.0", default-features = false }

defmt = "1.0.1"
defmt-rtt = "1.0.0"
panic-probe = { version = "1.0.0", features = ["print-defmt"] }

cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.0"

embedded-storage = "0.3.1"
portable-atomic = "1"

static_cell = "2"
hex-literal = "1.1"

參考 Embassy nRF54L15-app example 內的檔案建立以下檔案

  • memory.x
  • build.rs
  • .cargo/config.toml

src/main.rs

最簡單的版本:

#![no_std]
#![no_main]

use defmt::info;
use defmt_rtt as _;
use embassy_executor::Spawner;
use embassy_nrf::gpio::{Level, Output, OutputDrive};
use embassy_time::Timer;
use panic_probe as _;

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let p = embassy_nrf::init(Default::default());
    let mut led0 = Output::new(p.P2_09, Level::Low, OutputDrive::Standard);
    let mut led1 = Output::new(p.P1_10, Level::Low, OutputDrive::Standard);
    let mut led2 = Output::new(p.P2_07, Level::Low, OutputDrive::Standard);
    let mut led3 = Output::new(p.P1_14, Level::Low, OutputDrive::Standard);

    loop {
        info!("led on!");
        led0.set_high();
        // led1.set_high();
        // led2.set_high();
        // led3.set_high();
        Timer::after_millis(500).await;

        info!("led off!");
        led0.set_low();
        // led1.set_low();
        // led2.set_low();
        // led3.set_low();
        Timer::after_millis(500).await;
    }
}

Build

可以使用這個指令來 build

cargo build --target thumbv8m.main-none-eabihf

但由於 .cargo/config.toml 已經設定好要使用的 target 為 thumbv8m.main-none-eabihf 所以可以直接使用

cargo build

3. 燒錄程式

ELF 與 J-Link

Rust build 成功後得到:

target/thumbv8m.main-none-eabihf/debug/nrf54l15-led

這是一個 ELF executable。

可以確認:

file target/thumbv8m.main-none-eabihf/debug/nrf54l15-led

得到類似:

ELF 32-bit LSB executable, ARM, EABI5

安裝 cargo-binutils (rust-objcopy)

由於 J-Link 不能直接使用 ELF,所以需要將 ELF 轉為 HEX,可以使用 rust-objcopy 轉檔。
安裝命令:

cargo install cargo-binutils

確認:

rust-objcopy --version

ELF → HEX

將 Rust 產生的 ELF 轉成 Intel HEX。

命令:

rust-objcopy -O ihex target/thumbv8m.main-none-eabihf/debug/nrf54l15-led target/thumbv8m.main-none-eabihf/debug/nrf54l15-led.hex

HEX 是較適合直接描述「哪些 address 要寫入哪些資料」的 firmware image format。


使用 JLinkExe 連接 AN54LV-DB-15

J-Link 要使用的參數如下:

Device: NRF54L15
Core: Cortex-M33
Interface: SWD
Speed: 4000 kHz

啟動 J-Link 命令:

JLinkExe

然後:

J-Link> connect
Device> ?

https://ithelp.ithome.com.tw/upload/images/20260910/20158828D3z2bYbHXr.png

GUI 畫面選好 device 後接下來要設定 interface & interface speed,設定完他會執行一段測試,如下的顯示就是成功了。

Please specify target interface:

  J) JTAG (Default)

  S) SWD

  T) cJTAG

TIF>S

Specify target interface speed [kHz]. <Default>: 4000 kHz

Speed>

Device "NRF54L15_M33" selected.

  

  

Connecting to target via SWD

ConfigTargetSettings() start

ConfigTargetSettings() end - Took 278us

InitTarget() start

InitTarget() end - Took 3.53ms

Found SW-DP with ID 0x6BA02477

DPIDR: 0x6BA02477

CoreSight SoC-400 or earlier

AP map detection skipped. Manually configured AP map found.

AP[0]: AHB-AP (IDR: Not set, ADDR: 0x00000000)

AP[1]: APB-AP (IDR: Not set, ADDR: 0x00000000)

AP[2]: MEM-AP (IDR: Not set, ADDR: 0x00000000)

Iterating through AP map to find AHB-AP to use

AP[0]: Core found

AP[0]: AHB-AP ROM base: 0xE00FE000

CPUID register: 0x411FD210. Implementer code: 0x41 (ARM)

Feature set: Mainline

Cache: No cache

Found Cortex-M33 r1p0, Little endian.

FPUnit: 8 code (BP) slots and 0 literal slots

Security extension: implemented

Secure debug: enabled

CoreSight components:

ROMTbl[0] @ E00FE000

[0][0]: E00FF000 CID B105100D PID 000BB4C9 ROM Table

ROMTbl[1] @ E00FF000

[1][0]: E000E000 CID B105900D PID 000BBD21 DEVARCH 47702A04 DEVTYPE 00 Cortex-M33

[1][1]: E0001000 CID B105900D PID 000BBD21 DEVARCH 47701A02 DEVTYPE 00 DWT

[1][2]: E0002000 CID B105900D PID 000BBD21 DEVARCH 47701A03 DEVTYPE 00 FPB

[1][3]: E0000000 CID B105900D PID 000BBD21 DEVARCH 47701A01 DEVTYPE 43 ITM

[1][5]: E0041000 CID B105900D PID 002BBD21 DEVARCH 47724A13 DEVTYPE 13 ETM

[0][1]: E0040000 CID B105900D PID 000BBD21 DEVARCH 00000000 DEVTYPE 11 TPIU

Memory zones:

  Zone: "Default" Description: Default access mode

Cortex-M33 identified.

這代表:

Mac
 ↓
nRF5340-DK J-Link
 ↓
SWD
 ↓
AN54LV-DB-15
 ↓
nRF54L15 Cortex-M33

整條 debugger path 已經成功。
然後:

J-Link> loadfile /path/to/nrf54l15-led.hex

成功後需要手動啟動 go 讓 target 開始執行:

J-Link> g

可以使用 reset 對 target 執行 reset

J-Link> r

Troubleshooting

過程中曾經遇到:

loadfile 成功
但是程式沒有正常運作 (LED 沒有反應)

後來發現按下 AN54LV-DB-15 上的 RESET 後,程式正常執行。

因此需要注意:

loadfile

代表 firmware 已經寫入 target memory,

但在 debug workflow 中,不應該假設 target 一定已經以你預期的狀態重新啟動 firmware

遇到:

燒錄成功
但程式沒反應

可以先使用實體按鍵 reset 或斷電重連。


回顧 Rust 開發 Raytac AN54LV-DB-15 要做哪些事

今天實際驗證了整條 embedded development pipeline:

┌─────────────────────┐
│       Rust          │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│      Embassy        │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│  Cortex-M33 binary  │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│        ELF          │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│        HEX          │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│       J-Link        │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│        SWD          │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│      nRF54L15       │
│     Cortex-M33      │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│        GPIO         │
└──────────┬──────────┘
           ↓
┌─────────────────────┐
│     LED0 ~ LED3     │
└─────────────────────┘

使用 Probe-rs

實際上開發 embassy 的時候其實不需要使用 JLinkExe,使用 Probe-rs 更方便。
可以注意到 Embassy nRF54L15 example code .cargo/config.toml 已經設定好了。

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
runner = "probe-rs run --chip nrf54l15"

所以只要把設備上的線接好,直接執行 run 就可以了。

cargo run

執行後顯示

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s
     Running `probe-rs run --chip nrf54l15 target/thumbv8m.main-none-eabihf/debug/nrf54l15-led`
     Erasing ✔ 100% [####################]  52.00 KiB @  41.86 KiB/s (took 1s) 
 Programming ✔ 100% [####################]  52.00 KiB @  15.25 KiB/s (took 3s)
    Finished in 4.75s
0.000329 [INFO ] led on! (nrf54l15_led nrf54l15-led/src/main.rs:20)
0.500895 [INFO ] led off! (nrf54l15_led nrf54l15-led/src/main.rs:27)
1.001531 [INFO ] led on! (nrf54l15_led nrf54l15-led/src/main.rs:20)
1.502165 [INFO ] led off! (nrf54l15_led nrf54l15-led/src/main.rs:27)
2.002800 [INFO ] led on! (nrf54l15_led nrf54l15-led/src/main.rs:20)
2.503434 [INFO ] led off! (nrf54l15_led nrf54l15-led/src/main.rs:27)
3.004069 [INFO ] led on! (nrf54l15_led nrf54l15-led/src/main.rs:20)
3.504703 [INFO ] led off! (nrf54l15_led nrf54l15-led/src/main.rs:27)

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言