Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add USB driver #19

Merged
merged 43 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ee46809
wip(usb): add phy and dcd initialization
HaoboGu Jul 6, 2024
4e6a40a
wip(usb): add device and endpoint operations
HaoboGu Jul 7, 2024
fe0dde3
wip(usb): add device transfer
HaoboGu Jul 8, 2024
1bd49c6
feat(usb): add more usb low level driver function
HaoboGu Jul 12, 2024
bd619dd
feat(usb): impl usb driver in embassy
HaoboGu Jul 16, 2024
d9736d4
refactor(usb): reorganize usb mod, make dcd data static mut
HaoboGu Jul 18, 2024
b02e4de
refactor(usb): move qtd initialization to dcd data struct
HaoboGu Jul 18, 2024
464f8ba
feat(usb): finish main part of usb driver
HaoboGu Jul 18, 2024
5eed540
fix(usb): make visibility of usb structs
HaoboGu Jul 18, 2024
6cc3d6d
refactor(usb): add address alignment check, refine comments
HaoboGu Jul 20, 2024
539a87c
feat(usb): add usb pin initialization
HaoboGu Jul 22, 2024
df981ae
feat(usb): add usb-pin-reuse feature for hpm5300
HaoboGu Jul 23, 2024
d867fce
feat(example): add usb example
HaoboGu Jul 24, 2024
d0a59b5
feat(usb): enable usb interrupt
HaoboGu Jul 24, 2024
41685e9
refactor(usb): re-organize usb code
HaoboGu Jul 25, 2024
76bda51
feat(usb): add usb interrupt handler skeleton
HaoboGu Jul 25, 2024
c571411
fix(usb): move dcd init to UsbDriver
HaoboGu Jul 25, 2024
4af0d7a
feat(usb): add interrupt handler
HaoboGu Jul 26, 2024
6913b5e
feat(usb): refactor endpoint allocation and interrupt-waker(but waker…
HaoboGu Jul 27, 2024
90d9bf4
fix(usb): disable usb reset interrupt in interrupt handler
HaoboGu Jul 28, 2024
dcf3ee7
feat(usb): polish reset processing, add more debugging info
HaoboGu Jul 29, 2024
8b97f6f
feat(usb): add generated types for qhdlist
HaoboGu Jul 31, 2024
365c45c
feat(usb): receive setup packet, update generated qhd/qtd types
HaoboGu Jul 31, 2024
935b638
refactor(usb): clean code, add debugging info, fix qtd alignment
HaoboGu Aug 1, 2024
0e2a788
refactor(usb): add many many debugging logs, but no luck
HaoboGu Aug 2, 2024
f2db72a
feat(usb): received set address packet, the returned config desc is s…
HaoboGu Aug 4, 2024
b911aef
refactor(usb): remove unused code
HaoboGu Aug 4, 2024
77b9901
refactor(usb): code formatting, set qhd.ios for ep0
HaoboGu Aug 4, 2024
89499c2
feat(usb): make usb enumerable
HaoboGu Aug 5, 2024
e68ca24
feat(usb): improve ep processing, make usb hid & cdc acm receiving work
HaoboGu Aug 16, 2024
e6e9dcf
feat(usb): update hid demo
HaoboGu Aug 17, 2024
9099c6b
chore: merge latest master
HaoboGu Aug 17, 2024
78be02e
fix(usb): fix ci failure
HaoboGu Aug 17, 2024
6953246
feat(usb): make usb working finally
HaoboGu Aug 17, 2024
f6b95f8
fix(usb): fix packet missing in release mode by waiting for control t…
HaoboGu Aug 17, 2024
aa122b5
refactor(usb): clean logs
HaoboGu Aug 17, 2024
a6c8279
refactor(usb): clean and refactor usb code
HaoboGu Aug 18, 2024
0d32824
chore: clean dependency
HaoboGu Aug 18, 2024
db49f4f
feat(usb): add examples for hpm6e00evk
HaoboGu Aug 18, 2024
ced6b19
doc(usb): add usb to readme
HaoboGu Aug 20, 2024
b672c3b
feat(usb): add example for hpm67
HaoboGu Aug 21, 2024
76be50d
feat(usb): enable HS mode, update usb examples
HaoboGu Aug 22, 2024
7e7d377
fix(usb): check ep status before transfer
HaoboGu Aug 23, 2024
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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ embassy-sync = { version = "0.6.0", optional = true }
embassy-futures = { version = "0.1.1", optional = true }
embassy-hal-internal = { version = "0.2.0", default-features = false }
embassy-time = { version = "0.3.0", optional = true }
embassy-usb-driver = { version = "0.1.0", features = ["defmt"] }
critical-section = "1.1.2"

riscv-rt = { version = "0.12.2", optional = true }
Expand All @@ -42,7 +43,6 @@ embedded-hal-async = "1.0.0"
chrono = { version = "0.4.38", default-features = false, optional = true }
mcan = { version = "0.5.0", optional = true }


[build-dependencies]
# hpm-metapac = { path = "../hpm-data/build/hpm-metapac", default-features = false, features = [
# "metadata",
Expand All @@ -60,7 +60,7 @@ rt = ["dep:riscv-rt", "hpm-metapac/rt"]
defmt = ["dep:defmt"]
time = ["dep:embassy-time"]
chrono = ["dep:chrono"]

usb-pin-reuse-hpm5300 = []
embassy = [
"dep:embassy-sync",
"dep:embassy-futures",
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This crate is a working-in-progress and not ready for use.
| HPM6700 | ✓ | ✓ | ✓ | ✓ | ✓+ | ✓+ | ✓+ | ✓+ | ✓+ | | | | |
| HPM6300 | ✓ | ✓ | ✓ | ✓ | | | | | | | | | |
| HPM6200 | ✓ | | | | | | | | | | | | |
| HPM5300 | ✓ | ✓ | ✓ | ✓ | ✓+ | ✓+ | ✓+ | ✓+ | ✓+ | | ✓ | | ✓ |
| HPM5300 | ✓ | ✓ | ✓ | ✓ | ✓+ | ✓+ | ✓+ | ✓+ | ✓+ | | ✓ | | ✓ |
| HPM6800 | ✓ | | | | | | | | | | | | |
| HPM6E00 | ✓ | ✓ | ✓ | ✓ | ✓+ | ✓+ | ✓+ | ✓+ | ✓+ | | | | |

Expand Down Expand Up @@ -73,6 +73,9 @@ This crate is a working-in-progress and not ready for use.
- [x] basic `mcan` wrapper
- ~~[ ] async driver~~, better impl it in the App layer, see Mi motor demo
- [ ] TSU management
- [x] USB
- [x] Device
- [ ] Host

### Long term Plans

Expand Down
10 changes: 10 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,18 @@ fn main() {
})
}
}

