Merge pull request #122 from ferrous-systems/less-cargo-subcommands

move cargo-flash off the main track into the tooltips section
This commit is contained in:
Jorge Aparicio 2021-01-21 13:59:21 +01:00 committed by GitHub
commit 291110e75d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 72 deletions

View file

@ -8,9 +8,7 @@
- [Parts of an Embedded Program](./parts-embedded-program.md)
- [Building an Embedded Program](./building-program.md)
- [Binary Size](./binary-size.md)
- [Flashing the Program](./flashing-program.md)
- [Viewing Logs](./viewing-logs.md)
- [Running the Program from VS Code](./running-from-vsc.md)
- [Running the Program](./running-from-vsc.md)
- [Panicking](./panicking.md)
- [Using a Hardware Abstraction Layer](./using-hal.md)
- [Timers and Time](./time.md)

View file

@ -1,17 +0,0 @@
# Flashing the Program
✅ Use the following command to flash the program to the device.
``` console
$ cargo flash --chip nRF52840_xxAA --bin hello
```
> NOTE: If you run into an error along the lines of "Debug power request failed" retry the operation and the error should disappear.
This subcommand will build the program first so you'll always flash the latest version.
The `cargo-flash` subcommand flashes and runs the program but won't display logs. It is a deployment tool.
**🔎 How does flashing work?**
The flashing process consists of the PC communicating with a second microcontroller on the nRF52840 DK over USB (J2 port). This second microcontroller, named J-Link, is connected to the nRF52840 through a electrical interface known as SWD. The SWD protocol specifies procedures for reading memory, writing to memory, halting the target processor, reading the target processor registers, etc.

View file

@ -131,19 +131,11 @@ $ rustup +stable component add llvm-tools-preview
$ cargo install cargo-binutils
```
### Cargo subcommands
### General purpose tools
Install version v0.10.2 of the [`cargo-flash`](https://crates.io/crates/cargo-flash) and [`cargo-embed`](https://crates.io/crates/cargo-embed) subcommands, as well as the [`cargo-binutils`](https://crates.io/crates/cargo-binutils) set of subcommands using the following Cargo commands:
Install the [`cargo-binutils`](https://crates.io/crates/cargo-binutils) and [`probe-run`](https://crates.io/crates/probe-run) tools using the following Cargo commands:
``` console
$ cargo install cargo-flash --version 0.10.2 -f
(..)
Installed package `cargo-flash v0.8.0` (..)
$ cargo install cargo-embed --version 0.10.1 -f
(..)
Installed package `cargo-embed v0.10.1` (..)
$ cargo install cargo-binutils
(..)
Installed package `cargo-binutils v0.3.3` (..)
@ -153,7 +145,7 @@ $ cargo install probe-run
Installed package `probe-run v0.1.8` (..)
```
### Workshop tools
### Workshop specific tools
The [workshop git repository](https://github.com/ferrous-systems/embedded-trainings-2020) contains custom crates that help you with flashing and debugging the workshops. Depending on the workshop you're attending, you need to install all or some of them.

View file

@ -1,6 +1,4 @@
# Running the Program from VS Code
Both `cargo-embed` and `cargo-flash` are tools based on the `probe-rs` library. This library exposes an API to communicate with the J-Link and perform all the operations exposed by the JTAG protocol. We have developed a small Cargo runner called [probe-run](https://github.com/knurling-rs/probe-run) that uses the `probe-rs` library to streamline the process of running a program and printing logs, like `cargo-embed`, while also having better integration into VS code. We'll be using it in this workshop, and you can utilize it in your future projects too.
# Running the Program
✅ Open the `src/bin/hello.rs` file and click the "Run" button that's hovering over the `main` function.
@ -9,18 +7,49 @@ Both `cargo-embed` and `cargo-flash` are tools based on the `probe-rs` library.
If you are not using VS code, you can run the program out of your console.
Enter the command `cargo run --bin hello` from within the `beginer/apps` folder. Rust Analyzer's "Run" button is a short-cut for that command.
> NOTE: If you run into an error along the lines of "Debug power request failed" retry the operation and the error should disappear.
Expected output:
``` console
$ cargo run --bin hello
Running `probe-run --chip nRF52840_xxAA target/thumbv7em-none-eabihf/debug/hello`
(HOST) INFO flashing program (30.09 KiB)
(HOST) INFO success!
────────────────────────────────────────────────────────────────────────────────
INFO:hello -- Hello, world!
stack backtrace:
0: 0x0000229c - __bkpt
1: 0x0000030e - hello::__cortex_m_rt_main
2: 0x0000011a - main
3: 0x00001ba2 - Reset
0: __bkpt
1: hello::__cortex_m_rt_main
at src/bin/hello.rs:15
2: main
at src/bin/hello.rs:8
3: ResetTrampoline
at $REGISTRY/cortex-m-rt-0.6.13/src/lib.rs:547
4: Reset
at $REGISTRY/cortex-m-rt-0.6.13/src/lib.rs:550
```
`cargo run` will compile the application and then invoke `probe-run` with its argument set to the path of the output ELF file.
`cargo run` will compile the application and then invoke the `probe-run` tool with its argument set to the path of the output ELF file.
Unlike `cargo-embed`, `probe-run` will terminate when the program reaches a breakpoint (`asm::bkpt`) that halts the device. Before exiting, `probe-run` will print a stack backtrace of the program starting from the breakpoint. This can be used to write small test programs that are meant to perform some work and then terminate.
The `probe-run` tool will
- flash (load) the program on the microcontroller
- reset the microcontroller to make it execute the new program
- collect logs from the microcontroller and print them to the console
- print a backtrace of the program and exit when the devices reaches a breakpoint (`asm::bkpt()`)
Should you need to configure the `probe-run` invocation to e.g. flash a different microcontroller you can do that in the `.cargo/config.toml` file.
``` toml
[target.thumbv7em-none-eabihf]
runner = "probe-run --chip nRF52840_xxAA" # <- add/remove/modify flags here
# ..
```
**🔎 How does flashing work?**
The flashing process consists of the PC communicating with a second microcontroller on the nRF52840 DK over USB (J2 port). This second microcontroller, named J-Link, is connected to the nRF52840 through a electrical interface known as SWD. The SWD protocol specifies procedures for reading memory, writing to memory, halting the target processor, reading the target processor registers, etc.
**🔎 How does logging work?**
Logging is implemented using the Real Time Transfer (RTT) protocol. Under this protocol the target device writes log messages to a ring buffer stored in RAM; the PC communicates with the J-Link to read out log messages from this ring buffer. This logging approach is non-blocking in the sense that the target device does not have to wait for physical IO (USB comm, serial interface, etc.) to complete while logging messages since they are written to memory. It is possible, however, for the target device to run out of space in its logging ring buffer; this causes old log messages to be overwritten.

View file

@ -7,12 +7,6 @@
❗ The first two commands *must* return version `0.8.x`
``` console
$ cargo flash --version
0.10.2
$ cargo embed --version
0.10.1
$ cargo size --version
cargo-size 0.3.3
@ -51,4 +45,4 @@ $ usb-list
Bus 020 Device 007: ID 1b1c:0a42
Bus 020 Device 006: ID 1fc9:0132
(..)
```
```

