This commit is contained in:
Amanjeev Sethi 2023-06-28 07:12:07 -04:00 committed by GitHub
commit 1f9b7568ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 65 additions and 42 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ Cargo.lock
.vscode/
*.DS_Store
.idea

View file

@ -1,4 +1,5 @@
#![no_std]
pub const VID: u16 = 0x2020;
pub const PID: u16 = 0x0717;
// using the "working" IDs of nRF board
pub const VID: u16 = 0x1366;
pub const PID: u16 = 0x1015;

View file

@ -6,6 +6,6 @@ name = "print-descs"
version = "0.0.0"
[dependencies]
rusb = "0.5.5"
rusb = "0.8"
anyhow = "1.0.31"
consts = { path = "../../common/consts/" }

View file

@ -26,7 +26,7 @@
- [Starting a Project from Scratch](./from-scratch.md)
- [Advanced Workbook](./advanced-workbook.md)
- [Code Organization](./code-organisation.md)
- [Listing USB Devices](./listing-usb-devices.md)
- [Workshop goal](./workshop-goal.md)
- [Hello, world!](./hello-world.md)
- [Checking the API documentation](./api-documentation.md)
- [RTIC hello](./rtic-hello.md)

View file

@ -9,4 +9,4 @@ $ cargo doc -p dk --open
```
> NOTE: If you are using Safari and the documentation is hard to read due to missing CSS, try opening it in a different browser.
> ❗️ If you are using Safari and the documentation is hard to read due to missing CSS, try opening it in a different browser.

View file

@ -6,4 +6,11 @@ Below the `idle` function you'll see a `#[task]` handler, a 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 the end of `init` so that it never returns. Now run the program and connect the USB cable. What behavior do you observe? How would you explain this behavior? (hint: look at the `rtic-expansion.rs` file: under what conditions is the `init` function executed?)
Try this: add an infinite loop to the end of `init` so that it never returns. Now run the program and connect the USB cable. What behavior do you observe? How would you explain this behavior? (hint: look at the `rtic-expansion.rs` file: under what conditions is the `init` function executed?)
<details>
<summary>Click me to see hint</summary>
You may observe that nothing happens when you plug in the USB cable to J3. The `init` function is called once inside the `main` but `init` in this case has an infinite loop.
</details>

View file

@ -4,7 +4,7 @@ In this section, we'll set up the integration in VS Code and run the first progr
✅ 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.
> ❗️ 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.
@ -12,11 +12,11 @@ Give rust-analyzer some time to analyze the file and its dependency graph. When
If you are not using VS code run the `cargo run --bin hello` command from the `advanced/firmware` folder.
> NOTE if you run into an error along the lines of "Debug power request failed" retry the operation and the error should disappear
> ❗️ If you run into an error along the lines of "Debug power request failed" retry the operation and the error should disappear
The `firmware` workspace has been configured to cross-compile applications to the ARM Cortex-M architecture and then run them using the `probe-run` custom Cargo runner. The `probe-run` tool will load and run the embedded application on the microcontroller and collect logs from the microcontroller.
The `firmware` workspace has been configured to cross-compile applications to the ARM Cortex-M architecture and then run them using the `probe-run` custom Cargo runner. This is set in `.cargo/config.toml`. The `probe-run` tool will load and run the embedded application on the microcontroller and collect logs from the microcontroller.
The `probe-run` process will terminate when the microcontroller enters the "halted" state. From the embedded application, one can enter the "halted" state using the `asm::bkpt` function. For convenience, an `exit` function is provided in the `dk` Hardware Abstraction Layer (HAL). This function is divergent like `std::process::exit` (`fn() -> !`) and can be used to halt the device and terminate the `probe-run` process.
Note that when the `probe-run` tool sees the device enter the halted state it will proceed to *reset-halt* the device. This is particularly important when writing USB applications because simply leaving the device in a halted state will make it appear as an unresponsive USB device to the host. Some OSes (e.g. Linux) will try to make an unresponsive device respond by power cycling the entire USB bus -- this will cause all other USB devices on the bus to be re-enumerated. Reset-halting the device will cause it to be electrically disconnected from the host USB bus and avoid the "power cycle the whole USB bus" scenario.
>🔎 When the `probe-run` tool sees the device enter the halted state it will proceed to *reset-halt* the device. This is particularly important when writing USB applications because simply leaving the device in a halted state will make it appear as an unresponsive USB device to the host. Some OSes (e.g. Linux) will try to make an unresponsive device respond by power cycling the entire USB bus -- this will cause all other USB devices on the bus to be re-enumerated. Reset-halting the device will cause it to be electrically disconnected from the host USB bus and avoid the "power cycle the whole USB bus" scenario.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View file

