Skip to content

Commit

Permalink
Merge pull request #5 from dstric-aqueduct/master
Browse files Browse the repository at this point in the history
add USB serial example
  • Loading branch information
gdobato authored Dec 12, 2023
2 parents b3a2937 + bc1ca88 commit 19c06d2
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ oe = "objcopy --example"
blinky = "be blinky"
blinky-probe = "ee blinky"
blinky-bin = "oe blinky --release -- -O binary target/thumbv7em-none-eabihf/release/examples/blinky.bin"

serial = "be serial"
serial-probe = "ee serial"
serial-bin = "oe serial --release -- -O binary target/thumbv7em-none-eabihf/release/examples/serial.bin"

usb-serial = "be usb_serial --features=usb"
usb-serial-probe = "ee usb_serial --features=usb"
usb-serial-bin = "oe usb_serial --release --features=usb -- -O binary target/thumbv7em-none-eabihf/release/examples/usb_serial.bin"

[build]
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: ci

on: [push, pull_request]
on: [push, pull_request, workflow_dispatch]

env:
CARGO_TERM_COLOR: always
Expand All @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain : nightly-2023-06-28
toolchain : nightly
components: rustfmt
- uses: actions-rs/cargo@v1
with:
Expand All @@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2023-06-28
toolchain: nightly
target: thumbv7em-none-eabihf
override: true
- name: Prologue
Expand Down
29 changes: 21 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@ name = "portenta-h7-async"
version = "0.1.0"
edition = "2021"

[[example]]
name = "usb_serial"
required-features = ["usb"]

[features]
usb = []

[dependencies]
cortex-m = { version = "0.7.6", features = [
"inline-asm",
"critical-section-single-core",
] }
cortex-m-rt = "0.7"