View file

@ -1,6 +1,6 @@
# Tooltips
Besides the ones covered in this workshop, there are many more tools that make embedded development easier.
Besides the ones covered in this workshop, there are many more tools that make embedded development easier.
Here, we'd like to introduce you to some of these tools and encourage you to play around with them and adopt them if you find them helpful!
## `cargo-bloat`
@ -28,4 +28,33 @@ File .text Size Crate Name
5.1% 100.0% 9.4KiB .text section size, the file size is 184.5KiB
```
This breakdowns the size of the `.text` section by function. This breakdown can be used to identify the largest functions in the program; those could then be modified to make them smaller.
This breaks down the size of the `.text` section by function. This breakdown can be used to identify the largest functions in the program; those could then be modified to make them smaller.
## `cargo-flash`
`cargo-flash` is a tool that flashes a Rust program on a microcontroller.
From within a Cargo project it can be used like this:
``` console
$ # flash the `hello` program on an nRF52840 microcontroller
$ cargo flash --chip nRF52840_xxAA --bin hello
Flashing target/thumbv7em-none-eabihf/debug/blinky
Erasing sectors ✔ [00:00:00] [####] 20.00KB/ 20.00KB @ 21.24KB/s (eta 0s )
Programming pages ✔ [00:00:01] [####] 20.00KB/ 20.00KB @ 6.38KB/s (eta 0s )
Finished in 1.995s
```
The tool will reset the device after flashing it so when it finishes the device will be running the new firmware.
This subcommand will build the program first so you'll always flash the latest version.
The tool can also flash pre-built Rust programs so you could distribute binary releases of your firmware to your users and they can use `cargo-flash` to flash those binaries.
``` console
$ # you
$ cargo build --bin app --release
$ # distribute target/thumb*/release/app to your users
$ # your users
$ cargo flash --chip nRF52840_xxAA --elf ./app
```

View file

@ -1,23 +0,0 @@
# Viewing Logs with `cargo-embed`
To observe the program logs you can use the `cargo-embed` tool.
Unlike `cargo flash`, `cargo-embed` has no `--chip` flag; instead the target chip needs to be specified in a file named `Embed.toml`. This file must be placed in the root of the Cargo project / workspace, next to the `Cargo.toml` file.
``` toml
# Embed.toml
{{#include ../../beginner/apps/Embed.toml}}
```
✅ Use the following command to view your logs.
``` console
$ cargo embed --bin hello
```
This command will bring up a Text User Interface (TUI). You should see "Hello, world!" in the output. You can close the interface using Ctrl-C.
**🔎 How does logging work?**
Logging is implemented using the Real Time Transfer (RTT) protocol. Under this protocol the target device writes log messages to a ring buffer stored in RAM; the PC communicates with the J-Link to read out log messages from this ring buffer. This logging approach is non-blocking in the sense that the target device does not have to wait for physical IO (USB comm, serial interface, etc.) to complete while logging messages since they are written to memory. It is possible, however, for the target device to run out of space in its logging ring buffer; this causes old log messages to be overwritten.