- rework RTIC resources section in the adv. material

- change the USB PID so it matches the date of the workshop
This commit is contained in:
Jorge Aparicio 2020-06-16 10:16:25 +02:00
parent b7297fa2ab
commit fcf0e310ab
7 changed files with 258 additions and 30 deletions

View file

@ -58,7 +58,7 @@ Bus 002 Device 001: ID 1d6b:0003
Bus 001 Device 002: ID 0cf3:e300
Bus 001 Device 003: ID 0c45:6713
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 059: ID 2020:0705 <- nRF52840 on the nRF52840 Development Kit
Bus 001 Device 059: ID 2020:0717 <- nRF52840 on the nRF52840 Development Kit
```
## Hello, world!
@ -130,19 +130,31 @@ Below the `idle` function you'll see a `#[task]` handler (function). This *task*
Note that all tasks will be prioritized over the `idle` function so the execution of `idle` will be interrupted (paused) by the `on_power_event` task. When the `on_power_event` task finishes (returns) the execution of the `idle` will be resumed. This will become more obvious in the next section.
Try this: add an infinite loop to `init` so that it never returns. Now run the program and connect the USB cable. What behavior do you observe?
## Task state
Open the `src/bin/rtic-resources.rs` file.
Now let's say we want to change the previous program to count how many times the USB cable (port J3) has been connected and disconnected.
> TODO
Tasks run from start to finish, like functions, in response to events. To preserve some state between the different executions of a task we can add a *resource* to the task. In RTIC, resources are the mechanism used to share data between different tasks in a memory safe manner but they can also be used to hold task state.
You should always disconnect the device from the host before halting the device. Otherwise, the host will observe an unresponsive USB device and try power cycling the whole USB hub / bus.
To get the desired behavior we'll want to store some counter in the state of the `on_power_event` task.
Open the `src/bin/rtic-resources.rs` file. The starter code shows the syntax to declare a resource, the `Resources` struct, and the syntax to associate a resource to a task, the `resources` list in the `#[task]` attribute.
In the starter code a resource is used to *move* the POWER peripheral from `init` to the `on_power_event` task. The POWER peripheral then becomes part of the state of the `on_power_event` task. The resources of a task are available via the `Context` argument of the task.
We have moved the POWER peripheral into the task because we want to clear the USBDETECTED interrupt flag after it has been set by the hardware. If we miss this step the `on_power_event` task (function) will be called again once it returns and then again and again and again (ad infinitum).
Also note that in the starter code the `idle` function has been modified. Pay attention to the logs when you run the starter code.
Your task in this section will be to modify the program so that it prints the number of times the USB cable has been connected to the DK each time the cable is connected.
## USB basics
Some basics about the USB protocol. The protocol is complex so we'll leave out many details and focus on the concepts required to get enumeration working.
A USB device, the nRF52840 in our case, can be one of these three states: the Default state, the Address state or the Configured state.
A USB device, the nRF52840 in our case, can be one of these three states: the Default state, the Address state or the Configured state.
After being powered the device will start in the Default state. The enumeration process will take the device from the Default state to the Address state. As a result of the enumeration process the device will be assigned an address, in the range `1..=127`, by the host.

View file

@ -1,4 +1,4 @@
#![no_std]
pub const VID: u16 = 0x2020;
pub const PID: u16 = 0x0715;
pub const PID: u16 = 0x0717;

View file

