Skip to content

Commit

Permalink
edited ch 5
Browse files Browse the repository at this point in the history
  • Loading branch information
BartMassey committed Jul 10, 2024
1 parent 565fe82 commit 9cc20b6
Show file tree
Hide file tree
Showing 14 changed files with 350 additions and 352 deletions.
1 change: 1 addition & 0 deletions mdbook/src/05-led-roulette/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ panic-halt = "0.2.0"
panic-rtt-target = "0.1.3"
rtt-target = "0.5.0"
microbit-v2 = "0.15.0"
embedded-hal = "1.0.0"

[dependencies.cortex-m]
version = "0.7.7"
Expand Down
54 changes: 31 additions & 23 deletions mdbook/src/05-led-roulette/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,64 @@
Alright, let's start by building the following application:

<p align="center">
<video src="../assets/roulette_fast.mp4" loop autoplay>
<video src="../assets/roulette_fast.mp4" width="500" loop autoplay/>
</p>

I'm going to give you a high level API to implement this app but don't worry we'll do low level
stuff later on. The main goal of this chapter is to get familiar with the *flashing* and debugging
process.
I'm going to give you a high level API to implement this app. Don't worry — we'll do low level stuff
later on. The main goal of this chapter is to get familiar with the *flashing* and debugging
process. "Flashing" is the process of writing a compiled program's code into "flash" memory on a
device: it has nothing to do with the LEDs.

The starter code is in the `src` directory of the book repository. Inside that directory there are more
directories named after each chapter of this book. Most of those directories are starter Cargo
The starter code is in the `src` directory of the book repository. Inside that directory there are
more directories named after each chapter of this book. Most of those directories are starter Cargo
projects.

Now, jump into the `src/05-led-roulette` directory. Check the `src/main.rs` file:
Now, jump into the `src/05-led-roulette` directory. Check the `examples/init.rs` file:

``` rust
{{#include src/main.rs}}
{{#include examples/init.rs}}
```

Microcontroller programs are different from standard programs in two aspects: `#![no_std]` and
`#![no_main]`.

The `no_std` attribute says that this program won't use the `std` crate, which assumes an underlying
OS; the program will instead use the `core` crate, a subset of `std` that can run on bare metal
systems (i.e., systems without OS abstractions like files and sockets).
systems (that is, systems without OS abstractions like files and sockets).

The `no_main` attribute says that this program won't use the standard `main` interface, which is
tailored for command line applications that receive arguments. Instead of the standard `main` we'll
use the `entry` attribute from the [`cortex-m-rt`] crate to define a custom entry point. In this
program we have named the entry point "main", but any other name could have been used. The entry
point function must have signature `fn() -> !`; this type indicates that the function can't return
-- this means that the program never terminates.
program we have named the entry point `main`, but any other name could have been used. The entry
point function must have signature `fn() -> !`; this type indicates that the function can't return.
This means that the program never terminates by returning from `main`: if the compiler detects that
this would be possible it will refuse to compile your program.

[`cortex-m-rt`]: https://crates.io/crates/cortex-m-rt

If you are a careful observer, you'll also notice there is a `.cargo` directory in the Cargo project
as well. This directory contains a Cargo configuration file (`.cargo/config`) that tweaks the
linking process to tailor the memory layout of the program to the requirements of the target device.
This modified linking process is a requirement of the `cortex-m-rt` crate.
If you are a careful observer, you'll also notice there is a possibly-hidden `.cargo` directory in
the Cargo project as well. This directory contains a Cargo configuration file `.cargo/config.toml`.

Furthermore, there is also an `Embed.toml` file
```toml
{{#include .cargo/config.toml}}
```

This file tweaks the linking process to tailor the memory layout of the program to the requirements
of the target device. This modified linking process is a requirement of the `cortex-m-rt`
crate. The `.cargo/config.toml` file also tells Cargo how to build and run code on our MB2.

There is also an `Embed.toml` file here:

```toml
{{#include Embed.toml}}
```

This file tells `cargo-embed` that:

* we are working with an NRF52833.
* we want to halt the chip after we flashed it so our program does not instantly jump to the loop
* we want to disable RTT, RTT being a protocol that allows the chip to send text to a debugger.
You have in fact already seen RTT in action, it was the protocol that sent "Hello World" in chapter 3.
* we want to enable GDB, this will be required for the debugging procedure
- We are working with an NRF52833.
- We want to halt the chip after flashing it, so our program stops before `main`.
- We want to disable RTT. RTT is a protocol that allows the chip to send text to a debugger.
You have already seen RTT in action: it was the protocol that sent "Hello World" in chapter 3.
- We want to enable GDB. This will be required for the debugging procedure.

