Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CI

on: [push, pull_request]

jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup toolchain install stable --no-self-update --profile minimal
- run: cargo fmt --verbose --check

clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: rustup toolchain install stable --no-self-update --profile minimal --component clippy
# Small chip => fast to build => fast answers
- run: cargo clippy --tests --features=imxrt-ral/imxrt1011 -- -D warnings

tests:
runs-on: ubuntu-latest
strategy:
matrix:
# Should be enough coverage, but feel free to add more.
chip: [imxrt1011, imxrt1062, imxrt1176_cm7]
steps:
- uses: actions/checkout@v4
- run: rustup toolchain install stable --no-self-update --profile minimal
- run: cargo test --features=imxrt-ral/${{ matrix.chip }}

target:
runs-on: ubuntu-latest
strategy:
matrix:
chip: [imxrt1011, imxrt1062, imxrt1176_cm7]
steps:
- uses: actions/checkout@v4
- run: rustup toolchain install stable --no-self-update --profile minimal --target thumbv7em-none-eabihf
- run: cargo build --target=thumbv7em-none-eabihf --features=imxrt-ral/${{ matrix.chip }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/target
Cargo.lock
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ version = "0.1.0"
edition = "2024"

[dependencies]
cotton-usb-host = { version = "0.2.1", default-features = false }
defmt = "1.0"
futures-core = { version = "0.3.31", default-features = false }
imxrt-ral = "0.6"
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,45 @@ a Teensy 4.1, on the USB2 port.

[`cotton-usb-host`]: https://github.com/pdh11/cotton/tree/main/cotton-usb-host

Development
-----------

This repository contains the driver. The driver can build when targeting your
development system or an i.MX RT microcontroller.

When you make a change, you can check that it builds like this:

```
cargo build --features=imxrt-ral/imxrt1062
```

That built the library for your development system, not the MCU! This means you
can run unit and documentation tests on your development system.

```
cargo test --features=imxrt-ral/imxrt1062
```

To generate code for the MCU, append a target specifier. Hopefully, the code is
portable, so this shouldn't always be necessary.

```
cargo build --features=imxrt-ral/imxrt1062 --target=thumbv7em-none-eabihf
```

Hardware testing
----------------

This repository does not contain hardware examples. Those are in the [imxrt-hal]
repository. See the imxrt-hal documentation to learn how to run examples on your
board.

[imxrt-hal]: https://github.com/imxrt-rs/imxrt-hal

To test your changes, clone the imxrt-hal repository. In `imxrt-hal/Cargo.toml`,
find the `[patch.crates-io.imxrt-usbh]` directive, and point the patch to your
copy of this driver. Now, the changes you make _here_, in this driver, will be
incorporated into the hardware example you're running from imxrt-hal.

License
-------
Expand Down
127 changes: 120 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,127 @@
pub fn add(left: u64, right: u64) -> u64 {
left + right
#![cfg_attr(target_os = "none", no_std)]

pub use cotton_usb_host::{async_pool, bitset, host_controller, topology, usb_bus, wire};
use imxrt_ral as ral;

#[expect(dead_code)]
pub struct HostController<const N: u8> {
// Not sure if we need more or fewer instances!
// We'll figure that out later.
usb: ral::usb::Instance<N>,
phy: ral::usbphy::Instance<N>,
nc: ral::usbnc::Instance<N>,
}

impl<const N: u8> HostController<N> {
pub fn new(
usb: ral::usb::Instance<N>,
phy: ral::usbphy::Instance<N>,
nc: ral::usbnc::Instance<N>,
) -> Self {
Self { usb, phy, nc }
}
}

pub struct InterruptPipe {}
pub struct DeviceDetect {}

impl futures_core::Stream for InterruptPipe {
type Item = host_controller::InterruptPacket;

fn poll_next(
self: core::pin::Pin<&mut Self>,
_: &mut core::task::Context<'_>,
) -> core::task::Poll<Option<Self::Item>> {
defmt::todo!()
}
}

impl futures_core::Stream for DeviceDetect {
type Item = host_controller::DeviceStatus;

fn poll_next(
self: core::pin::Pin<&mut Self>,
_: &mut core::task::Context<'_>,
) -> core::task::Poll<Option<Self::Item>> {
defmt::todo!()
}
}

#[expect(unused_variables, reason = "Autofill filled it in")]
impl<const N: u8> host_controller::HostController for HostController<N> {
type InterruptPipe = InterruptPipe;
type DeviceDetect = DeviceDetect;

fn device_detect(&self) -> Self::DeviceDetect {
defmt::todo!()
}

fn reset_root_port(&self, rst: bool) {
defmt::todo!()
}

async fn control_transfer(
&self,
address: u8,
transfer_extras: usb_bus::TransferExtras,
packet_size: u8,
setup: wire::SetupPacket,
data_phase: usb_bus::DataPhase<'_>,
) -> Result<usize, usb_bus::UsbError> {
defmt::todo!()
}

async fn bulk_in_transfer(
&self,
address: u8,
endpoint: u8,
packet_size: u16,
data: &mut [u8],
transfer_type: usb_bus::TransferType,
data_toggle: &core::cell::Cell<bool>,
) -> Result<usize, usb_bus::UsbError> {
defmt::todo!()
}

async fn bulk_out_transfer(
&self,
address: u8,
endpoint: u8,
packet_size: u16,
data: &[u8],
transfer_type: usb_bus::TransferType,
data_toggle: &core::cell::Cell<bool>,
) -> Result<usize, usb_bus::UsbError> {
defmt::todo!()
}

async fn alloc_interrupt_pipe(
&self,
address: u8,
transfer_extras: usb_bus::TransferExtras,
endpoint: u8,
max_packet_size: u16,
interval_ms: u8,
) -> Self::InterruptPipe {
defmt::todo!()
}

fn try_alloc_interrupt_pipe(
&self,
address: u8,
transfer_extras: usb_bus::TransferExtras,
endpoint: u8,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::InterruptPipe, usb_bus::UsbError> {
defmt::todo!()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
fn you_can_test_the_units() {
assert_eq!(1 + 1, 2);
}
}