Skip to content

Commit 7ce1074

Browse files
Use mdBook anchors (#221)
* docs: Use mdBook anchors * docs: Document anchors
1 parent f9fb003 commit 7ce1074

File tree

13 files changed

+63
-90
lines changed

13 files changed

+63
-90
lines changed

advanced/button-interrupt/examples/solution_led.rs

+6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ fn main() -> Result<()> {
1414
esp_idf_svc::sys::link_patches();
1515

1616
let peripherals = Peripherals::take()?;
17+
// ANCHOR: led
1718
let mut led = WS2812RMT::new(peripherals.pins.gpio2, peripherals.rmt.channel0)?;
19+
// ANCHOR_END: led
1820

1921
// Configures the button
2022
let mut button = PinDriver::input(peripherals.pins.gpio9)?;
@@ -33,6 +35,7 @@ fn main() -> Result<()> {
3335
})?;
3436
}
3537

38+
// ANCHOR: loop
3639
loop {
3740
// Enable interrupt and wait for new notificaton
3841
button.enable_interrupt()?;
@@ -41,9 +44,11 @@ fn main() -> Result<()> {
4144
// Generates random rgb values and sets them in the led.
4245
random_light(&mut led);
4346
}
47+
// ANCHOR_END: loop
4448
}
4549

4650
#[allow(unused)]
51+
// ANCHOR: random_light
4752
fn random_light(led: &mut WS2812RMT) {
4853
let mut color = RGB8::new(0, 0, 0);
4954
unsafe {
@@ -56,3 +61,4 @@ fn random_light(led: &mut WS2812RMT) {
5661

5762
led.set_pixel(color).unwrap();
5863
}
64+
// ANCHOR_END: random_light

advanced/i2c-driver/src/icm42670p_solution.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use embedded_hal::blocking::i2c;
44

55
/// ICM42670P device driver.
66
/// Datasheet: https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf
7+
// ANCHOR: struct
78
#[derive(Debug)]
89
pub struct ICM42670P<I2C> {
910
// The concrete I²C device implementation.
@@ -12,17 +13,21 @@ pub struct ICM42670P<I2C> {
1213
// Device address
1314
address: DeviceAddr,
1415
}
16+
// ANCHOR_END: struct
1517

1618
// See Table 3.3.2 in Documentation
1719
/// Contains the possible variants of the devices addesses as binary numbers.
1820
#[derive(Debug, Clone, Copy, PartialEq)]
21+
// ANCHOR: device_addr
1922
pub enum DeviceAddr {
2023
/// 0x68
2124
AD0 = 0b110_1000,
2225
/// 0x69
2326
AD1 = 0b110_1001,
2427
}
28+
// ANCHOR_END: device_addr
2529

30+
// ANCHOR: impl
2631
impl<I2C, E> ICM42670P<I2C>
2732
where
2833
I2C: i2c::WriteRead<Error = E> + i2c::Write<Error = E>,
@@ -31,6 +36,7 @@ where
3136
pub fn new(i2c: I2C, address: DeviceAddr) -> Result<Self, E> {
3237
Ok(Self { i2c, address })
3338
}
39+
// ANCHOR_END: impl
3440

3541
/// Returns the device's ID `0x67
3642
//(if it doesn't, something is amiss)
@@ -39,6 +45,7 @@ where
3945
self.read_register(Register::WhoAmI)
4046
}
4147

48+
// ANCHOR: read_write
4249
/// Writes into a register
4350
// This method is not public as it is only needed inside this file.
4451
#[allow(unused)]
@@ -56,10 +63,12 @@ where
5663
.write_read(self.address as u8, &[register.address()], &mut data)?;
5764
Ok(u8::from_le_bytes(data))
5865
}
66+
// ANCHOR_END: read_write
5967
}
6068

6169
// See Table 14.1 in documentation
6270
/// This enum represents the device's registers
71+
// ANCHOR: register
6372
#[derive(Clone, Copy)]
6473
pub enum Register {
6574
WhoAmI = 0x75,
@@ -70,3 +79,4 @@ impl Register {
7079
*self as u8
7180
}
7281
}
82+
// ANCHOR_END: register

advanced/i2c-sensor-reading/examples/part_2.rs

