Merge branch 'master' into usb_msc
This commit is contained in:
@ -1,11 +1,12 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "embassy-nrf-examples"
|
||||
name = "embassy-nrf52840-examples"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[features]
|
||||
default = ["nightly"]
|
||||
msos-descriptor = ["embassy-usb/msos-descriptor"]
|
||||
nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net",
|
||||
"embassy-lora", "lorawan-device", "lorawan"]
|
||||
|
||||
@ -14,7 +15,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
|
||||
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
|
||||
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
|
||||
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
|
||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true }
|
||||
embedded-io = "0.4.0"
|
||||
@ -34,4 +35,8 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
|
||||
rand = { version = "0.8.4", default-features = false }
|
||||
embedded-storage = "0.3.0"
|
||||
usbd-hid = "0.6.0"
|
||||
serde = { version = "1.0.136", default-features = false }
|
||||
serde = { version = "1.0.136", default-features = false }
|
||||
|
||||
[[bin]]
|
||||
name = "usb_serial_winusb"
|
||||
required-features = ["msos-descriptor"]
|
||||
|
@ -24,9 +24,9 @@ async fn main(_spawner: Spawner) {
|
||||
let sample_rate = master_clock.sample_rate();
|
||||
info!("Sample rate: {}", sample_rate);
|
||||
|
||||
let config = Config::default()
|
||||
.sample_width(SampleWidth::_16bit)
|
||||
.channels(Channels::MonoLeft);
|
||||
let mut config = Config::default();
|
||||
config.sample_width = SampleWidth::_16bit;
|
||||
config.channels = Channels::MonoLeft;
|
||||
|
||||
let irq = interrupt::take!(I2S);
|
||||
let buffers_out = MultiBuffering::<Sample, NUM_BUFFERS, NUM_SAMPLES>::new();
|
||||
|
@ -22,9 +22,9 @@ async fn main(_spawner: Spawner) {
|
||||
let sample_rate = master_clock.sample_rate();
|
||||
info!("Sample rate: {}", sample_rate);
|
||||
|
||||
let config = Config::default()
|
||||
.sample_width(SampleWidth::_16bit)
|
||||
.channels(Channels::MonoLeft);
|
||||
let mut config = Config::default();
|
||||
config.sample_width = SampleWidth::_16bit;
|
||||
config.channels = Channels::MonoLeft;
|
||||
|
||||
let irq = interrupt::take!(I2S);
|
||||
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
||||
|
@ -23,9 +23,9 @@ async fn main(_spawner: Spawner) {
|
||||
let sample_rate = master_clock.sample_rate();
|
||||
info!("Sample rate: {}", sample_rate);
|
||||
|
||||
let config = Config::default()
|
||||
.sample_width(SampleWidth::_16bit)
|
||||
.channels(Channels::MonoLeft);
|
||||
let mut config = Config::default();
|
||||
config.sample_width = SampleWidth::_16bit;
|
||||
config.channels = Channels::MonoLeft;
|
||||
|
||||
let irq = interrupt::take!(I2S);
|
||||
let buffers = DoubleBuffering::<Sample, NUM_SAMPLES>::new();
|
||||
|
@ -5,7 +5,7 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_nrf::interrupt;
|
||||
use embassy_nrf::saadc::{ChannelConfig, Config, Saadc, SamplerState};
|
||||
use embassy_nrf::saadc::{CallbackResult, ChannelConfig, Config, Saadc};
|
||||
use embassy_nrf::timer::Frequency;
|
||||
use embassy_time::Duration;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -61,7 +61,7 @@ async fn main(_p: Spawner) {
|
||||
c = 0;
|
||||
a = 0;
|
||||
}
|
||||
SamplerState::Sampled
|
||||
CallbackResult::Continue
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
@ -9,7 +9,7 @@ use embassy_executor::Spawner;
|
||||
use embassy_net::tcp::TcpSocket;
|
||||
use embassy_net::{Stack, StackResources};
|
||||
use embassy_nrf::rng::Rng;
|
||||
use embassy_nrf::usb::{Driver, PowerUsb};
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac, peripherals};
|
||||
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
||||
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
||||
@ -18,7 +18,7 @@ use embedded_io::asynch::Write;
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
|
||||
type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
|
||||
|
||||
macro_rules! singleton {
|
||||
($val:expr) => {{
|
||||
@ -46,8 +46,31 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! {
|
||||
stack.run().await
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn test_function() -> (usize, u32, [u32; 2]) {
|
||||
let mut array = [3; 2];
|
||||
|
||||
let mut index = 0;
|
||||
let mut result = 0;
|
||||
|
||||
for x in [1, 2] {
|
||||
if x == 1 {
|
||||
array[1] = 99;
|
||||
} else {
|
||||
index = if x == 2 { 1 } else { 0 };
|
||||
|
||||
// grabs value from array[0], not array[1]
|
||||
result = array[index];
|
||||
}
|
||||
}
|
||||
|
||||
(index, result, array)
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(spawner: Spawner) {
|
||||
info!("{:?}", test_function());
|
||||
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
let clock: pac::CLOCK = unsafe { mem::transmute(()) };
|
||||
|
||||
@ -58,7 +81,7 @@ async fn main(spawner: Spawner) {
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -82,7 +105,6 @@ async fn main(spawner: Spawner) {
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
None,
|
||||
);
|
||||
|
||||
// Our MAC addr.
|
||||
|
@ -10,13 +10,13 @@ use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_futures::select::{select, Either};
|
||||
use embassy_nrf::gpio::{Input, Pin, Pull};
|
||||
use embassy_nrf::usb::{Driver, PowerUsb};
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::signal::Signal;
|
||||
use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
|
||||
use embassy_usb::control::OutResponse;
|
||||
use embassy_usb::{Builder, Config, DeviceStateHandler};
|
||||
use embassy_usb::{Builder, Config, Handler};
|
||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) {
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -52,7 +52,7 @@ async fn main(_spawner: Spawner) {
|
||||
let mut bos_descriptor = [0; 256];
|
||||
let mut control_buf = [0; 64];
|
||||
let request_handler = MyRequestHandler {};
|
||||
let device_state_handler = MyDeviceStateHandler::new();
|
||||
let mut device_handler = MyDeviceHandler::new();
|
||||
|
||||
let mut state = State::new();
|
||||
|
||||
@ -63,9 +63,10 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
Some(&device_state_handler),
|
||||
);
|
||||
|
||||
builder.handler(&mut device_handler);
|
||||
|
||||
// Create classes on the builder.
|
||||
let config = embassy_usb::class::hid::Config {
|
||||
report_descriptor: KeyboardReport::desc(),
|
||||
@ -164,20 +165,20 @@ impl RequestHandler for MyRequestHandler {
|
||||
}
|
||||
}
|
||||
|
||||
struct MyDeviceStateHandler {
|
||||
struct MyDeviceHandler {
|
||||
configured: AtomicBool,
|
||||
}
|
||||
|
||||
impl MyDeviceStateHandler {
|
||||
impl MyDeviceHandler {
|
||||
fn new() -> Self {
|
||||
MyDeviceStateHandler {
|
||||
MyDeviceHandler {
|
||||
configured: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeviceStateHandler for MyDeviceStateHandler {
|
||||
fn enabled(&self, enabled: bool) {
|
||||
impl Handler for MyDeviceHandler {
|
||||
fn enabled(&mut self, enabled: bool) {
|
||||
self.configured.store(false, Ordering::Relaxed);
|
||||
SUSPENDED.store(false, Ordering::Release);
|
||||
if enabled {
|
||||
@ -187,17 +188,17 @@ impl DeviceStateHandler for MyDeviceStateHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&self) {
|
||||
fn reset(&mut self) {
|
||||
self.configured.store(false, Ordering::Relaxed);
|
||||
info!("Bus reset, the Vbus current limit is 100mA");
|
||||
}
|
||||
|
||||
fn addressed(&self, addr: u8) {
|
||||
fn addressed(&mut self, addr: u8) {
|
||||
self.configured.store(false, Ordering::Relaxed);
|
||||
info!("USB address set to: {}", addr);
|
||||
}
|
||||
|
||||
fn configured(&self, configured: bool) {
|
||||
fn configured(&mut self, configured: bool) {
|
||||
self.configured.store(configured, Ordering::Relaxed);
|
||||
if configured {
|
||||
info!("Device configured, it may now draw up to the configured current limit from Vbus.")
|
||||
@ -206,7 +207,7 @@ impl DeviceStateHandler for MyDeviceStateHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn suspended(&self, suspended: bool) {
|
||||
fn suspended(&mut self, suspended: bool) {
|
||||
if suspended {
|
||||
info!("Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled).");
|
||||
SUSPENDED.store(true, Ordering::Release);
|
||||
|
@ -7,7 +7,7 @@ use core::mem;
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_nrf::usb::{Driver, PowerUsb};
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State};
|
||||
@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) {
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -55,7 +55,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -7,7 +7,7 @@ use core::mem;
|
||||
use defmt::{info, panic};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply};
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
use embassy_usb::driver::EndpointError;
|
||||
@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) {
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -59,7 +59,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
@ -97,7 +96,7 @@ impl From<EndpointError> for Disconnected {
|
||||
}
|
||||
}
|
||||
|
||||
async fn echo<'d, T: Instance + 'd, P: UsbSupply + 'd>(
|
||||
async fn echo<'d, T: Instance + 'd, P: VbusDetect + 'd>(
|
||||
class: &mut CdcAcmClass<'d, Driver<'d, T, P>>,
|
||||
) -> Result<(), Disconnected> {
|
||||
let mut buf = [0; 64];
|
||||
|
@ -6,7 +6,7 @@ use core::mem;
|
||||
|
||||
use defmt::{info, panic, unwrap};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_nrf::usb::{Driver, PowerUsb};
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||
use embassy_nrf::{interrupt, pac, peripherals};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
use embassy_usb::driver::EndpointError;
|
||||
@ -14,7 +14,7 @@ use embassy_usb::{Builder, Config, UsbDevice};
|
||||
use static_cell::StaticCell;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
|
||||
type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn usb_task(mut device: UsbDevice<'static, MyDriver>) {
|
||||
@ -42,7 +42,7 @@ async fn main(spawner: Spawner) {
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, PowerUsb::new(power_irq));
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
@ -83,7 +83,6 @@ async fn main(spawner: Spawner) {
|
||||
&mut res.config_descriptor,
|
||||
&mut res.bos_descriptor,
|
||||
&mut res.control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
130
examples/nrf52840/src/bin/usb_serial_winusb.rs
Normal file
130
examples/nrf52840/src/bin/usb_serial_winusb.rs
Normal file
@ -0,0 +1,130 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::mem;
|
||||
|
||||
use defmt::{info, panic};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect, Instance, VbusDetect};
|
||||
use embassy_nrf::{interrupt, pac};
|
||||
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
|
||||
use embassy_usb::driver::EndpointError;
|
||||
use embassy_usb::msos::{self, windows_version};
|
||||
use embassy_usb::types::InterfaceNumber;
|
||||
use embassy_usb::{Builder, Config};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
// This is a randomly generated GUID to allow clients on Windows to find our device
|
||||
const DEVICE_INTERFACE_GUIDS: &[&str] = &["{EAA9A5DC-30BA-44BC-9232-606CDC875321}"];
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_nrf::init(Default::default());
|
||||
let clock: pac::CLOCK = unsafe { mem::transmute(()) };
|
||||
|
||||
info!("Enabling ext hfosc...");
|
||||
clock.tasks_hfclkstart.write(|w| unsafe { w.bits(1) });
|
||||
while clock.events_hfclkstarted.read().bits() != 1 {}
|
||||
|
||||
// Create the driver, from the HAL.
|
||||
let irq = interrupt::take!(USBD);
|
||||
let power_irq = interrupt::take!(POWER_CLOCK);
|
||||
let driver = Driver::new(p.USBD, irq, HardwareVbusDetect::new(power_irq));
|
||||
|
||||
// Create embassy-usb Config
|
||||
let mut config = Config::new(0xc0de, 0xcafe);
|
||||
config.manufacturer = Some("Embassy");
|
||||
config.product = Some("USB-serial example");
|
||||
config.serial_number = Some("12345678");
|
||||
config.max_power = 100;
|
||||
config.max_packet_size_0 = 64;
|
||||
|
||||
// Required for windows compatiblity.
|
||||
// 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 msos_descriptor = [0; 256];
|
||||
let mut control_buf = [0; 64];
|
||||
|
||||
let mut state = State::new();
|
||||
|
||||
let mut builder = Builder::new(
|
||||
driver,
|
||||
config,
|
||||
&mut device_descriptor,
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut msos_descriptor,
|
||||
&mut control_buf,
|
||||
);
|
||||
|
||||
builder.msos_descriptor(windows_version::WIN8_1, 2);
|
||||
|
||||
// Create classes on the builder.
|
||||
let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
|
||||
|
||||
// Since we want to create MS OS feature descriptors that apply to a function that has already been added to the
|
||||
// builder, need to get the MsOsDescriptorWriter from the builder and manually add those descriptors.
|
||||
// Inside a class constructor, you would just need to call `FunctionBuilder::msos_feature` instead.
|
||||
let msos_writer = builder.msos_writer();
|
||||
msos_writer.configuration(0);
|
||||
msos_writer.function(InterfaceNumber(0));
|
||||
msos_writer.function_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
|
||||
msos_writer.function_feature(msos::RegistryPropertyFeatureDescriptor::new(
|
||||
"DeviceInterfaceGUIDs",
|
||||
msos::PropertyData::RegMultiSz(DEVICE_INTERFACE_GUIDS),
|
||||
));
|
||||
|
||||
// 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).await;
|
||||
info!("Disconnected");
|
||||
}
|
||||
};
|
||||
|
||||
// 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, P: VbusDetect + 'd>(
|
||||
class: &mut CdcAcmClass<'d, Driver<'d, T, P>>,
|
||||
) -> Result<(), Disconnected> {
|
||||
let mut buf = [0; 64];
|
||||
loop {
|
||||
let n = class.read_packet(&mut buf).await?;
|
||||
let data = &buf[..n];
|
||||
info!("data: {:x}", data);
|
||||
class.write_packet(data).await?;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "embassy-nrf-examples"
|
||||
name = "embassy-nrf5340-examples"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
|
@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) {
|
||||
config.baudrate = uarte::Baudrate::BAUD115200;
|
||||
|
||||
let irq = interrupt::take!(SERIAL0);
|
||||
let mut uart = uarte::Uarte::new(p.UARTETWISPI0, irq, p.P1_00, p.P1_01, config);
|
||||
let mut uart = uarte::Uarte::new(p.SERIAL0, irq, p.P1_00, p.P1_01, config);
|
||||
|
||||
info!("uarte initialized!");
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::gpio::{AnyPin, Pin};
|
||||
use embassy_rp::pio::{Pio0, PioPeripherial, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2};
|
||||
use embassy_rp::pio::{Pio0, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2};
|
||||
use embassy_rp::pio_instr_util;
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
@ -4,7 +4,7 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_rp::pio::{PioPeripherial, PioStateMachine, ShiftDirection};
|
||||
use embassy_rp::pio::{PioPeripheral, PioStateMachine, ShiftDirection};
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use embassy_rp::{pio_instr_util, Peripheral};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
@ -73,7 +73,6 @@ async fn main(spawner: Spawner) {
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
None,
|
||||
);
|
||||
|
||||
// Our MAC addr.
|
||||
|
@ -53,7 +53,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
|
||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
|
||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] }
|
||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] }
|
||||
embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dhcpv4"] }
|
||||
embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] }
|
||||
embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" }
|
||||
embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] }
|
||||
critical-section = { version = "1.1", features = ["std"] }
|
||||
|
@ -65,7 +65,7 @@ async fn main_task(spawner: Spawner) {
|
||||
let seed = u64::from_le_bytes(seed);
|
||||
|
||||
// Init network stack
|
||||
let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed));
|
||||
let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed));
|
||||
|
||||
// Launch network task
|
||||
spawner.spawn(net_task(stack)).unwrap();
|
||||
|
98
examples/std/src/bin/net_dns.rs
Normal file
98
examples/std/src/bin/net_dns.rs
Normal file
@ -0,0 +1,98 @@
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use std::default::Default;
|
||||
|
||||
use clap::Parser;
|
||||
use embassy_executor::{Executor, Spawner};
|
||||
use embassy_net::dns::DnsQueryType;
|
||||
use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources};
|
||||
use heapless::Vec;
|
||||
use log::*;
|
||||
use rand_core::{OsRng, RngCore};
|
||||
use static_cell::StaticCell;
|
||||
|
||||
#[path = "../tuntap.rs"]
|
||||
mod tuntap;
|
||||
|
||||
use crate::tuntap::TunTapDevice;
|
||||
|
||||
macro_rules! singleton {
|
||||
($val:expr) => {{
|
||||
type T = impl Sized;
|
||||
static STATIC_CELL: StaticCell<T> = StaticCell::new();
|
||||
STATIC_CELL.init_with(move || $val)
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(version = "1.0")]
|
||||
struct Opts {
|
||||
/// TAP device name
|
||||
#[clap(long, default_value = "tap0")]
|
||||
tap: String,
|
||||
/// use a static IP instead of DHCP
|
||||
#[clap(long)]
|
||||
static_ip: bool,
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn net_task(stack: &'static Stack<TunTapDevice>) -> ! {
|
||||
stack.run().await
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn main_task(spawner: Spawner) {
|
||||
let opts: Opts = Opts::parse();
|
||||
|
||||
// Init network device
|
||||
let device = TunTapDevice::new(&opts.tap).unwrap();
|
||||
|
||||
// Choose between dhcp or static ip
|
||||
let config = if opts.static_ip {
|
||||
Config::Static(embassy_net::StaticConfig {
|
||||
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 1), 24),
|
||||
dns_servers: Vec::from_slice(&[Ipv4Address::new(8, 8, 4, 4).into(), Ipv4Address::new(8, 8, 8, 8).into()])
|
||||
.unwrap(),
|
||||
gateway: Some(Ipv4Address::new(192, 168, 69, 100)),
|
||||
})
|
||||
} else {
|
||||
Config::Dhcp(Default::default())
|
||||
};
|
||||
|
||||
// Generate random seed
|
||||
let mut seed = [0; 8];
|
||||
OsRng.fill_bytes(&mut seed);
|
||||
let seed = u64::from_le_bytes(seed);
|
||||
|
||||
// Init network stack
|
||||
let stack: &Stack<_> = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed));
|
||||
|
||||
// Launch network task
|
||||
spawner.spawn(net_task(stack)).unwrap();
|
||||
|
||||
let host = "example.com";
|
||||
info!("querying host {:?}...", host);
|
||||
match stack.dns_query(host, DnsQueryType::A).await {
|
||||
Ok(r) => {
|
||||
info!("query response: {:?}", r);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
|
||||
|
||||
fn main() {
|
||||
env_logger::builder()
|
||||
.filter_level(log::LevelFilter::Debug)
|
||||
.filter_module("async_io", log::LevelFilter::Info)
|
||||
.format_timestamp_nanos()
|
||||
.init();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
spawner.spawn(main_task(spawner)).unwrap();
|
||||
});
|
||||
}
|
@ -62,7 +62,7 @@ async fn main_task(spawner: Spawner) {
|
||||
let seed = u64::from_le_bytes(seed);
|
||||
|
||||
// Init network stack
|
||||
let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed));
|
||||
let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<3>::new()), seed));
|
||||
|
||||
// Launch network task
|
||||
spawner.spawn(net_task(stack)).unwrap();
|
||||
|
@ -58,7 +58,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -55,7 +55,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -4,15 +4,20 @@
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::sdmmc::Sdmmc;
|
||||
use embassy_stm32::sdmmc::{DataBlock, Sdmmc};
|
||||
use embassy_stm32::time::mhz;
|
||||
use embassy_stm32::{interrupt, Config};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
/// This is a safeguard to not overwrite any data on the SD card.
|
||||
/// If you don't care about SD card contents, set this to `true` to test writes.
|
||||
const ALLOW_WRITES: bool = false;
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) -> ! {
|
||||
let mut config = Config::default();
|
||||
config.rcc.sys_ck = Some(mhz(48));
|
||||
config.rcc.pll48 = true;
|
||||
let p = embassy_stm32::init(config);
|
||||
info!("Hello World!");
|
||||
|
||||
@ -34,11 +39,42 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
// Should print 400kHz for initialization
|
||||
info!("Configured clock: {}", sdmmc.clock().0);
|
||||
|
||||
unwrap!(sdmmc.init_card(mhz(25)).await);
|
||||
unwrap!(sdmmc.init_card(mhz(48)).await);
|
||||
|
||||
let card = unwrap!(sdmmc.card());
|
||||
|
||||
info!("Card: {:#?}", Debug2Format(card));
|
||||
info!("Clock: {}", sdmmc.clock());
|
||||
|
||||
// Arbitrary block index
|
||||
let block_idx = 16;
|
||||
|
||||
// SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware.
|
||||
let mut block = DataBlock([0u8; 512]);
|
||||
|
||||
sdmmc.read_block(block_idx, &mut block).await.unwrap();
|
||||
info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
|
||||
|
||||
if !ALLOW_WRITES {
|
||||
info!("Writing is disabled.");
|
||||
loop {}
|
||||
}
|
||||
|
||||
info!("Filling block with 0x55");
|
||||
block.fill(0x55);
|
||||
sdmmc.write_block(block_idx, &block).await.unwrap();
|
||||
info!("Write done");
|
||||
|
||||
sdmmc.read_block(block_idx, &mut block).await.unwrap();
|
||||
info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
|
||||
|
||||
info!("Filling block with 0xAA");
|
||||
block.fill(0xAA);
|
||||
sdmmc.write_block(block_idx, &block).await.unwrap();
|
||||
info!("Write done");
|
||||
|
||||
sdmmc.read_block(block_idx, &mut block).await.unwrap();
|
||||
info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]);
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
@ -82,7 +82,6 @@ async fn main(spawner: Spawner) {
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
None,
|
||||
);
|
||||
|
||||
// Our MAC addr.
|
||||
|
@ -57,7 +57,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -13,6 +13,7 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
async fn main(_spawner: Spawner) -> ! {
|
||||
let mut config = Config::default();
|
||||
config.rcc.sys_ck = Some(mhz(200));
|
||||
config.rcc.pll48 = true;
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
info!("Hello World!");
|
||||
|
@ -58,7 +58,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -9,7 +9,7 @@ embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["de
|
||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
|
||||
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits"] }
|
||||
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] }
|
||||
embedded-io = { version = "0.4.0", features = ["async"] }
|
||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||
|
||||
@ -21,7 +21,7 @@ cortex-m-rt = "0.7.0"
|
||||
embedded-hal = "0.2.6"
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
|
||||
embedded-hal-async = { version = "=0.2.0-alpha.0" }
|
||||
embedded-nal-async = "0.3.0"
|
||||
embedded-nal-async = "0.4.0"
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
heapless = { version = "0.7.5", default-features = false }
|
||||
|
@ -57,7 +57,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -59,7 +59,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -79,7 +79,6 @@ async fn main(spawner: Spawner) {
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 256])[..],
|
||||
&mut singleton!([0; 128])[..],
|
||||
None,
|
||||
);
|
||||
|
||||
// Our MAC addr.
|
||||
|
@ -51,7 +51,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -59,7 +59,6 @@ async fn main(_spawner: Spawner) {
|
||||
&mut config_descriptor,
|
||||
&mut bos_descriptor,
|
||||
&mut control_buf,
|
||||
None,
|
||||
);
|
||||
|
||||
// Create classes on the builder.
|
||||
|
@ -6,7 +6,7 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
RAM (xrw) : ORIGIN = 0x20000004, LENGTH = 191K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
|
||||
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user