embassy-stm32 = { version = "0.1.0", git = "https://github.com/embassy-rs/embassy.git", features = [
"nightly",
"unstable-traits",
embassy-stm32 = { rev = "b4bc9ac028568dfb3896dfb00cbd1e181863fd64", git = "https://github.com/embassy-rs/embassy.git", features = [
"defmt",
"stm32h747xi-cm7",
"unstable-pac",
Expand All @@ -21,31 +26,39 @@ embassy-stm32 = { version = "0.1.0", git = "https://github.com/embassy-rs/embass
"exti",
"embedded-sdmmc",
"chrono",
"nightly",
"unstable-traits",
] }
embassy-sync = { version = "0.4.0", git = "https://github.com/embassy-rs/embassy.git", features = [

embassy-sync = { rev = "b4bc9ac028568dfb3896dfb00cbd1e181863fd64", git = "https://github.com/embassy-rs/embassy.git", features = [
"defmt",
] }
embassy-executor = { version = "0.3.1", git = "https://github.com/embassy-rs/embassy.git", features = [

embassy-executor = { rev = "b4bc9ac028568dfb3896dfb00cbd1e181863fd64", git = "https://github.com/embassy-rs/embassy.git", features = [
"nightly",
"arch-cortex-m",
"executor-thread",
"executor-interrupt",
"defmt",
"integrated-timers",
] }
embassy-time = { version = "0.1.2", git = "https://github.com/embassy-rs/embassy.git", features = [

embassy-time = { rev = "b4bc9ac028568dfb3896dfb00cbd1e181863fd64", git = "https://github.com/embassy-rs/embassy.git", features = [
"defmt",
"defmt-timestamp-uptime",
"unstable-traits",
"tick-hz-32_768",
"unstable-traits",
] }
embassy-usb = { version = "0.1.0", git = "https://github.com/embassy-rs/embassy.git", features = [

embassy-usb = { rev = "b4bc9ac028568dfb3896dfb00cbd1e181863fd64", git = "https://github.com/embassy-rs/embassy.git", features = [
"defmt",
] }

defmt = "=0.3.2"
defmt-rtt = "0.4.0"
embedded-hal = "0.2.6"
embedded-io = "0.6.1"
embedded-io-async = { version = "0.6.0" }
panic-probe = { version = "0.3", features = ["print-defmt"] }
futures = { version = "0.3.17", default-features = false, features = [
"async-await",
Expand Down
119 changes: 119 additions & 0 deletions examples/usb_serial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use defmt::info;
use defmt_rtt as _;
use embassy_executor::{main, task, Spawner};
use embassy_time::Timer;
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
use embassy_usb::driver::EndpointError;
use embassy_usb::Builder;
use futures::future::join;
use panic_probe as _;
use portenta_h7_async::led;

use embassy_stm32::usb_otg::{Driver, Instance};

#[main]
async fn main(spawner: Spawner) {
info!("Init");

let portenta_h7_async::Board {
led_blue,
mut led_red,
usb,
..
} = portenta_h7_async::Board::take();

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

// 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 device_descriptor = [0; 256];
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,
config,
&mut device_descriptor,
&mut config_descriptor,
&mut bos_descriptor,
&mut [], // no msos descriptors
&mut control_buf,
);

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

// 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 {
loop {
class.wait_connection().await;
info!("Connected");
let _ = echo(&mut class, &mut led_red).await;
info!("Disconnected");
}
};

spawner.spawn(blink_led_blue(led_blue)).unwrap();

// Run everything concurrently.
// If we had made everything `'static` above instead, we could do this using separate tasks instead.
join(usb_fut, echo_fut).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>(
class: &mut CdcAcmClass<'d, Driver<'d, T>>,
led_red: &mut led::user::Red,
) -> Result<(), Disconnected> {
let mut buf = [0; 512];
loop {
let n = class.read_packet(&mut buf).await?;
let data = &buf[..n];
info!("data: {:x}", data);
led_red.toggle();
class.write_packet(data).await?;
}
}

#[task]
async fn blink_led_blue(mut led: led::user::Blue) {
loop {
led.toggle();
Timer::after_millis(1_000).await;
}
}
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Before upgrading check that everything is available on all tier1 targets here:
# https://rust-lang.github.io/rustup-components-history
[toolchain]
channel = "nightly-2023-06-28"
channel = "nightly-2023-12-05"
components = ["rust-src", "rustfmt", "llvm-tools-preview"]
targets = [
"thumbv7em-none-eabihf",
Expand Down
62 changes: 60 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![no_std]
#![feature(type_alias_impl_trait)]

pub mod led;
mod sys;
Expand All @@ -12,21 +13,37 @@ use embassy_stm32::{
Config,
};

#[cfg(feature = "usb")]
use embassy_stm32::usb_otg::{self, Driver};

#[cfg(not(feature = "usb"))]
bind_interrupts!(struct Irqs {
USART1 => usart::InterruptHandler<peripherals::USART1>;
UART4 => usart::InterruptHandler<peripherals::UART4>;
});

#[cfg(feature = "usb")]
bind_interrupts!(struct Irqs {
USART1 => usart::InterruptHandler<peripherals::USART1>;
UART4 => usart::InterruptHandler<peripherals::UART4>;
OTG_HS => usb_otg::InterruptHandler<peripherals::USB_OTG_HS>;
});

// Naming according to breakout board
pub type Uart0 = Uart<'static, peripherals::UART4, peripherals::DMA1_CH0, peripherals::DMA1_CH1>;
pub type Uart1 = Uart<'static, peripherals::USART1, peripherals::DMA1_CH2, peripherals::DMA1_CH3>;
#[cfg(feature = "usb")]
pub type Usb = Driver<'static, peripherals::USB_OTG_HS>;

pub struct Board {
pub led_red: Output<'static, peripherals::PK5>,
pub led_green: Output<'static, peripherals::PK6>,
pub led_blue: Output<'static, peripherals::PK7>,
#[cfg(not(feature = "usb"))]
pub uart0: Uart0,
pub uart1: Uart1,
#[cfg(feature = "usb")]
pub usb: Usb,
}

impl Board {
Expand All @@ -39,15 +56,23 @@ impl Board {
pub fn setup() -> Self {
sys::Clk::new().reset().enable_ext_clock();
// TODO Configure 480 MHz (sys) and 240 MHz (per)
let config = Config::default();
let mut config = Config::default();

{
use embassy_stm32::rcc::*;
config.rcc.hsi48 = Some(Hsi48Config {
sync_from_usb: true,
});
}

let p = embassy_stm32::init(config);

// User leds
let led_red = Output::new(p.PK5, Level::High, Speed::Low);
let led_green = Output::new(p.PK6, Level::High, Speed::Low);
let led_blue = Output::new(p.PK7, Level::High, Speed::Low);

// Uart0 of breakout board
#[cfg(not(feature = "usb"))]
let uart0 = Uart::new_with_rtscts(
p.UART4,
p.PI9,
Expand Down Expand Up @@ -75,12 +100,45 @@ impl Board {
)
.unwrap();

#[cfg(feature = "usb")]
let usb;

#[cfg(feature = "usb")]
{
use static_cell::make_static;

// Create the USB driver, from the HAL.
let mut config = embassy_stm32::usb_otg::Config::default();
config.vbus_detection = true;
usb = Driver::new_hs_ulpi(
p.USB_OTG_HS,
Irqs,
p.PA5,
p.PI11,
p.PH4,
p.PC0,
p.PA3,
p.PB0,
p.PB1,
p.PB10,
p.PB11,
p.PB12,
p.PB13,
p.PB5,
&mut make_static!([0; 1024])[..],
config,
);
}

Self {
led_red,
led_green,
led_blue,
#[cfg(not(feature = "usb"))]
uart0,
uart1,
#[cfg(feature = "usb")]
usb,
}
}
}

0 comments on commit 19c06d2

Please sign in to comment.