本篇文章將介紹如何使用GDB命令調試Rust嵌入式代碼,以國產的arm單片機py32
為例。開發環境為Mac下,使用Jlink作為下載和調試工具。
原理
我們調試單片機的主要用到該單片機編譯工具鏈的gdb工具arm-none-eabi-gdb
。與本地gdb工具調試不一樣的是,嵌入式gdb工具的目標通常在遠端的嵌入式主板上而非本地主機,因此需要一個調試器來連接嵌入式主板和主機,通常可以使用jlink,stlink,cmsis-cap等工具提供服務,通過調試工具將固件燒錄到硬件后,再與gdb程序進行通信,解析調試命令,控制遠程硬件CPU。
測試程序
#![no_std]
#![no_main]
use embedded_hal::timer::CountDown;
use fugit::ExtU32;
use hal::mode::Blocking;
use hal::timer::advanced_timer::AnyTimer;
use py32f030_hal as hal;
use {defmt_rtt as _, panic_probe as _};
#[cortex_m_rt::entry]
fn main() -> ! {
defmt::info!("timer counter examples start...");
let p = hal::init(Default::default());
let timer = AnyTimer::<_, Blocking>::new(p.TIM1).unwrap();
let mut counter = timer.as_counter();
let mut cnt = 0;
loop {
// 延時 5s
defmt::info!("repeat...{} ", cnt);
let _ = counter.start(5u32.secs());
let _ = counter.wait();
cnt += 1;
}
}
開啟GDB
在Embed.toml
文件配置中開啟GDB服務
[default.general]
chip = "PY32F030x8"
[default.rtt]
enabled = false
[default.gdb]
enabled = true
[default.reset]
halt_afterwards = true
執行cargo embed
命令燒錄代碼以及自動開啟GDB服務,默認端口1337
,保持該命令后臺繼續運行。
gdb調試
在其他終端中執行命令
arm-none-eabi-gdb target/thumbv6m-none-eabi/debug/examples/advanced_timer_block_2
連接GDB服務器target remote:1337
即可連接單片機,可查看CPU信息。
如查看arm寄存器:info registers
查看匯編代碼disassemble
可以在匯編文件中看到代碼的起點是cortex_m_rt::DefaultPreInit
函數。然后是進入Reset
,然后才進入main
函數。
通過命令step
單步執行,可以在命令disassemble
的左側箭頭查看當前運行的地址。
為了快速執行到main
函數,可以用斷點命令b main
打斷點,然后使用continue
命令直接運行到斷點處。
由于匯編后的函數和變量名可能被重新命令,可以使用命令set print asm-demangle on
,讓匯編中的函數和變量使用原代碼中的命名。
可以使用list
命令查看當前代碼執行的情況,使用break N
命令添加指定行的斷點
使用info locals
命令查看當前的局部變量,使用print
命令打印變量的值