Merge pull request #39 from ferrous-systems/tie-loose-ends

remove empty sections; add open-ended exercises
This commit is contained in:
Jorge Aparicio 2020-07-14 11:11:09 +00:00 committed by GitHub
commit 9cab8bb24e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 77 additions and 33 deletions

View file

@ -179,7 +179,7 @@ checksum = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc"
[[package]]
name = "nrf-hal-common"
version = "0.10.0"
source = "git+https://github.com/japaric/nrf-hal?branch=radio#7076639891fd2493e1c61a7aca71944b48ae0458"
source = "git+https://github.com/japaric/nrf-hal?branch=radio#b57ba8100eda0145de9823e63c7f5e2cf5d888d1"
dependencies = [
"cast",
"cortex-m",
@ -194,7 +194,7 @@ dependencies = [
[[package]]
name = "nrf52840-hal"
version = "0.10.0"
source = "git+https://github.com/japaric/nrf-hal?branch=radio#7076639891fd2493e1c61a7aca71944b48ae0458"
source = "git+https://github.com/japaric/nrf-hal?branch=radio#b57ba8100eda0145de9823e63c7f5e2cf5d888d1"
dependencies = [
"cast",
"cortex-m",

View file

@ -17,6 +17,7 @@
- [Radio In ](./radio-in.md)
- [Radio Puzzle](./radio-puzzle.md)
- [Starting a Project from Scratch](./from-scratch.md)
- [Next Steps](./beginner-next-steps.md)
- [Advanced Workbook](./advanced-workbook.md)
- [Code Organization](./code-organisation.md)
- [Listing USB Devices](./listing-usb-devices.md)
@ -44,13 +45,11 @@
- [Idle State](./idle-state.md)
- [Inspecting the Descriptors](./inspecting-descriptors.md)
- [Getting it Configured](./getting-device-configured.md)
- [Next Steps](./next-steps.md)
- [String Descriptors](./string-descriptors.md)
- [Custom Control Transfers](./custom-control-transfers.md)
- [Next Steps](./advanced-next-steps.md)
- [References and Resources](./references-resources.md)
- [Troubleshooting](./troubleshooting.md)
- [`cargo-size` is not working](./troubleshoot-cargo-size.md)
- [`cargo-flash` is not working](./troubleshoot-cargo-flash.md)
- [Rust analyzer is not working](./troubleshoot-rust-analyzer.md)
- [`cargo-build` fails to link](./troubleshoot-cargo-build.md)
- [`dongle-flash` is not working](./troubleshoot-dongle-flash.md)
- [`dongle-flash` is not working](./troubleshoot-dongle-flash.md)

View file

@ -0,0 +1,33 @@
# Next Steps
## String descriptors
If you'd like to continue working on your workshop project, we recommend adding String Descriptors support to the USB firmware.
- First, you'll want to read through section 9.6.7 of the USB spec, which covers string descriptors.
- Next, we suggest you change your *configuration* descriptor to use string descriptors. You'll want to change the `iConfiguration` field to a non-zero value. Note that this change will likely break enumeration.
- Now, re-run the program to see what new control requests you get from the host.
- You'll need to update the `usb` parser to handle the new requests.
- Then you can extend the logic of `ep0setup` to handle these new requests.
- Eventually, you'll need to send a string descriptor to the host. Note here that Rust string literals are UTF-8 encoded but the USB protocol uses UTF-**16** strings. You'll need to convert between these formats.
- After you have `iConfiguration` working you can start adding strings to other descriptors like the device descriptor e.g. its `iProduct` field.
To verify that string descriptors are working in a cross-platform way you can extend the `print-descs` program to also print the device's string descriptors. See the [`read_string_descriptor`] method but note that this must be called on a "device handle", which is what the commented out `open` operation does.
[`read_string_descriptor`]: https://docs.rs/rusb/0.6.2/rusb/struct.DeviceHandle.html#method.read_string_descriptor
## Explore more RTIC features
We have covered only a few of the core features of the RTIC framework but the framework has many more features like *software* tasks, tasks that can be spawned by the software; message passing between tasks; and task scheduling, which allows the creation of periodic tasks. We encourage to check the [RTIC book][rtic-book] which describes the features we haven't covered here.
[rtic-book]: https://rtic.rs/0.5/book/en/
## usb-device
[`usb-device`] is a library for building USB devices. It has been built using traits (the pillar of Rust's *generics*) such that USB interfaces like HID and TTY ACM can be implemented in a device agnostic manner. The device details then are limited to a trait *implementation*. There's a work in progress implementation of the `usb-device` trait for the nRF52840 device in [this PR] and there are many `usb-device` "classes" like [HID] and [TTY ACM] that can be used with that trait implementation. We encourage you to check out that implementation, test it on different OSes and report issues, or contribute fixes, to the `usb-device` ecosystem.
[this PR]: https://github.com/nrf-rs/nrf-hal/pull/144
[HID]: https://crates.io/crates/usbd-hid
[TTY ACM]: https://crates.io/crates/usbd-serial
[`usb-device`]: https://crates.io/crates/usb-device

View file

@ -0,0 +1,37 @@
# Next Steps
## Collision avoidance
If you've already completed the main workshop tasks or would like to explore more on your own, we suggest you test the collision avoidance of the IEEE 802.15.4 radio used by the Dongle and DK.
If you check the API documentation of the `Radio` abstraction we have been using you'll notice that we haven't used these methods: `energy_detection_scan()`, `set_cca()` and `try_send()`.
The first method scans the currently selected channel (see `set_channe()l`), measures the energy level of ongoing radio communication in this channel and returns the maximum energy observed over a span of time. This method can be used to determine what the *idle* energy level of a channel is. If there's non-IEEE 802.15.4 traffic on this channel the method will return a high value.
Under the 802.15.4 specification, before sending a data packet devices must first check if there's communication going on in the channel. This process is known as Clear Channel Assessment (CCA). The `send` method we have been used performs CCA in a loop and sends the packet only when the channel appears to be idle. The `try_send` method performs CCA *once* and returns the `Err` variant is the channel appears to be busy. In this failure scenario the device does not send any packet.
The `Radio` abstraction supports 2 CCA modes: `CarrierSense` and `EnergyDetection`. `CarrierSense` is the default CCA mode and what we have been using in this workshop. `CarrierSense` will only look for ongoing 802.15.4 traffic in the channel but ignore other traffic like 2.4 GHz WiFi and Bluetooth. The `EnergyDetection` method is able to detect ongoing non-802.15.4 traffic.
Here are some things for you to try out:
- First, read the section 6.20.12.4 of the nRF52840 Product Specification, which covers the nRF52840's implementation of CCA.
- Disconnect the Dongle. Write a program for the DK that scans and reports the energy levels of all valid 802.15.4 channels. In your location which channels have high energy levels when there's no ongoing 802.15.4 traffic? If you can, use an application like [WiFi Analyzer] to see which WiFi channels are in use in your location. Compare the output of WiFiAnalyzer to the values you got from `energy_detection_scan`. Is there a correspondence? Note that WiFi channels don't match in frequency with 802.15.4 channels; some mapping is required to convert between them -- [check this illustration for more details about co-existence of 802.15.4 and WiFi][coexistence].
[WiFi Analyzer]: https://play.google.com/store/apps/details?id=com.farproc.wifi.analyzer&hl=en
[coexistence]: https://inet.omnetpp.org/docs/showcases/wireless/coexistence/doc/
- Choose the channel with the highest idle energy. Now write a program on the DK that sets the CCA mode to `EnergyDetection` and then send a packet over this channel using `try_send`. The `EnergyDetection` CCA mode requires a Energy Detection (ED) "threshold" value. Try different threshold values. What threshold value makes the `try_send` succeed?
- Repeat the previous experiment but use the channel with the lowest idle energy.
- Pick the channel with the lowest idle energy. Run the `loopback` app on the Dongle and set its listening channel to the chosen channel. Modify the DK program to perform a `send` operation immediately followed by a `try_send` operation. The `try_send` operation will collide with the response of the Dongle (remember: the Dongle responds to all incoming packets). Find a ED threshold that detects this collision and makes `try_send` return the `Err` variant.
## Interrupt handling
We haven't covered interrupt handling in the workshop but the `cortex-m-rt` crate provides attributes to declare exception and interrupt handlers: `#[exception]` and `#[interrupt]`. You can find documentation about these attributes and how to safely share data with interrupt handlers using Mutexes in the ["Concurrency" chapter][concurrency] of the Embedded Rust book.
Another way to deal with interrupts is to use a framework like Real-Time Interrupt-driven Concurrency ([RTIC]); this framework has a [book] that explains how you can build reactive applications using interrupts. We use this framework in the advanced level workshop.
[concurrency]: https://rust-embedded.github.io/book/concurrency/index.html
[RTIC]: https://crates.io/crates/cortex-m-rtic
[book]: https://rtic.rs/0.5/book/en/

View file

@ -1 +0,0 @@
# Custom Control Transfers

View file

@ -37,8 +37,7 @@ The `thumb` targets listed above are all the currently supported ARM Cortex-M ta
| `thumbv8m.main-none-eabihf` | ARM Cortex-M33F, ARM Cortex-M35PF |
The ARM Cortex-M ISA is backwards compatible so for example you could compile a program using the `thumbv6m-none-eabi` target and run it on an ARM Cortex-M4 microcontroller. This will work but using the `thumbv7em-none-eabi` results in better performance (ARMv7-M instructions will be emitted by the compiler) so it should be preferred. The opposite, compiling for `thumbv7em-none-eabi` and running the resulting
> TODO delete or finish last sentence
The ARM Cortex-M ISA is backwards compatible so for example you could compile a program using the `thumbv6m-none-eabi` target and run it on an ARM Cortex-M4 microcontroller. This will work but using the `thumbv7em-none-eabi` results in better performance (ARMv7-M instructions will be emitted by the compiler) so it should be preferred.
### 2. Its memory layout.
@ -135,18 +134,10 @@ If no HAL is available for your device then you'll need to build one yourself. T
[SVD]: http://www.keil.com/pack/doc/CMSIS/SVD/html/index.html
[`svd2rust`]: https://crates.io/crates/svd2rust
---
> NOTE additional content, if needed / desired
# Hello, 💡
Now that you've set up your own project from scratch, you could start playing around with it by turning on one of the DK's on-board LEDs using only the HAL. Some hints that might be helpful there:
- The [Nordic Infocenter][infocenter] tells you which LED is connected to which pin.
[infocenter]: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fug_nrf52840_dk%2FUG%2Fnrf52840_DK%2Fhw_buttons_leds.html
# (extra) adding addresses to packets
> have people use the `ieee802154` crate to add a MAC header to the radio packet. New dongle firmware would be required to respond differently to broadcast packets and addressed packets

View file

@ -1,14 +0,0 @@
# Next Steps
We have covered only a few of the core features of the RTIC framework but the framework has many more features like *software* tasks, tasks that can be spawned by the software; message passing between tasks; and task scheduling, which allows the creation of periodic tasks. We encourage to check the [RTIC book][rtic-book] which describes the features we haven't covered here.
[rtic-book]: https://rtic.rs/0.5/book/en/
[`usb-device`] is a library for building USB devices. It has been built using traits (the pillar of Rust's *generics*) such that USB interfaces like HID and TTY ACM can be implemented in a device agnostic manner. The device details then are limited to a trait *implementation*. There's a work in progress implementation of the `usb-device` trait for the nRF52840 device in [this PR] and there are many `usb-device` "classes" like [HID] and [TTY ACM] that can be used with that trait implementation.
[this PR]: https://github.com/nrf-rs/nrf-hal/pull/144
[HID]: https://crates.io/crates/usbd-hid
[TTY ACM]: https://crates.io/crates/usbd-serial
[`usb-device`]: https://crates.io/crates/usb-device

View file

@ -1 +0,0 @@
# String Descriptors