@ -2,37 +2,42 @@
#![no_std]
use cortex_m::asm;
use dk::{peripheral::USBD, usbd};
use dk::peripheral::POWER;
use panic_log as _; // panic handler
#[rtic::app(device = dk)]
const APP: () = {
struct Resources {
usbd: USBD,
power: POWER,
}
#[init]
fn init(_cx: init::Context) -> init::LateResources {
let board = dk::init().unwrap();
// initialize the USB peripheral; will block until the USB cable is physically connected
usbd::init(board.power, &board.usbd);
let power = board.power;
// electrically connects the device to the host
usbd::connect(&board.usbd);
power.intenset.write(|w| w.usbdetected().set_bit());
init::LateResources { usbd: board.usbd }
log::info!("USBDETECTED interrupt enabled");
init::LateResources { power }
}
#[task(binds = USBD, resources = [usbd])]
fn usb(cx: usb::Context) {
let usbd = cx.resources.usbd;
#[idle]
fn idle(_cx: idle::Context) -> ! {
loop {
log::info!("idle: going to sleep");
asm::wfi();
log::info!("idle: woke up");
}
}
log::info!("USB event occurred");
#[task(binds = POWER_CLOCK, resources = [power])]
fn on_power_event(cx: on_power_event::Context) {
log::info!("POWER event occurred");
// electrically disconnects the device to the host
usbd::disconnect(usbd);
asm::bkpt();
// clear the interrupt flag; otherwise this task will run again after it returns
cx.resources.power.events_usbdetected.reset();
}
};

190
advanced/host/print-descs/Cargo.lock generated Normal file
View file

@ -0,0 +1,190 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
[[package]]
name = "anyhow"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
[[package]]
name = "bit-set"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
[[package]]
name = "cc"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "consts"
version = "0.1.0"
[[package]]
name = "crc32fast"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
dependencies = [
"cfg-if",
]
[[package]]
name = "filetime"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi",
]
[[package]]
name = "libc"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
[[package]]
name = "libflate"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9135df43b1f5d0e333385cb6e7897ecd1a43d7d11b91ac003f4d2c2d2401fdd"
dependencies = [
"adler32",
"crc32fast",
"rle-decode-fast",
"take_mut",
]
[[package]]
name = "libusb1-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d9ddd446b6f233a79ef7e6f73de63a58f3a9047d60c46f15cda31452a8f86e"
dependencies = [
"cc",
"libc",
"libflate",
"pkg-config",
"tar",
"vcpkg",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "print-descs"
version = "0.1.0"
dependencies = [
"anyhow",
"consts",
"rusb",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "rle-decode-fast"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
[[package]]
name = "rusb"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d10caa3e5fc7ad1879a679bf16d3304ea10614b8f2f1a1386be4ec942d44062a"
dependencies = [
"bit-set",
"libc",
"libusb1-sys",
]
[[package]]
name = "take_mut"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
[[package]]
name = "tar"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c058ad0bd6ccb84faa24cc44d4fc99bee8a5d7ba9ff33aa4d993122d1aeeac2"
dependencies = [
"filetime",
"libc",
"redox_syscall",
"xattr",
]
[[package]]
name = "vcpkg"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "xattr"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
dependencies = [
"libc",
]

View file

@ -0,0 +1,12 @@
[package]
name = "print-descs"
version = "0.1.0"
authors = ["Jorge Aparicio <jorge.aparicio@ferrous-systems.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rusb = "0.5.5"
anyhow = "1.0.31"
consts = { path = "../../common/consts/" }

View file

@ -0,0 +1,16 @@
use anyhow::anyhow;
fn main() -> Result<(), anyhow::Error> {
for dev in rusb::devices()?.iter() {
let dev_desc = dev.device_descriptor()?;
if dev_desc.vendor_id() == consts::VID && dev_desc.product_id() == consts::PID {
println!("{:#?}", dev_desc);
for i in 0..dev_desc.num_configurations() {
println!("{}: {:#?}", i, dev.config_descriptor(i)?);
}
return Ok(());
}
}
Err(anyhow!("nRF52840 USB device not found"))
}

View file

@ -3,23 +3,16 @@ use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
for dev in rusb::devices()?.iter() {
let desc = dev.device_descriptor()?;
let mut show_config = false;
let suffix = match (desc.vendor_id(), desc.product_id()) {
(0x1366, 0x1015) => " <- J-Link on the nRF52840 Development Kit",
(0x1915, 0x521f) => " <- nRF52840 Dongle (in bootloader mode)",
(0x2020, 0x0309) => " <- nRF52840 Dongle (loopback.hex)",
(consts::VID, consts::PID) => {
show_config = true;
" <- nRF52840 on the nRF52840 Development Kit"
}
(0x2020, 0x0310) => " <- nRF52840 Dongle (puzzle.hex)",
(consts::VID, consts::PID) => " <- nRF52840 on the nRF52840 Development Kit",
_ => "",
};
println!("{:?}{}", dev, suffix);
if show_config {
let desc = dev.config_descriptor(0)?;
println!("> {:?}", desc);
}
}
Ok(())