The first learning opportunity
For me, learning means working through the material by writing and trying out the examples for myself. This also means I have to work through the errors as well. It did not take long to hit the first issue. I wrote the basic Hello World program, to blink an LED, from chapter 5 of the book in my own repository. I then proceeded to flash the device and I got the following error:
> cargo embed --example light-up
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
Config default
Target /home/-x-x-/embedded/target/thumbv7em-none-eabihf/debug/examples/light-up
WARN probe_rs::flashing::loader: No loadable segments were found in the ELF file.
Error No loadable segments were found in the ELF file.
This came as a surprise after all the setup and verification I did in the previous session. I tried running the example in a clone of the book's repository and that worked like a charm. Meaning the issue had to be in my project. The error message didn't give me much to go on and a quick search did not prove helpful either. This was definitely turning out to be a learning opportunity.
The program I was working with was as basic as this:
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use nrf52833_hal::{gpio, pac};
use panic_halt as _;
#[entry]
fn main() -> ! {
let peripherals = pac::Peripherals::take().unwrap();
let p0 = gpio::p0::Parts::new(peripherals.P0);
let _row1 = p0.p0_21.into_push_pull_output(gpio::Level::High);
let _col1 = p0.p0_28.into_push_pull_output(gpio::Level::Low);
#[allow(clippy::empty_loop)]
loop {}
}
Since the warning mentioned probe-rs, I followed this clue as my first step.
Unfortunately the documentation did not give me any more insights to explain
the issue. I then turned to the documentation for the runtime crate used in the
project: cortex-m-rt.
According to the documentation the crate requires a memory.x file to specify
the memory layout of the microcontroller.
The linker script,
link.x,
in the cortex-m-rt crate depends on this file to specify the chip memory
layout:
/* Provides information about the memory layout of the device */
/* This will be provided by the user (see `memory.x`) or by a Board Support Crate */
INCLUDE memory.x
For our nRF52833 chip the file and memory layout should look like this:
MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
RAM : ORIGIN = 0x20000000, LENGTH = 128K
}
We could add this file to the project and Cargo would build and flash the program to our microcontroller just fine. However, we are using the nrf52833-hal hardware abstraction layer (HAL) crate and the crate do provides the necessary memory layout for our microcontroller: memory.x.
We just need to put the pieces together by instructing Cargo to pass the
correct arguments when building for our cortex-m chip. Adding this as
configuration to Cargo in the .cargo/config.toml file of the project should
connect the dots for us:
[build]
target = "thumbv7em-none-eabihf"
[target.thumbv7em-none-eabihf]
rustflags = [
"-C", "link-arg=-Tlink.x"
]
Running cargo embed again with the configuration in place:
> cargo embed --example light-up
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
Config default
Target /home/-*-*-/Work/rust-embedded-discovery/target/thumbv7em-none-eabihf/debug/examples/light-up
Erasing ✔ 100% [####################] 8.00 KiB @ 32.56 KiB/s (took 0s)
Programming ✔ 100% [####################] 8.00 KiB @ 30.58 KiB/s (took 0s)
Finished in 0.51s
Success!
I learned a lot from this little detour and in the end it also provided me with an opportunity. Turns out that a section of the Rust Embedded MB2 Discovery Book had fallen out during refactoring. Thus it gave me an opportunity for a lightweight contribution to the Embedded Rust community in the form of two PRs. The first, #57, to add the missing section back to the book and the second, #58, to add a new paragraph to the troubleshooting chapter in case anyone else runs into the same issue.
Thank you for reading!