@ -1,26 +1 @@
# Listing USB Devices
✅ To list all USB devices, run `cargo xtask usb-list` from the `advanced` folder.
``` console
$ cargo xtask usb-list
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 010: ID 1366:1015 <- J-Link on the nRF52840 Development Kit
```
The goal of this workshop is to get the nRF52840 SoC to show in this list. The embedded application will use the vendor ID (VID) and product ID (PID) defined in `advanced/common/consts`; `cargo xtask usb-list` will highlight the USB device that matches that VID PID pair.
``` console
$ # expected output
$ cargo xtask usb-list
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 010: ID 1366:1015 <- J-Link on the nRF52840 Development Kit
Bus 001 Device 059: ID 2020:0717 <- nRF52840 on the nRF52840 Development Kit
```

View file

@ -1,16 +1,24 @@
# USB Enumeration
Check this miro board for an [overview](https://miro.com/app/board/uXjVObcQhcc=/?invite_link_id=467100096053).
![Labeled Diagram of the nRF52840 and Host interaction](img/host-and-device.jpg)
A USB device, like the nRF52840, 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.
[Screenshot taken from miro board](https://miro.com/app/board/uXjVObcQhcc=/?invite_link_id=467100096053)
The USB protocol is complex so we'll leave out many details and focus only on the concepts required to get enumeration and configuration working. There are also several USB specific terms so we recommend checking chapter 2, "Terms and Abbreviations", of the USB specification (linked at the bottom of this document) every now and then.
A USB device, like the nRF52840, 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.
The USB protocol is complex so we'll leave out many details and focus only on the concepts required to get enumeration and configuration working. There are also several USB specific terms so we recommend checking chapter 2, "Terms and Abbreviations", of [the USB specification](https://www.usb.org/document-library/usb-20-specification) every now and then.
Each OS may perform the enumeration process slightly differently but the process will always involve these host actions:
- USB reset. This will put the device in the Default state, regardless of what state it was in.
- GET_DESCRIPTOR request to get the device descriptor.
- SET_ADDRESS request to assign an address to the device.
- USB reset: put the device in the Default state, regardless of what state it was in.
- GET_DESCRIPTOR: request to get the device descriptor.
- SET_ADDRESS: request to assign an address to the device.
These host actions will be perceived as *events* by the nRF52840. During this workshop, we will gradually parse and handle these events and learn more about Embedded Rust along the way.

View file

@ -12,7 +12,7 @@ In this starter code the USBD peripheral is initialized in `init` and a task, na
This code will panic because `USBRESET` is not implemented yet.
✅ Go to `fn on_event`, line 39. In this section you'll need to implement the following USB events `USBRESET` and `EP0SETUP` so that your log output will look like this:
✅ Go to `fn on_event`. In this section you'll need to implement the following USB events `USBRESET` and `EP0SETUP` so that your log output will look like this:
``` console
USBD initialized

View file

@ -0,0 +1,31 @@
# Workshop goal
The goal of this workshop is to get the nRF52840 SoC to show in this list. The embedded application will use the vendor ID (VID) and product ID (PID) defined in `advanced/common/consts`.
`cargo xtask usb-list` will highlight the USB device that matches that VID PID pair.
``` console
$ # expected output
$ cargo xtask usb-list
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 010: ID 1366:1015 <- J-Link on the nRF52840 Development Kit
Bus 001 Device 059: ID 2020:0717 <- nRF52840 on the nRF52840 Development Kit
```
## Listing USB Devices
✅ To list all USB devices, run `cargo xtask usb-list` from the `advanced` folder.
``` console
$ cargo xtask usb-list
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 010: ID 1366:1015 <- J-Link on the nRF52840 Development Kit
```