// if regs.kind == "dac"
}

// Usb is special
#[cfg(feature = "usb-pin-reuse-hpm5300")]
if p.name == "USB0" {
g.extend(quote! {
pin_trait_impl!(crate::usb::DmPin, USB0, PA24, 0);
pin_trait_impl!(crate::usb::DpPin, USB0, PA25, 0);
})
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions examples/hpm5300evk/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ runner = [
"probe-rs", "run",
"--chip", "HPM5361",
"--chip-description-path", "../../HPMicro.yaml",
# "--chip-description-path", "../../../flash-algo/target/definition.yaml",
"--protocol","jtag",
"--log-format", "{t} {L} {F}:{l} {s}",
]
Expand Down Expand Up @@ -37,4 +36,4 @@ rustflags = [
build-std = ["core"]

[env]
DEFMT_LOG = "info"
DEFMT_LOG = "trace"
15 changes: 13 additions & 2 deletions examples/hpm5300evk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ edition = "2021"

[dependencies]
# hpm5301 is a subset of hpm5361, either is ok if you have the 5301 board.
hpm-hal = { path = "../..", features = ["rt", "embassy", "hpm5361"] }
hpm-hal = { path = "../..", features = [
"rt",
"embassy",
"hpm5361",
"usb-pin-reuse-hpm5300",
] }

panic-halt = "0.2.0"
riscv-rt = "0.12.2"
Expand All @@ -31,7 +36,13 @@ embedded-hal-bus = "0.2.0"
assign-resources = "0.4.1"
mcan = "0.5.0"
embassy-sync = "0.6.0"

embassy-usb = { version = "0.3.0", features = [
"defmt",
"max-handler-count-8",
"max-interface-count-8",
] }
usbd-hid = "0.8"
static_cell = "2"

[profile.release]
strip = false # symbols are not flashed to the microcontroller, so don't strip them.
Expand Down
115 changes: 115 additions & 0 deletions examples/hpm5300evk/src/bin/usb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#![no_main]
#![no_std]
#![feature(type_alias_impl_trait)]
#![feature(abi_riscv_interrupt)]
#![feature(impl_trait_in_assoc_type)]

use defmt::info;
use embassy_executor::Spawner;
use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State};
use embassy_usb::driver::EndpointError;
use embassy_usb::Builder;
use futures_util::future::join;
use hal::usb::{Instance, UsbDriver};
use hpm_hal::{bind_interrupts, peripherals};
use {defmt_rtt as _, hpm_hal as hal, riscv_rt as _};

bind_interrupts!(struct Irqs {
USB0 => hal::usb::InterruptHandler<peripherals::USB0>;
});

#[embassy_executor::main(entry = "hpm_hal::entry")]
async fn main(_spawner: Spawner) -> ! {
let p = hal::init(Default::default());

let usb_driver = hal::usb::UsbDriver::new(p.USB0, p.PA24, p.PA25);

// Create embassy-usb Config
let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
config.manufacturer = Some("hpm-hal");
config.product = Some("USB-serial example");
config.serial_number = Some("12345678");

// Required for windows compatibility.
// https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
config.device_class = 0xEF;
config.device_sub_class = 0x02;
config.device_protocol = 0x01;
config.composite_with_iads = true;

// Create embassy-usb DeviceBuilder using the driver and config.
// It needs some buffers for building the descriptors.
let mut config_descriptor = [0; 256];
let mut bos_descriptor = [0; 256];
let mut control_buf = [0; 64];

let mut state = State::new();

let mut builder = Builder::new(
usb_driver,
config,
&mut config_descriptor,
&mut bos_descriptor,
&mut [], // no msos descriptors
&mut control_buf,
);

// Create classes on the builder.
let class = CdcAcmClass::new(&mut builder, &mut state, 64);

// Build the builder.
let mut usb = builder.build();

// Run the USB device.
let usb_fut = usb.run();

// Do stuff with the class!
let echo_fut = async {
// class.wait_connection().await;
let (mut sender, mut reader) = class.split();
sender.wait_connection().await;
reader.wait_connection().await;
info!("Connected");
let _ = echo(&mut reader, &mut sender).await;
info!("Disconnected");
};

// Run everything concurrently.
join(usb_fut, echo_fut).await;

loop {
embassy_time::Timer::after_millis(500).await;
}
}

struct Disconnected {}

impl From<EndpointError> for Disconnected {
fn from(val: EndpointError) -> Self {
match val {
EndpointError::BufferOverflow => panic!("Buffer overflow"),
EndpointError::Disabled => Disconnected {},
}
}
}

async fn echo<'d, T: Instance + 'd>(
reader: &mut Receiver<'d, UsbDriver<'d, T>>,
sender: &mut Sender<'d, UsbDriver<'d, T>>,
) -> Result<(), Disconnected> {
let mut buf = [0; 64];
loop {
let n = reader.read_packet(&mut buf).await?;
let data = &buf[..n];
info!("echo data: {:x}, len: {}", data, n);
sender.write_packet(data).await?;
// Clear bufffer
buf = [0; 64];
}
}

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
defmt::info!("panic: {:?}", defmt::Debug2Format(&info));
loop {}
}
Loading
Loading