Alright, let's start by building this program.
Now that we've seen what's going on, let's start by building this program.
61 changes: 33 additions & 28 deletions mdbook/src/05-led-roulette/build-it.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Build it

The first step is to build our "binary" crate. Because the microcontroller has a different
architecture than your computer we'll have to cross compile. Cross compiling in Rust land is as simple
as passing an extra `--target` flag to `rustc`or Cargo. The complicated part is figuring out the
argument of that flag: the *name* of the target.
architecture than your computer we'll have to cross compile. Cross compiling in Rust land is as
simple as passing an extra `--target` flag to `rustc`or Cargo. The complicated part is figuring out
the argument of that flag: the *name* of the target.

As we already know the microcontroller on the micro:bit v2 has a Cortex-M4F processor in it, the one on v1 a Cortex-M0.
`rustc` knows how to cross-compile to the Cortex-M architecture and provides several different targets that cover the different processors
families within that architecture:
As we already know the microcontroller on the micro:bit v2 has a Cortex-M4F processor in it.
`rustc` knows how to cross-compile to the Cortex-M architecture and provides several different
targets that cover the different processors families within that architecture:

- `thumbv6m-none-eabi`, for the Cortex-M0 and Cortex-M1 processors
- `thumbv7m-none-eabi`, for the Cortex-M3 processor
Expand All @@ -16,50 +16,55 @@ families within that architecture:
- `thumbv8m.main-none-eabi`, for the Cortex-M33 and Cortex-M35P processors
- `thumbv8m.main-none-eabihf`, for the Cortex-M33**F** and Cortex-M35P**F** processors

(The `hf`/`F` parts have hardware floating point acceleration. This will make
numeric computations involving fractional ("floating decimal point") computations
much faster.)
"Thumb" here refers to a version of the Arm instruction set that has smaller instructions for
reduced code size (it's a pun, see). The `hf`/`F` parts have hardware floating point
acceleration. This will make numeric computations involving fractional ("floating decimal point")
computations much faster.

For the micro:bit v2, we'll want the `thumbv7em-none-eabihf` target.

Before cross-compiling you have to download a pre-compiled version of the standard library
(a reduced version of it, actually) for your target. That's done using `rustup`:
Before cross-compiling you have to download a pre-compiled version of the standard library (a
reduced version of it, actually) for your target. That's done using `rustup`:

``` console
$ rustup target add thumbv7em-none-eabihf
```

You only need to do the above step once; `rustup` will re-install a new standard library
(`rust-std` component) whenever you update your toolchain. Therefore you can skip this step, if you have already added the necessary target
You only need to do the above step once; `rustup` will then update this target (re-installing a new
standard library `rust-std` component that contains the `core` library we use) whenever you update
your toolchain. Therefore you can skip this step if you have already added the necessary target
while [verifying your setup].

[verifying your setup]: ../03-setup/verify.html#verifying-cargo-embed


With the `rust-std` component in place you can now cross compile the program using Cargo:
With the `rust-std` component in place you can now cross compile the program using Cargo.
Make sure you are in the `src/05-led-roulette` directory, then build. This initial code is an
example, so we compile it as such.

``` console
# make sure you are in the `src/05-led-roulette` directory

$ cargo build --target thumbv7em-none-eabihf
$ cargo build --example init
Compiling semver-parser v0.7.0
Compiling typenum v1.12.0
Compiling cortex-m v0.6.3
(...)
Compiling microbit-v2 v0.10.1
Compiling proc-macro2 v1.0.86
...

Finished dev [unoptimized + debuginfo] target(s) in 33.67s
```

> **NOTE** Be sure to compile this crate *without* optimizations. The provided Cargo.toml
> file and build command above will ensure optimizations are off.
> **NOTE** Be sure to compile this crate *without* optimizations. The provided `Cargo.toml` file and
> build command above will ensure optimizations are off as long as you *don't* pass `cargo` the
> `--release` flag.
OK, now we have produced an executable. This executable won't blink any LEDs: it's just a simplified
version that we will build upon later in the chapter. As a sanity check, let's verify that the
produced executable is actually an ARM binary. (The command below is equivalent to

readelf -h ../../../target/thumbv7em-none-eabihf/debug/examples/init

OK, now we have produced an executable. This executable won't blink any LEDs,
it's just a simplified version that we will build upon later in the chapter.
As a sanity check, let's verify that the produced executable is actually an ARM binary:
on systems that have `readelf`.)

``` console
# equivalent to `readelf -h target/thumbv7em-none-eabihf/debug/led-roulette`
$ cargo readobj --target thumbv7em-none-eabihf --bin led-roulette -- --file-headers
$ cargo readobj --example init -- --file-headers
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Expand Down
Loading

0 comments on commit 9cc20b6

Please sign in to comment.