Merge pull request #35 from ferrous-systems/edit-book

didactic layout and structure changes
This commit is contained in:
Jorge Aparicio 2020-07-14 08:58:49 +00:00 committed by GitHub
commit 92662a658c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 59 deletions

View file

@ -5,6 +5,7 @@
- [Beginner Workbook](./beginner-workbook.md)
- [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)

View file

@ -0,0 +1,50 @@
# Binary Size
ELF files contain metadata like debug information so their size on disk is not a good indication of the amount of Flash the program will use once it's loaded on the target device's memory.
To display the amount of Flash the program will occupy on the target device use the `cargo-size` tool, which is part of the `cargo-binutils` package.
✅ Use the following command to print the binary's size in system V format.
``` console
$ cargo size --bin hello -- -A
```
Expected output:
The breakdown of the program's static memory usage per *linker section*.
``` console
hello :
section size addr
.vector_table 256 0x0
.text 9740 0x100
.rodata 4568 0x270c
.data 8 0x20000000
.bss 2124 0x20000008
.uninit 0 0x20000854
```
**🔎 More details about each linker section:**
The first three sections are contiguously located in Flash memory -- Flash memory spans from address `0x0000_0000` to `0x0010_0000` (1 MB).
* The `.vector_table` section contains the *vector table*, a data structure required by the Cortex-M ISA.
* The `.text` section contains the instructions the program will execute.
* The `.rodata` section contains constants like strings literals.
The next three sections, `.data`, `.bss` and `.uninit`, are located in RAM -- RAM memory spans the address range `0x2000_0000` - `0x2004_0000` (256 KB). These sections contain statically allocated variables (`static` variables).
Another other useful tool to analyze the binary size of a program is `cargo-bloat`:
``` console
$ cargo bloat --bin hello
File .text Size Crate Name
0.7% 13.5% 1.3KiB std <char as core::fmt::Debug>::fmt
0.5% 9.6% 928B hello hello::__cortex_m_rt_main
0.4% 8.4% 804B std core::str::slice_error_fail
0.4% 8.0% 768B std core::fmt::Formatter::pad
0.3% 6.4% 614B std core::fmt::num::<impl core::fmt::Debug for usize>::fmt
(..)
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.

View file

@ -1,12 +1,6 @@
# Building an Embedded Program
The following command cross compiles the program to the ARM Cortex-M4 architecture.
``` console
$ cargo build --bin hello
```
The default in a Cargo project is to compile for the host (native compilation) but the `beginner/apps` project has been configured for cross compilation. This configuration can be seen in the Cargo configuration file (`.cargo/config`):
The default in a Cargo project is to compile for the host (native compilation). The `beginner/apps` project has been configured for cross compilation to the ARM Cortex-M4 architecture. This configuration can be seen in the Cargo configuration file (`.cargo/config`):
``` text
# .cargo/config
@ -14,49 +8,18 @@ The default in a Cargo project is to compile for the host (native compilation) b
target = "thumbv7em-none-eabi" # = ARM Cortex-M4
```
✅ Inside the folder `beginner/apps`, use the following command to cross compile the program to the ARM Cortex-M4 architecture.
``` console
$ cargo build --bin hello
```
The output of the compilation process will be an ELF (Executable and Linkable Format) file. The file will be placed in the `target/thumbv7em-none-eabi` directory.
✅ Run `$ file target/thumbv7em-none-eabi/debug/hello` and compare if your output is as expected.
Expected output:
``` console
$ file target/thumbv7em-none-eabi/debug/hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
```
## Binary size
ELF files contain metadata like debug information so their size on disk is not a good indication of the amount of Flash the program will use once it's loaded on the target device's memory.
To display the amount of Flash the program will occupy on the target device use the `cargo-size` tool (part of the `cargo-binutils` package):
``` console
$ cargo size --bin hello -- -A
hello :
section size addr
.vector_table 256 0x0
.text 9740 0x100
.rodata 4568 0x270c
.data 8 0x20000000
.bss 2124 0x20000008
.uninit 0 0x20000854
```
This gives you a breakdown of the program's static memory usage per *linker section*.
The `.vector_table` section contains the *vector table*, a data structure required by the Cortex-M ISA. The `.text` section contains the instructions the program will execute. The `.rodata` section contains constants like strings literals. These three sections are contiguously located in Flash memory -- Flash memory spans from address `0x0000_0000` to `0x0010_0000` (1 MB).
The next three sections, `.data`, `.bss` and `.uninit`, are located in RAM -- RAM memory spans the address range `0x2000_0000` - `0x2004_0000` (256 KB). These sections contain statically allocated variables (`static` variables).
Another other useful tool to analyze the binary size of a program is `cargo-bloat`:
``` console
$ cargo bloat --bin hello
File .text Size Crate Name
0.7% 13.5% 1.3KiB std <char as core::fmt::Debug>::fmt
0.5% 9.6% 928B hello hello::__cortex_m_rt_main
0.4% 8.4% 804B std core::str::slice_error_fail
0.4% 8.0% 768B std core::fmt::Formatter::pad
0.3% 6.4% 614B std core::fmt::num::<impl core::fmt::Debug for usize>::fmt
(..)
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.
```

View file

@ -1,12 +1,12 @@
# Flashing the Program
The following command will flash the ELF file to the device.
✅ Use the following command to flash the ELF file to the device.
``` console
$ cargo flash --chip nRF52840_xxAA --elf target/thumbv7em-none-eabi/debug/hello
```
> NOTE if you run into an error along the lines of "Debug power request failed" retry the operation and the error should disappear
> NOTE: If you run into an error along the lines of "Debug power request failed" retry the operation and the error should disappear.
Alternatively you can run this command, which builds the application before flashing it.
@ -16,4 +16,6 @@ $ cargo flash --chip nRF52840_xxAA --bin hello
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 JTAG. The JTAG protocol specifies procedures for reading memory, writing to memory, halting the target processor, reading the target processor registers, etc.

View file

@ -1,26 +1,30 @@
# Parts of an Embedded Program
[❗Intro ]
Open the `beginner/apps` folder in VS Code.
We will look at the elements that distinguish an embedded Rust program from a desktop program.
✅ Open the `beginner/apps` folder in VS Code.
``` console
$ # or use "File > Open Folder" in VS Code
$ code beginner/apps
```
Then open the `src/bin/hello.rs` file.
Then open the `src/bin/hello.rs` file.
If you find it more convenient to open the repository at the root then please also add the `beginner/apps` folder to the VS Code workspace: right click the left side panel, select "Add folder to workspace" and add the `beginner/apps` folder.
[❗No optional way of doing things here]
Note the differences between this embedded program and a desktop program:
## In the file, you will find the following attributes:
[❗Have a non embedded program up to compare]
### `#![no_std]`
The `#![no_std]` attribute indicates that the program will not make use of the standard library, `std` crate. Instead it will use the `core` library, a subset of the standard library that does depend not on a underlying operating system (OS).
The `#![no_std]` attribute indicates that the program will not make use of the standard library, the `std` crate. Instead it will use the `core` library, a subset of the standard library that does not depend on an underlying operating system (OS).
### `#![no_main]`
The `#![no_main]` attribute indicates that the program will use a custom entry point instead of the default `fn main() { .. }` one.
The `#[entry]` attribute declares the custom entry point of the program. The entry point must be a divergent function; note that the return type is the never type `!`. The function is not allowed to return; therefore the program is not allowed to terminate.
### `#[entry]`
The `#[entry]` attribute declares the custom entry point of the program. The entry point must be a divergent function whose return type is the never type `!`. The function is not allowed to return; therefore the program is not allowed to terminate.