Выбрать главу

Breakpoint 1, main () at examples/hello.rs:15

15 let mut stdout = hio::hstdout().unwrap();

NOTE If GDB blocks the terminal instead of hitting the breakpoint after you issue the continue command above, you might want to double check that the memory region information in the memory.x file is correctly set up for your device (both the starts and lengths).

Advancing the program with next should produce the same results as before.

(gdb) next

16 writeln!(stdout, "Hello, world!").unwrap();

(gdb) next

19 debug::exit(debug::EXIT_SUCCESS);

At this point you should see "Hello, world!" printed on the OpenOCD console, among other stuff.

$ openocd

(..)

Info : halted: PC: 0x08000e6c

Hello, world!

Info : halted: PC: 0x08000d62

Info : halted: PC: 0x08000d64

Info : halted: PC: 0x08000d66

Info : halted: PC: 0x08000d6a

Info : halted: PC: 0x08000a0c

Info : halted: PC: 0x08000d70

Info : halted: PC: 0x08000d72

Issuing another next will make the processor execute debug::exit. This acts as a breakpoint and halts the process:

(gdb) next

Program received signal SIGTRAP, Trace/breakpoint trap.

0x0800141a in __syscall ()

It also causes this to be printed to the OpenOCD console:

$ openocd

(..)

Info : halted: PC: 0x08001188

semihosting: *** application exited ***

Warn : target not halted

Warn : target not halted

target halted due to breakpoint, current mode: Thread

xPSR: 0x21000000 pc: 0x08000d76 msp: 0x20009fc0, semihosting

However, the process running on the microcontroller has not terminated and you can resume it using continue or a similar command.

You can now exit GDB using the quit command.

(gdb) quit

Debugging now requires a few more steps so we have packed all those steps into a single GDB script named openocd.gdb. The file was created during the cargo generate step, and should work without any modifications. Let's have a peak:

cat openocd.gdb

target extended-remote :3333

# print demangled symbols

set print asm-demangle on

# detect unhandled exceptions, hard faults and panics

break DefaultHandler

break HardFault

break rust_begin_unwind

monitor arm semihosting enable

load

# start the process but immediately halt the processor

stepi

Now running <gdb> -x openocd.gdb target/thumbv7em-none-eabihf/debug/examples/hello will immediately connect GDB to OpenOCD, enable semihosting, load the program and start the process.

Alternatively, you can turn <gdb> -x openocd.gdb into a custom runner to make cargo run build a program and start a GDB session. This runner is included in .cargo/config.toml but it's commented out.

head -n10 .cargo/config.toml

[target.thumbv7m-none-eabi]

# uncomment this to make `cargo run` execute programs on QEMU

# runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"

[target.'cfg(all(target_arch = "arm", target_os = "none"))']

# uncomment ONE of these three option to make `cargo run` start a GDB session

# which option to pick depends on your system

runner = "arm-none-eabi-gdb -x openocd.gdb"

# runner = "gdb-multiarch -x openocd.gdb"

# runner = "gdb -x openocd.gdb"

$ cargo run --example hello

(..)

Loading section .vector_table, size 0x400 lma 0x8000000

Loading section .text, size 0x1e70 lma 0x8000400

Loading section .rodata, size 0x61c lma 0x8002270

Start address 0x800144e, load size 10380

Transfer rate: 17 KB/sec, 3460 bytes/write.

(gdb)

Embedded systems can only get so far by executing normal Rust code and moving data around in RAM. If we want to get any information into or out of our system (be that blinking an LED, detecting a button press or communicating with an off-chip peripheral on some sort of bus) we're going to have to dip into the world of Peripherals and their 'memory mapped registers'.

You may well find that the code you need to access the peripherals in your micro-controller has already been written, at one of the following levels:

   • Micro-architecture Crate - This sort of crate handles any useful routines common to the processor core your microcontroller is using, as well as any peripherals that are common to all micro-controllers that use that particular type of processor core. For example the cortex-m crate gives you functions to enable and disable interrupts, which are the same for all Cortex-M based micro-controllers. It also gives you access to the 'SysTick' peripheral included with all Cortex-M based micro-controllers.

   • Peripheral Access Crate (PAC) - This sort of crate is a thin wrapper over the various memory-wrapper registers defined for your particular part-number of micro-controller you are using. For example, tm4c123x for the Texas Instruments Tiva-C TM4C123 series, or stm32f30x for the ST-Micro STM32F30x series. Here, you'll be interacting with the registers directly, following each peripheral's operating instructions given in your micro-controller's Technical Reference Manual.

   • HAL Crate - These crates offer a more user-friendly API for your particular processor, often by implementing some common traits defined in embedded-hal. For example, this crate might offer a Serial struct, with a constructor that takes an appropriate set of GPIO pins and a baud rate, and offers some sort of write_byte function for sending data. See the chapter on Portability for more information on embedded-hal.

   • Board Crate - These crates go one step further than a HAL Crate by pre-configuring various peripherals and GPIO pins to suit the specific developer kit or board you are using, such as stm32f3-discovery for the STM32F3DISCOVERY board.

A board crate is the perfect starting point, if you're new to embedded Rust. They nicely abstract the HW details that might be overwelming when starting studying this subject, and makes standard tasks easy, like turning a LED on or off. The functionality they exposes varies a lot between boards. Since this book aims at staying hardware agnostic, the board crates won't be covered by this book.

If you want to experiment with the STM32F3DISCOVERY board, it is highly recommmand to take a look at the stm32f3-discovery board crate, which provides functionality to blink the board LEDs, access its compass, bluetooth and more. The Discovery book offers a great introduction to the use of a board crate.