本篇文章将介绍如何使用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命令打印变量的值