From 6dc89fb8bd98b75659078030786faa93dd8dcc93 Mon Sep 17 00:00:00 2001 From: Mirabellensaft Date: Thu, 5 Aug 2021 17:49:56 +0200 Subject: [PATCH 1/3] rewritten passages --- .../src/radio-puzzle-help.md | 12 ++++----- embedded-workshop-book/src/radio-puzzle.md | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/embedded-workshop-book/src/radio-puzzle-help.md b/embedded-workshop-book/src/radio-puzzle-help.md index f94eb7f..434eeed 100644 --- a/embedded-workshop-book/src/radio-puzzle-help.md +++ b/embedded-workshop-book/src/radio-puzzle-help.md @@ -2,7 +2,7 @@ ## Use a dictionary. -Our suggestion is to use a dictionary / map. `std::collections::HashMap` is not available in `no_std` code (without linking to a global allocator) but you can use one of the stack-allocated maps in the [`heapless`] crate. It supplies a stack-allocated, fixed-capacity version of the `std::Vec` type which will come in handy to store byte arrays. To store character mappings we recommend using a `heapless::IndexMap`. +Our suggestion is to use a dictionary / map. `std::collections::HashMap` is not available in `no_std` code (without linking to a global allocator) but you can use one of the stack-allocated maps in the [`heapless`] crate. It supplies a stack-allocated, fixed-capacity version of the `std::Vec` type which will come in handy to store byte arrays. To store character mappings we recommend using a `heapless::LinearMap`. `heapless` is already declared as a dependency in the Cargo.toml of the project so you can directly import it into the application code using a `use` statement. @@ -12,13 +12,13 @@ Our suggestion is to use a dictionary / map. `std::collections::HashMap` is not ``` rust use heapless::Vec; // like `std::Vec` but stack-allocated -use heapless::FnvIndexMap; // a dictionary / map -use heapless::consts::*; // defines U16, U32, U64... etc. to set the size of the IndexMap +use heapless::LinearMap; // a dictionary / map +use heapless::consts::*; // defines U16, U32, U64... etc. to set the size of the LinearMap fn main() { // A hash map with a capacity of 16 key-value pairs allocated on the stack // note that U16 is a heapless constant, not Rust's u16 - let mut my_map = FnvIndexMap::<_, _, U16>::new(); + let mut my_map = LinearMap::<_, _, U16>::new(); my_map.insert(b'A', b'~').unwrap(); // A vector with a fixed capacity of 8 elements allocated on the stack @@ -28,9 +28,9 @@ fn main() { } ``` -If you haven't used a stack-allocated collection before note that you'll need to specify the capacity of the collection as a type parameter using one of the "type-level values" in the `heapless::consts` module (e.g. `U8`, `U64` etc.). The [`heapless::IndexMap` documentation][indexMap] of the `heapless` crate has some usage examples, as does the [`heapless::Vec` documentation][vec]. +If you haven't used a stack-allocated collection before note that you'll need to specify the capacity of the collection as a type parameter using one of the "type-level values" in the `heapless::consts` module (e.g. `U8`, `U64` etc.). The [`heapless::LinearMap` documentation][indexMap] of the `heapless` crate has some usage examples, as does the [`heapless::Vec` documentation][vec]. -[indexMap]: https://docs.rs/heapless/0.5.5/heapless/struct.IndexMap.html +[indexMap]: https://docs.rs/heapless/0.5.5/heapless/struct.LinearMap.html [vec]: https://docs.rs/heapless/0.5.5/heapless/struct.Vec.html ## Note the difference between character literals and byte literals! diff --git a/embedded-workshop-book/src/radio-puzzle.md b/embedded-workshop-book/src/radio-puzzle.md index 1d1b377..1d1923b 100644 --- a/embedded-workshop-book/src/radio-puzzle.md +++ b/embedded-workshop-book/src/radio-puzzle.md @@ -2,10 +2,13 @@ ![illustration showing that you send plaintext and the dongle responds with ciphertext](../img/puzzle_illustration.jpg) -Your task in this section is to decrypt the [substitution cipher] encrypted *ASCII* string stored in the Dongle. The string has been encrypted using *simple substitution*. +Your task in this section is to decrypt the [substitution cipher] encrypted *ASCII* string stored in the Dongle using one of the stack-allocated maps in the [`heapless`] crate. The string has been encrypted using *simple substitution*. + +## Preparing the Dongle [substitution cipher]: https://en.wikipedia.org/wiki/Substitution_cipher +[`heapless`]: https://docs.rs/heapless ✅ Flash the `puzzle.hex` program on the Dongle. Follow the instructions from the "nRF52840 Dongle" section but flash the `puzzle.hex` program instead of the `loopback.hex` one -- don't forget to put the Dongle in bootloader mode before invoking `nrfdfu`. @@ -13,13 +16,25 @@ Your task in this section is to decrypt the [substitution cipher] encrypted *ASC Like in the previous sections the Dongle will listen for radio packets -- this time over *channel 25* -- while also logging messages over a USB/serial interface. +## Sending Messages and Receiving the Dongle's Responses + ✅ Open the `beginner/apps` folder in VS Code; then open the `src/bin/radio-puzzle.rs` file. Run the program. - -## Dongle Responses +This will send a zero sized packet `let msg = b""` to the dongle. ❗ The Dongle responds to the DK's requests wirelessly (i.e. by sending back radio packets) as well. You'll see the dongle responses printed by the DK. This means you don't have to worry if serial-term doesn't work on your machine. +✅ Try sending one-byte sized packets. +✅ Try sending longer packets. + +What happens? + +❗ The Dongle responds to the DK's requests wirelessly (i.e. by sending back radio packets) as well. You'll see the dongle responses printed by the DK. This means you don't have to worry if serial-term doesn't work on your machine. + + +
+ Answer + The Dongle will respond differently depending on the length of the incoming packet: - On zero-sized packets it will respond with the encrypted string. @@ -28,4 +43,8 @@ The Dongle will respond differently depending on the length of the incoming pack The Dongle will always respond with packets that are valid UTF-8 so you can use `str::from_utf8` on the response packets. -See the next chapter for solving stragies and help. \ No newline at end of file +This step is illustrated in `src/bin/radio-puzzle-1.rs` + +
+ +From here on, the exercise can be solved in multiple ways. If you have an idea on how to go from here and what tools to use, you can work on your own. If you don't have an idea what to do next or what tools to use, we'll provide a guide on the next page. \ No newline at end of file From d7f4b6ab132cac5ca4a8ef08a9ab4062860f29fb Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 6 Aug 2021 16:55:17 +0200 Subject: [PATCH 2/3] Update probe-run output to newer versions --- boards/dk/src/lib.rs | 3 +- embedded-workshop-book/src/panicking.md | 28 ++++++++++++------- .../src/running-from-vsc.md | 17 ++++------- .../src/stack-overflow-protection.md | 18 ++++++------ 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/boards/dk/src/lib.rs b/boards/dk/src/lib.rs index aaa1005..508f66c 100644 --- a/boards/dk/src/lib.rs +++ b/boards/dk/src/lib.rs @@ -321,8 +321,7 @@ fn RTC0() { unsafe { core::mem::transmute::<_, RTC0>(()).events_ovrflw.reset() } } -/// Exits the application and prints a backtrace when the program is executed through the `probe-run` -/// Cargo runner +/// Exits the application when the program is executed through the `probe-run` Cargo runner pub fn exit() -> ! { log::info!("`dk::exit() called; exiting ...`"); // force any pending memory operation to complete before the BKPT instruction that follows diff --git a/embedded-workshop-book/src/panicking.md b/embedded-workshop-book/src/panicking.md index 0093782..1163b5f 100644 --- a/embedded-workshop-book/src/panicking.md +++ b/embedded-workshop-book/src/panicking.md @@ -5,20 +5,28 @@ This program attempts to index an array beyond its length and this results in a panic. ``` console +(HOST) INFO flashing program (34.79 KiB) +(HOST) INFO success! +──────────────────────────────────────────────────────────────────────────────── ERROR:panic_log -- panicked at 'index out of bounds: the len is 3 but the index is 3', src/bin/panic.rs:29:13 +──────────────────────────────────────────────────────────────────────────────── stack backtrace: - 0: 0x000022f0 - __bkpt - 1: 0x00002010 - rust_begin_unwind - 2: 0x00000338 - core::panicking::panic_fmt - 3: 0x00000216 - core::panicking::panic_bounds_check - 4: 0x0000016a - panic::bar - 5: 0x00000158 - panic::foo - 6: 0x00000192 - panic::__cortex_m_rt_main - 7: 0x00000178 - main - 8: 0x0000199e - Reset + 0: HardFaultTrampoline + +[...] + 7: panic::bar + at src/bin/panic.rs:29:13 + 8: panic::foo + at src/bin/panic.rs:22:5 + 9: panic::__cortex_m_rt_main + at src/bin/panic.rs:12:5 + 10: main + at src/bin/panic.rs:8:1 +[...] +(HOST) ERROR the program panicked ``` -In `no_std` programs the behavior of panic is defined using the `#[panic_handler]` attribute. In the example, the *panic handler* is defined in the `panic_log` crate but we can also implement it manually: +In `no_std` programs the behavior of panic is defined using the `#[panic_handler]` attribute. In the example, the *panic handler* is defined in the `panic_log` crate but we can also implement it manually: ✅ Comment out the `panic_log` import and add the following function to the example: diff --git a/embedded-workshop-book/src/running-from-vsc.md b/embedded-workshop-book/src/running-from-vsc.md index b3a44ef..371abcc 100644 --- a/embedded-workshop-book/src/running-from-vsc.md +++ b/embedded-workshop-book/src/running-from-vsc.md @@ -14,20 +14,13 @@ 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! +(HOST) INFO flashing program (34.79 KiB) +(HOST) INFO success! ──────────────────────────────────────────────────────────────────────────────── INFO:hello -- Hello, world! -stack backtrace: - 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 +──────────────────────────────────────────────────────────────────────────────── +(HOST) INFO device halted without error + ``` `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. diff --git a/embedded-workshop-book/src/stack-overflow-protection.md b/embedded-workshop-book/src/stack-overflow-protection.md index 6a68dbc..d874251 100644 --- a/embedded-workshop-book/src/stack-overflow-protection.md +++ b/embedded-workshop-book/src/stack-overflow-protection.md @@ -16,24 +16,24 @@ The `spam()` function allocates data on the stack until the stack boundaries are ✅ Run `stack_overflow.rs` -You should see output similar to this: +You should see output similar to this (the program output between the horizontal bars might be missing): ``` console - (...) - (HOST) INFO flashing program (32.68 KiB) - (HOST) INFO success! +(HOST) INFO flashing program (35.25 KiB) +(HOST) INFO success! ──────────────────────────────────────────────────────────────────────────────── INFO:stack_overflow -- provoking stack overflow... INFO:stack_overflow -- address of current `use_stack` at recursion depth 0: 0x2003aec0 INFO:stack_overflow -- address of current `use_stack` at recursion depth 1: 0x20039e50 (...) INFO:stack_overflow -- address of current `use_stack` at recursion depth 10: 0x20030a60 -INFO:stack_overflow -- address of current `use_stack` at recursionstack backtrace: +INFO:stack_overflow -- address of current `use_stack` at recursion +──────────────────────────────────────────────────────────────────────────────── +stack backtrace: 0: HardFaultTrampoline - 1: ??? -error: the stack appears to be corrupted beyond this point - (HOST) ERROR the program has overflowed its stack +(HOST) WARN call stack was corrupted; unwinding could not be completed +(HOST) ERROR the program has overflowed its stack ``` ❗️ `flip-link` is a third-party tool, so make sure you've installed it through `cargo install flip-link` @@ -51,4 +51,4 @@ If you'd like to use `flip-link` in your own projects, this is all you need to a [`flip-link`]: https://github.com/knurling-rs/flip-link -[`flip-link` README]: https://github.com/knurling-rs/flip-link/blob/main/README.md \ No newline at end of file +[`flip-link` README]: https://github.com/knurling-rs/flip-link/blob/main/README.md From e3721713a9fb14aea80392c45a01503e4dec1c36 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 3 Dec 2021 14:51:52 +0100 Subject: [PATCH 3/3] Remove confusing redundant instruction --- embedded-workshop-book/src/hello-world.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embedded-workshop-book/src/hello-world.md b/embedded-workshop-book/src/hello-world.md index bb901dc..43cfaa5 100644 --- a/embedded-workshop-book/src/hello-world.md +++ b/embedded-workshop-book/src/hello-world.md @@ -2,11 +2,11 @@ In this section, we'll set up the integration in VS Code and run the first program. -✅ Open the `advanced/firmware` folder in VS Code and open the `src/bin/hello.rs` file from the `advanced/apps` folder. +✅ Open the `advanced/firmware` folder in VS Code and open the `src/bin/hello.rs` file. -> Note: To ensure full Rust-Analyzer support, do not open the whole `embedded-trainings-2020` folder. +> Note: To ensure full rust-analyzer support, do not open the whole `embedded-trainings-2020` folder. -Give Rust Analyzer some time to analyze the file and its dependency graph. When it's done, a "Run" button will appear over the `main` function. If it doesn't appear on its own, type something in the file, delete and save. This should trigger a re-load. +Give rust-analyzer some time to analyze the file and its dependency graph. When it's done, a "Run" button will appear over the `main` function. If it doesn't appear on its own, type something in the file, delete and save. This should trigger a re-load. ✅ Click the "Run" button to run the application on the microcontroller.