You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This puts the given data into a packet, along with a random device address, and then waits for a reply containing a matching device address. This allows the function to reject packets that were intended for another device, and makes it somewhat robust when multiple devices are running on the same channel at the same time.
Copy file name to clipboardExpand all lines: exercise-book/src/nrf52-radio-alt-containers.md
+4-3Lines changed: 4 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,12 +2,13 @@
2
2
3
3
## Modify-in-place
4
4
5
-
If you solved the puzzle using a `Vec` buffer you can try solving it without the buffer as a stretch goal. You may find the [slice methods][slice] that let you mutate its data useful. A solution that does not use a `heapless:Vec` buffer can be found in the `src/bin/radio-puzzle-solution-2.rs` file.
5
+
If you solved the puzzle using a `Vec` buffer you can try solving it without the buffer as a stretch goal. You may find the [slice methods][slice] that let you mutate a `Packet`'s data useful, but remember that the first six bytes of your `Packet` will be the random device address - you can't decrypt those! A solution that does not use a `heapless:Vec` buffer can be found in the `src/bin/radio-puzzle-solution-2.rs` file.
6
6
7
7
## Using `liballoc::BTreeMap`
8
8
9
-
If you get all that working and still need something else to try, you could look at the [`BTreeMap`][btreemap] contained within `liballoc`. This will require you to set up a global memory allocator, like [`embedded-alloc`][embedded-alloc].
9
+
If you solved the puzzle using a `heapless::Vec` buffer and a `heapless::LinearMap` and you still need something else to try, you could look at the [`Vec`][vec] and [`BTreeMap`][btreemap] types contained within `liballoc`. This will require you to set up a global memory allocator, like [`embedded-alloc`][embedded-alloc].
Copy file name to clipboardExpand all lines: exercise-book/src/nrf52-radio-in.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,4 +16,4 @@ The Dongle will respond as soon as it receives a packet. If you insert a delay b
16
16
17
17
Having log statements between `send` and `recv_timeout` can also cause packets to be missed so try to keep those two calls as close to each other as possible and with as little code in between as possible.
18
18
19
-
> NOTE Packet loss can always occur in wireless networks, even if the radios are close to each other. The `Radio` API we are using will not detect lost packets because it does not implement IEEE 802.15.4 Acknowledgement Requests. If you are having trouble with lost packets, consider adding a retry loop, but remember you are sharing the airwaves with other users, so make sure not to spam incessantly by accident!
19
+
> NOTE Packet loss can always occur in wireless networks, even if the radios are close to each other. The `Radio` API we are using will not detect lost packets because it does not implement IEEE 802.15.4 Acknowledgement Requests. For the next step in the workshop, we will use a new function to handle this for us. For the sake of other radio users, please do ensure you never call `send()` in a tight loop!
Copy file name to clipboardExpand all lines: exercise-book/src/nrf52-radio-puzzle-help.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ Something you will likely run into while solving this exercise are *character* l
40
40
41
41
*IMPORTANT* you do not need to use the `str` or `char` API to solve this problem, other than for printing purposes. Work directly with slices of bytes (`[u8]`) and bytes (`u8`); and only convert those to `str` or `char` when you are about to print them.
42
42
43
-
> Note: The plaintext string is *not* stored in `puzzle-fw` so running `strings` on it will not give you the answer. Nice try.
43
+
> Note: The plaintext secret string is *not* stored in `puzzle-fw` so running `strings` on it will not give you the answer. Nice try.
Copy file name to clipboardExpand all lines: exercise-book/src/nrf52-radio-puzzle.md
+17-6Lines changed: 17 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,18 @@ Like in the previous sections the Dongle will listen for radio packets -- this t
19
19
20
20
✅ Open the [`nrf52-code/radio-app`](../../nrf52-code/radio-app) folder in VS Code; then open the `src/bin/radio-puzzle.rs` file. Run the program.
21
21
22
-
This will send a zero sized packet `let msg = b""` to the dongle.
22
+
This will send a zero sized packet `let msg = b""` to the dongle. It does this using a special function called `dk::send_recv`. This function will:
23
+
24
+
1. Determine a unique address for your nRF52840 (Nordic helpfully bake a different random address into every nRF52 chip they make)
25
+
2. Construct a packet where the first six bytes are the unique address, and the remainder are the ones you passed to the `send_recv()` function
26
+
3. Use the `Radio::send()` method to wait for the channel to be clear (using a *Clear Channel Assessment*) before actually sending the packet
27
+
4. Use the `Radio::recv_timeout()` method to wait for a reply, up to the given number of microseconds specified
28
+
5. Check that the first six bytes in the reply match our six byte address
29
+
a. If so, the remainder of the reply is returned as the `Ok` variant
30
+
b. Otherwise, increment a retry counter and, if we have run out of retry attempts, we return the `Err` variant
31
+
c. Otherwise, we go back to step 2 and try again.
32
+
33
+
This function allows communication with the USB dongle to be relatively robust, even in the presence of other devices on the same channel. However, it's not perfect and sometimes you will run out of retry attempts and your program will need to be restarted.
23
34
24
35
❗ 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.
25
36
@@ -33,13 +44,13 @@ What happens?
33
44
<details>
34
45
<summary>Answer</summary>
35
46
36
-
The Dongle will respond differently depending on the length of the incoming packet:
47
+
The Dongle will respond differently depending on the length of the payload in the incoming packet:
37
48
38
-
- On zero-sized packets it will respond with the encrypted string.
39
-
- On one-byte sized packets it will respond with the *direct* mapping from a *plaintext* letter (single `u8` value) -- the letter contained in the packet -- to the *ciphertext* letter (`u8` value).
40
-
- On packets of any other length the Dongle will respond with the string `correct` if it received the decrypted string, otherwise it will respond with the `incorrect` string.
49
+
- On zero-sized payloads (i.e. packets that only contain the device address and nothing else) it will respond with the encrypted string.
50
+
- On one-byte sized payloads it will respond with the *direct* mapping from the given *plaintext* letter (single `u8` value) to the corresponding *ciphertext* letter (another `u8` value).
51
+
- On payloads of any other length the Dongle will respond with the string `correct` if it received the correct secret string, otherwise it will respond with the string `incorrect`.
41
52
42
-
The Dongle will always respond with packets that are valid UTF-8 so you can use `str::from_utf8` on the response packets.
53
+
The Dongle will always respond with payloads that are valid UTF-8 so you can use `str::from_utf8` on the response packets. However, do not attempt to look inside the raw packet, as it will contain six random address bytes at the start, and they will not be valid UTF-8. Only look at the `&[u8]` that the `send_recv()` function returns, and treat the `Packet` as just a storage area that you don't look inside.
43
54
44
55
This step is illustrated in `src/bin/radio-puzzle-1.rs`
Copy file name to clipboardExpand all lines: exercise-book/src/nrf52-radio-setup.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,4 +12,4 @@ received 5 bytes (CRC=Ok(0xdad9), LQI=53)
12
12
13
13
The program broadcasts a radio packet that contains the 5-byte string `Hello` over channel 20 (which has a center frequency of 2450 MHz). The `loopback` program running on the Dongle is listening to all packets sent over channel 20; every time it receives a new packet it reports its length and the Link Quality Indicator (LQI) metric of the transmission over the USB/serial interface. As the name implies the LQI metric indicates how good the connection between the sender and the receiver is.
14
14
15
-
To repeatedly send a packet without re-flashing your DK, try pressing the BOOT/RESET button (next to the nRF USB connector that we aren't using yet).
15
+
Because of how our firmware generates a *semihosting exception* to tell our flashing tool (`probe-run`) when the firmware has finished running, if you load the `radio-send` firmware and then power-cycle the nRF52840-DK, the firmware will enter a reboot loop and repeatedly send a packet. This is because nothing catches the *semihosting exception* and so the CPU reboots, sends a packet, and then tries another *semihosting exception*.
0 commit comments