+4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ use esp_idf_svc::hal::{
66
peripherals::Peripherals,
77
prelude::*,
88
};
9+
// ANCHOR: include
910
use icm42670::{Address, Icm42670, PowerMode as imuPowerMode};
11+
// ANCHOR_END: include
12+
// ANCHOR: shared_bus
1013
use shared_bus::BusManagerSimple;
14+
// ANCHOR_END: shared_bus
1115
use shtcx::{self, PowerMode as shtPowerMode};
1216

1317
// Goals of this exercise:

book/src/02_0_preparations.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@ This chapter contains information about the course material, the required hardwa
66

77
We use Icons to mark different kinds of information in the book:
88
* ✅ Call for action.
9-
* ⚠️ Warnings, details that require special attention.
9+
* ⚠️ Warnings, and details that require special attention.
1010
* 🔎 Knowledge that dives deeper into a subject but which you aren't required to understand, proceeding.
1111
* 💡 Hints that might help you during the exercises
1212

1313
> Example note: Notes like this one contain helpful information
1414
15+
## Code Annotations
16+
17+
In some Rust files, you can find some anchor comments:
18+
```rust,ignore
19+
// ANCHOR: test
20+
let foo = 1;
21+
...
22+
// ANCHOR_END: test
23+
```
24+
Anchor comments can be ignored, they are only used to introduce those parts of code in this book. See [`mdBook` documentation](https://rust-lang.github.io/mdBook/format/mdbook.html#including-portions-of-a-file)
25+
1526
## Required Hardware
1627

1728
- [Rust ESP Board](https://github.com/esp-rs/esp-rust-board): available on Mouser, Aliexpress. [Full list of vendors](https://github.com/esp-rs/esp-rust-board#where-to-buy).

book/src/02_2_software.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ to compile the binaries for the Espressif target. Flashing binaries from contain
8383

8484
✅ Install [`Docker`](https://docs.docker.com/get-docker/) for your operating system.
8585

86-
✅ Get the docker image: There are 2 ways of getting the Docker image:
86+
✅ Get the Docker image: There are 2 ways of getting the Docker image:
8787
- Build the Docker image from the `Dockerfile`:
8888
```console
8989
docker image build --tag rust-std-training --file .devcontainer/Dockerfile .

book/src/03_2_cargo_generate.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ More information on generating projects can be found in the [Writing Your Own Ap
88
>
99
✅ Install `cargo-generate`:
1010

11-
```shell
11+
```console
1212
cargo install cargo-generate
1313
```
1414

1515
✅ Change to the `intro` directory and run `cargo generate` with the [`esp-idf` template](https://github.com/esp-rs/esp-idf-template):
1616

17-
```shell
17+
```console
1818
cd intro
1919
cargo generate esp-rs/esp-idf-template cargo
2020
```
@@ -59,14 +59,14 @@ channel = "nightly-2023-11-14" # change this line
5959

6060
✅ Run your project by using the following command out of the `hello-world` directory.
6161

62-
```shell
62+
```console
6363
cd hello-world
6464
cargo run
6565
```
6666

6767
✅ The last lines of your output should look like this:
6868

69-
```shell
69+
```console
7070
(...)
7171
I (268) cpu_start: Starting scheduler.
7272
Hello, world!

book/src/03_3_2_http_client.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ The `get` function uses [as_ref()](https://doc.rust-lang.org/std/convert/trait.A
3737

3838

3939
```rust
40-
let request = client.get(url.as_ref())?;
41-
let response = request.submit()?;
40+
{{#include ../../intro/http-client/examples/http_client.rs:request}}
4241
```
4342

4443
A successful response has [a status code in the 2xx range](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). Followed by the raw html of the website.

book/src/03_3_3_https_client.md

+2-6
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,14 @@ You will now make changes to your HTTP client files so that it also works for en
44

55
`intro/http-client/examples/http_client.rs` contains the solution. You can run it with the following command:
66

7-
```shell
7+
```console
88
cargo run --example https_client
99
```
1010

1111
Create a custom client configuration to use an `esp_idf_svc::http::client::EspHttpConnection` which enables the use of these certificates and uses default values for everything else:
1212

1313
```rust
14-
let connection = EspHttpConnection::new(&Configuration {
15-
use_global_ca_store: true,
16-
crt_bundle_attach: Some(esp_idf_sys::esp_crt_bundle_attach),
17-
..Default::default()
18-
}
14+
{{#include ../../intro/http-client/examples/https_client.rs:connection}}
1915
```
2016

2117
✅ Initialize your HTTP client with this new configuration and verify HTTPS works by downloading from an `https` resource, e.g. `https://espressif.com/`. the download will show as raw HTML in the terminal output.

book/src/04_3_1_i2c.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ HUM: [local humidity] %
7171
Using a bus manager, implement the second sensor. Read out its values and print the values from both sensors.
7272

7373

74-
Continue with your own solution from part one. Alternatively you can start with the provided partial solution of Part 1: `i2c-sensor-reading/examples/part_1.rs`.
74+
Continue with your own solution from part one. Alternatively, you can start with the provided partial solution of Part 1: `i2c-sensor-reading/examples/part_1.rs`.
7575

7676
`i2c-sensor-reading/examples/part_2.rs` contains a working solution of Part 2. You can consult it if you need help, by running:
7777

@@ -84,7 +84,7 @@ cargo run --example part_2
8484
✅ Import the driver crate for the ICM42670p.
8585

8686
```rust
87-
use icm42670::{Address, Icm42670, PowerMode as imuPowerMode};
87+
{{#include ../../advanced/i2c-sensor-reading/examples/part_2.rs:include}}
8888
```
8989

9090
✅ Create an instance of the sensor.
@@ -101,7 +101,7 @@ This is an ownership issue. Every place in memory needs to be owned by something
101101
✅ Import the bus manager crate.
102102

103103
```rust
104-
use shared_bus::BusManagerSimple;
104+
{{#include ../../advanced/i2c-sensor-reading/examples/part_2.rs:shared_bus}}
105105
```
106106

107107
✅ Create an instance of a simple bus manager. Make two proxies and use them instead of the original I²C instance to pass to the sensors.

book/src/04_3_2_i2c.md

+7-48
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,21 @@ We're not going to write an entire driver, merely the first step: the `hello wor
1313
To use a peripheral sensor first you must get an instance of it. The sensor is represented as a struct that contains both its device address, and an object representing the I²C bus itself. This is done using traits defined in the [`embedded-hal`](https://docs.rs/embedded-hal/latest/embedded_hal/) crate. The struct is public as it needs to be accessible from outside this crate, but its fields are private.
1414

1515
```rust
16-
#[derive(Debug)]
17-
pub struct ICM42670P<I2C> {
18-
/// The concrete I²C device implementation.
19-
i2c: I2C,
20-
21-
/// Device address
22-
address: DeviceAddr,
23-
}
24-
25-
// ...
16+
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:struct}}
2617
```
2718

2819
We add an `impl` block that will contain all the methods that can be used on the sensor instance. It also defines the Error Handling. In this block, we also implement an instantiating method. Methods can also be public or private. This method needs to be accessible from outside, so it's labelled `pub`. Note that written this way, the sensor instance takes ownership of the I²C bus.
2920

3021
```rust
31-
impl<I2C, E>ICM42670P<I2C>
32-
where
33-
I2C: i2c::WriteRead<Error = E> + i2c::Write<Error = E>,
34-
{
35-
/// Create a new instance of the ICM42670P.
36-
pub fn new(i2c: I2C, address: DeviceAddr) -> Result<Self, E> {
37-
Ok(Self{ i2c, address })
38-
}
22+
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:impl}}
3923
// ...
4024
```
4125
### Device Address
4226

4327
- The device's addresses are available in the code:
4428

4529
```rust
46-
AD0 = 0b110_1000, // or 0x68
47-
AD1 = 0b110_1001, // or 0x69
30+
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:device_addr}}
4831
```
4932

5033
- This I²C device has two possible addresses - `0x68` and `0x69`.
@@ -56,16 +39,7 @@ More information is available in the [datasheet, section 9.3](https://invensense
5639
The sensor's registers are represented as enums. Each variant has the register's address as value. The type `Register` implements a method that exposes the variant's address.
5740

5841
```rust
59-
#[derive(Clone, Copy)]
60-
pub enum Register {
61-
WhoAmI = 0x75,
62-
}
63-
64-
impl Register {
65-
fn address(&self) -> u8 {
66-
*self as u8
67-
}
68-
}
42+
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:register}}
6943

7044
```
7145

@@ -74,24 +48,9 @@ impl Register {
7448
We define a _read_ and a _write_ method, based on methods provided by the `embedded-hal` crate. They serve as helpers for more specific methods and as an abstraction that is adapted to a sensor with 8-bit registers. Note how the `read_register()` method is based on a `write_read()` method. The reason for this lies in the characteristics of the I²C protocol: We first need to write a command over the I²C bus to specify which register we want to read from. Helper methods can remain private as they don't need to be accessible from outside this crate.
7549

7650
```rust
77-
impl<I2C, E>ICM42670P<I2C>
78-
where
79-
I2C: i2c::WriteRead<Error = E> + i2c::Write<Error = E>,
80-
{
81-
//...
82-
fn write_register(&mut self, register: Register, value: u8) -> Result<(), E> {
83-
let byte = value as u8;
84-
self.i2c
85-
.write(self.address as u8, &[register.address(), byte])
86-
}
87-
88-
fn read_register(&mut self, register: Register) -> Result<u8, E> {
89-
let mut data = [0];
90-
self.i2c
91-
.write_read(self.address as u8, &[register.address()], &mut data)?;
92-
Ok(u8::from_le_bytes(data))
93-
}
94-
}
51+
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:impl}}
52+
// ...
53+
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:read_write}}
9554
```
9655

9756
✅ Implement a public method that reads the `WhoAmI` register with the address `0x75`. Make use of the above `read_register()` method.

book/src/04_4_3_interrupts.md

+9-25
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
1. Initialize the LED peripheral and switch the LED on with an arbitrary value just to see that it works.
44
```rust
5-
let mut led = WS2812RMT::new(peripherals.pins.gpio2, peripherals.rmt.channel0)?;
5+
{{#include ../../advanced/button-interrupt/examples/solution_led.rs:led}}
66

77
led.set_pixel(RGB8::new(20, 0, 20)).unwrap(); // Remove this line after you tried it once
88
```
@@ -31,28 +31,12 @@
3131

3232
4. **Optional**: If you intend to reuse this code in another place, it makes sense to put it into its own function. This lets us explore, in detail, which parts of the code need to be in `unsafe` blocks.
3333

34-
```rust
35-
// ...
36-
loop {
37-
// enable_interrupt should also be called after each received notification from non-ISR context
38-
button.enable_interrupt()?;
39-
notification.wait(esp_idf_svc::hal::delay::BLOCK);
40-
println!("Button pressed!");
41-
// Generates random rgb values and sets them in the led.
42-
random_light(&mut led);
43-
}
44-
// ...
45-
fn random_light(led: &mut WS2812RMT) {
46-
let mut color = RGB8::new(0, 0, 0);
47-
unsafe {
48-
let r = esp_random() as u8;
49-
let g = esp_random() as u8;
50-
let b = esp_random() as u8;
51-
52-
color = RGB8::new(r, g, b);
53-
}
54-
55-
led.set_pixel(color).unwrap();
56-
}
57-
```
34+
```rust
35+
// ...
36+
{{#include ../../advanced/button-interrupt/examples/solution_led.rs:loop}}
37+
38+
// ...
39+
{{#include ../../advanced/button-interrupt/examples/solution_led.rs:random_light}}
40+
41+
```
5842

intro/http-client/examples/http_client.rs

+2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ fn get(url: impl AsRef<str>) -> Result<()> {
5050

5151
// 3. Open a GET request to `url`
5252
let headers = [("accept", "text/plain")];
53+
// ANCHOR: request
5354
let request = client.request(Method::Get, url.as_ref(), &headers)?;
55+
// ANCHOR_END: request
5456

5557
// 4. Submit the request and check the status code of the response.
5658
// Successful http status codes are in the 200..=299 range.

intro/http-client/examples/https_client.rs

+2
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ fn main() -> Result<()> {
4444

4545
fn get(url: impl AsRef<str>) -> Result<()> {
4646
// 1. Create a new EspHttpClient. (Check documentation)
47+
// ANCHOR: connection
4748
let connection = EspHttpConnection::new(&Configuration {
4849
use_global_ca_store: true,
4950
crt_bundle_attach: Some(esp_idf_svc::sys::esp_crt_bundle_attach),
5051
..Default::default()
5152
})?;
53+
// ANCHOR_END: connection
5254
let mut client = Client::wrap(connection);
5355

5456
// 2. Open a GET request to `url`

0 commit comments

Comments
 (0)