aboutsummaryrefslogtreecommitdiff
path: root/examples/rp/src/bin
diff options
context:
space:
mode:
authorFrostie314159 <[email protected]>2024-03-31 20:48:05 +0200
committerGitHub <[email protected]>2024-03-31 20:48:05 +0200
commit67c9cc2c4b886e6962ecdd6eff8794b14c1accdc (patch)
treef176ab269949d26f48e04c950cebc5489bae8c56 /examples/rp/src/bin
parenta2f9aa592ec61beb247065003016515f0d423c13 (diff)
parent6634cc90bcd3eb25b64712688920f383584b2964 (diff)
Merge branch 'embassy-rs:main' into ticker_send_sync
Diffstat (limited to 'examples/rp/src/bin')
-rw-r--r--examples/rp/src/bin/adc.rs1
-rw-r--r--examples/rp/src/bin/blinky.rs1
-rw-r--r--examples/rp/src/bin/blinky_two_channels.rs50
-rw-r--r--examples/rp/src/bin/blinky_two_tasks.rs49
-rw-r--r--examples/rp/src/bin/button.rs1
-rw-r--r--examples/rp/src/bin/debounce.rs80
-rw-r--r--examples/rp/src/bin/ethernet_w5500_multisocket.rs22
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_client.rs22
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_server.rs22
-rw-r--r--examples/rp/src/bin/ethernet_w5500_udp.rs22
-rw-r--r--examples/rp/src/bin/flash.rs1
-rw-r--r--examples/rp/src/bin/gpio_async.rs1
-rw-r--r--examples/rp/src/bin/gpout.rs1
-rw-r--r--examples/rp/src/bin/i2c_async.rs1
-rw-r--r--examples/rp/src/bin/i2c_blocking.rs1
-rw-r--r--examples/rp/src/bin/i2c_slave.rs9
-rw-r--r--examples/rp/src/bin/multicore.rs16
-rw-r--r--examples/rp/src/bin/multiprio.rs1
-rw-r--r--examples/rp/src/bin/pio_async.rs1
-rw-r--r--examples/rp/src/bin/pio_dma.rs1
-rw-r--r--examples/rp/src/bin/pio_hd44780.rs1
-rw-r--r--examples/rp/src/bin/pio_i2s.rs125
-rw-r--r--examples/rp/src/bin/pio_rotary_encoder.rs1
-rw-r--r--examples/rp/src/bin/pio_stepper.rs1
-rw-r--r--examples/rp/src/bin/pio_uart.rs3
-rw-r--r--examples/rp/src/bin/pio_ws2812.rs8
-rw-r--r--examples/rp/src/bin/pwm.rs1
-rw-r--r--examples/rp/src/bin/pwm_input.rs1
-rw-r--r--examples/rp/src/bin/rosc.rs1
-rw-r--r--examples/rp/src/bin/rtc.rs1
-rw-r--r--examples/rp/src/bin/spi.rs1
-rw-r--r--examples/rp/src/bin/spi_async.rs1
-rw-r--r--examples/rp/src/bin/spi_display.rs1
-rw-r--r--examples/rp/src/bin/uart.rs1
-rw-r--r--examples/rp/src/bin/uart_buffered_split.rs9
-rw-r--r--examples/rp/src/bin/uart_unidir.rs1
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs27
-rw-r--r--examples/rp/src/bin/usb_hid_keyboard.rs3
-rw-r--r--examples/rp/src/bin/usb_hid_mouse.rs180
-rw-r--r--examples/rp/src/bin/usb_logger.rs1
-rw-r--r--examples/rp/src/bin/usb_midi.rs3
-rw-r--r--examples/rp/src/bin/usb_raw.rs3
-rw-r--r--examples/rp/src/bin/usb_raw_bulk.rs3
-rw-r--r--examples/rp/src/bin/usb_serial.rs3
-rw-r--r--examples/rp/src/bin/usb_serial_with_logger.rs115
-rw-r--r--examples/rp/src/bin/watchdog.rs1
-rw-r--r--examples/rp/src/bin/wifi_ap_tcp_server.rs20
-rw-r--r--examples/rp/src/bin/wifi_blinky.rs12
-rw-r--r--examples/rp/src/bin/wifi_scan.rs14
-rw-r--r--examples/rp/src/bin/wifi_tcp_server.rs20
50 files changed, 717 insertions, 148 deletions
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs
index a579be139..1bb7c2249 100644
--- a/examples/rp/src/bin/adc.rs
+++ b/examples/rp/src/bin/adc.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use defmt::*; 7use defmt::*;
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/blinky.rs b/examples/rp/src/bin/blinky.rs
index 66c8773fa..60fc45a70 100644
--- a/examples/rp/src/bin/blinky.rs
+++ b/examples/rp/src/bin/blinky.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/blinky_two_channels.rs b/examples/rp/src/bin/blinky_two_channels.rs
new file mode 100644
index 000000000..b2eec2a21
--- /dev/null
+++ b/examples/rp/src/bin/blinky_two_channels.rs
@@ -0,0 +1,50 @@
1#![no_std]
2#![no_main]
3/// This example demonstrates how to access a given pin from more than one embassy task
4/// The on-board LED is toggled by two tasks with slightly different periods, leading to the
5/// apparent duty cycle of the LED increasing, then decreasing, linearly. The phenomenon is similar
6/// to interference and the 'beats' you can hear if you play two frequencies close to one another
7/// [Link explaining it](https://www.physicsclassroom.com/class/sound/Lesson-3/Interference-and-Beats)
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_rp::gpio;
11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
12use embassy_sync::channel::{Channel, Sender};
13use embassy_time::{Duration, Ticker};
14use gpio::{AnyPin, Level, Output};
15use {defmt_rtt as _, panic_probe as _};
16
17enum LedState {
18 Toggle,
19}
20static CHANNEL: Channel<ThreadModeRawMutex, LedState, 64> = Channel::new();
21
22#[embassy_executor::main]
23async fn main(spawner: Spawner) {
24 let p = embassy_rp::init(Default::default());
25 let mut led = Output::new(AnyPin::from(p.PIN_25), Level::High);
26
27 let dt = 100 * 1_000_000;
28 let k = 1.003;
29
30 unwrap!(spawner.spawn(toggle_led(CHANNEL.sender(), Duration::from_nanos(dt))));
31 unwrap!(spawner.spawn(toggle_led(
32 CHANNEL.sender(),
33 Duration::from_nanos((dt as f64 * k) as u64)
34 )));
35
36 loop {
37 match CHANNEL.receive().await {
38 LedState::Toggle => led.toggle(),
39 }
40 }
41}
42
43#[embassy_executor::task(pool_size = 2)]
44async fn toggle_led(control: Sender<'static, ThreadModeRawMutex, LedState, 64>, delay: Duration) {
45 let mut ticker = Ticker::every(delay);
46 loop {
47 control.send(LedState::Toggle).await;
48 ticker.next().await;
49 }
50}
diff --git a/examples/rp/src/bin/blinky_two_tasks.rs b/examples/rp/src/bin/blinky_two_tasks.rs
new file mode 100644
index 000000000..a57b513d6
--- /dev/null
+++ b/examples/rp/src/bin/blinky_two_tasks.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3/// This example demonstrates how to access a given pin from more than one embassy task
4/// The on-board LED is toggled by two tasks with slightly different periods, leading to the
5/// apparent duty cycle of the LED increasing, then decreasing, linearly. The phenomenon is similar
6/// to interference and the 'beats' you can hear if you play two frequencies close to one another
7/// [Link explaining it](https://www.physicsclassroom.com/class/sound/Lesson-3/Interference-and-Beats)
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_rp::gpio;
11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
12use embassy_sync::mutex::Mutex;
13use embassy_time::{Duration, Ticker};
14use gpio::{AnyPin, Level, Output};
15use {defmt_rtt as _, panic_probe as _};
16
17type LedType = Mutex<ThreadModeRawMutex, Option<Output<'static>>>;
18static LED: LedType = Mutex::new(None);
19
20#[embassy_executor::main]
21async fn main(spawner: Spawner) {
22 let p = embassy_rp::init(Default::default());
23 // set the content of the global LED reference to the real LED pin
24 let led = Output::new(AnyPin::from(p.PIN_25), Level::High);
25 // inner scope is so that once the mutex is written to, the MutexGuard is dropped, thus the
26 // Mutex is released
27 {
28 *(LED.lock().await) = Some(led);
29 }
30 let dt = 100 * 1_000_000;
31 let k = 1.003;
32
33 unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos(dt))));
34 unwrap!(spawner.spawn(toggle_led(&LED, Duration::from_nanos((dt as f64 * k) as u64))));
35}
36
37#[embassy_executor::task(pool_size = 2)]
38async fn toggle_led(led: &'static LedType, delay: Duration) {
39 let mut ticker = Ticker::every(delay);
40 loop {
41 {
42 let mut led_unlocked = led.lock().await;
43 if let Some(pin_ref) = led_unlocked.as_mut() {
44 pin_ref.toggle();
45 }
46 }
47 ticker.next().await;
48 }
49}
diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs
index d7aa89410..4ad2ca3b7 100644
--- a/examples/rp/src/bin/button.rs
+++ b/examples/rp/src/bin/button.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
10use embassy_rp::gpio::{Input, Level, Output, Pull}; 9use embassy_rp::gpio::{Input, Level, Output, Pull};
diff --git a/examples/rp/src/bin/debounce.rs b/examples/rp/src/bin/debounce.rs
new file mode 100644
index 000000000..0077f19fc
--- /dev/null
+++ b/examples/rp/src/bin/debounce.rs
@@ -0,0 +1,80 @@
1//! This example shows the ease of debouncing a button with async rust.
2//! Hook up a button or switch between pin 9 and ground.
3
4#![no_std]
5#![no_main]
6
7use defmt::info;
8use embassy_executor::Spawner;
9use embassy_rp::gpio::{Input, Level, Pull};
10use embassy_time::{with_deadline, Duration, Instant, Timer};
11use {defmt_rtt as _, panic_probe as _};
12
13pub struct Debouncer<'a> {
14 input: Input<'a>,
15 debounce: Duration,
16}
17
18impl<'a> Debouncer<'a> {
19 pub fn new(input: Input<'a>, debounce: Duration) -> Self {
20 Self { input, debounce }
21 }
22
23 pub async fn debounce(&mut self) -> Level {
24 loop {
25 let l1 = self.input.get_level();
26
27 self.input.wait_for_any_edge().await;
28
29 Timer::after(self.debounce).await;
30
31 let l2 = self.input.get_level();
32 if l1 != l2 {
33 break l2;
34 }
35 }
36 }
37}
38
39#[embassy_executor::main]
40async fn main(_spawner: Spawner) {
41 let p = embassy_rp::init(Default::default());
42 let mut btn = Debouncer::new(Input::new(p.PIN_9, Pull::Up), Duration::from_millis(20));
43
44 info!("Debounce Demo");
45
46 loop {
47 // button pressed
48 btn.debounce().await;
49 let start = Instant::now();
50 info!("Button Press");
51
52 match with_deadline(start + Duration::from_secs(1), btn.debounce()).await {
53 // Button Released < 1s
54 Ok(_) => {
55 info!("Button pressed for: {}ms", start.elapsed().as_millis());
56 continue;
57 }
58 // button held for > 1s
59 Err(_) => {
60 info!("Button Held");
61 }
62 }
63
64 match with_deadline(start + Duration::from_secs(5), btn.debounce()).await {
65 // Button released <5s
66 Ok(_) => {
67 info!("Button pressed for: {}ms", start.elapsed().as_millis());
68 continue;
69 }
70 // button held for > >5s
71 Err(_) => {
72 info!("Button Long Held");
73 }
74 }
75
76 // wait for button release before handling another press
77 btn.debounce().await;
78 info!("Button pressed for: {}ms", start.elapsed().as_millis());
79 }
80}
diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs
index c0fde62ab..bd52cadca 100644
--- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs
+++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -14,13 +13,13 @@ use embassy_net_wiznet::chip::W5500;
14use embassy_net_wiznet::*; 13use embassy_net_wiznet::*;
15use embassy_rp::clocks::RoscRng; 14use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull}; 15use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; 16use embassy_rp::peripherals::SPI0;
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 17use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::{Delay, Duration}; 18use embassy_time::{Delay, Duration};
20use embedded_hal_bus::spi::ExclusiveDevice; 19use embedded_hal_bus::spi::ExclusiveDevice;
21use embedded_io_async::Write; 20use embedded_io_async::Write;
22use rand::RngCore; 21use rand::RngCore;
23use static_cell::make_static; 22use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
25 24
26#[embassy_executor::task] 25#[embassy_executor::task]
@@ -28,9 +27,9 @@ async fn ethernet_task(
28 runner: Runner< 27 runner: Runner<
29 'static, 28 'static,
30 W5500, 29 W5500,
31 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, 30 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
32 Input<'static, PIN_21>, 31 Input<'static>,
33 Output<'static, PIN_20>, 32 Output<'static>,
34 >, 33 >,
35) -> ! { 34) -> ! {
36 runner.run().await 35 runner.run().await
@@ -55,7 +54,8 @@ async fn main(spawner: Spawner) {
55 let w5500_reset = Output::new(p.PIN_20, Level::High); 54 let w5500_reset = Output::new(p.PIN_20, Level::High);
56 55
57 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 56 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
58 let state = make_static!(State::<8, 8>::new()); 57 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
58 let state = STATE.init(State::<8, 8>::new());
59 let (device, runner) = embassy_net_wiznet::new( 59 let (device, runner) = embassy_net_wiznet::new(
60 mac_addr, 60 mac_addr,
61 state, 61 state,
@@ -70,11 +70,13 @@ async fn main(spawner: Spawner) {
70 let seed = rng.next_u64(); 70 let seed = rng.next_u64();
71 71
72 // Init network stack 72 // Init network stack
73 let stack = &*make_static!(Stack::new( 73 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
74 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
75 let stack = &*STACK.init(Stack::new(
74 device, 76 device,
75 embassy_net::Config::dhcpv4(Default::default()), 77 embassy_net::Config::dhcpv4(Default::default()),
76 make_static!(StackResources::<3>::new()), 78 RESOURCES.init(StackResources::<3>::new()),
77 seed 79 seed,
78 )); 80 ));
79 81
80 // Launch network task 82 // Launch network task
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
index b19362fc1..3e4fbd2e6 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use core::str::FromStr; 8use core::str::FromStr;
10 9
@@ -16,13 +15,13 @@ use embassy_net_wiznet::chip::W5500;
16use embassy_net_wiznet::*; 15use embassy_net_wiznet::*;
17use embassy_rp::clocks::RoscRng; 16use embassy_rp::clocks::RoscRng;
18use embassy_rp::gpio::{Input, Level, Output, Pull}; 17use embassy_rp::gpio::{Input, Level, Output, Pull};
19use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; 18use embassy_rp::peripherals::SPI0;
20use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 19use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
21use embassy_time::{Delay, Duration, Timer}; 20use embassy_time::{Delay, Duration, Timer};
22use embedded_hal_bus::spi::ExclusiveDevice; 21use embedded_hal_bus::spi::ExclusiveDevice;
23use embedded_io_async::Write; 22use embedded_io_async::Write;
24use rand::RngCore; 23use rand::RngCore;
25use static_cell::make_static; 24use static_cell::StaticCell;
26use {defmt_rtt as _, panic_probe as _}; 25use {defmt_rtt as _, panic_probe as _};
27 26
28#[embassy_executor::task] 27#[embassy_executor::task]
@@ -30,9 +29,9 @@ async fn ethernet_task(
30 runner: Runner< 29 runner: Runner<
31 'static, 30 'static,
32 W5500, 31 W5500,
33 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, 32 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
34 Input<'static, PIN_21>, 33 Input<'static>,
35 Output<'static, PIN_20>, 34 Output<'static>,
36 >, 35 >,
37) -> ! { 36) -> ! {
38 runner.run().await 37 runner.run().await
@@ -58,7 +57,8 @@ async fn main(spawner: Spawner) {
58 let w5500_reset = Output::new(p.PIN_20, Level::High); 57 let w5500_reset = Output::new(p.PIN_20, Level::High);
59 58
60 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 59 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
61 let state = make_static!(State::<8, 8>::new()); 60 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
61 let state = STATE.init(State::<8, 8>::new());
62 let (device, runner) = embassy_net_wiznet::new( 62 let (device, runner) = embassy_net_wiznet::new(
63 mac_addr, 63 mac_addr,
64 state, 64 state,
@@ -73,11 +73,13 @@ async fn main(spawner: Spawner) {
73 let seed = rng.next_u64(); 73 let seed = rng.next_u64();
74 74
75 // Init network stack 75 // Init network stack
76 let stack = &*make_static!(Stack::new( 76 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
77 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
78 let stack = &*STACK.init(Stack::new(
77 device, 79 device,
78 embassy_net::Config::dhcpv4(Default::default()), 80 embassy_net::Config::dhcpv4(Default::default()),
79 make_static!(StackResources::<2>::new()), 81 RESOURCES.init(StackResources::<2>::new()),
80 seed 82 seed,
81 )); 83 ));
82 84
83 // Launch network task 85 // Launch network task
diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
index c62caed7a..5532851f3 100644
--- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
+++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
@@ -15,13 +14,13 @@ use embassy_net_wiznet::chip::W5500;
15use embassy_net_wiznet::*; 14use embassy_net_wiznet::*;
16use embassy_rp::clocks::RoscRng; 15use embassy_rp::clocks::RoscRng;
17use embassy_rp::gpio::{Input, Level, Output, Pull}; 16use embassy_rp::gpio::{Input, Level, Output, Pull};
18use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; 17use embassy_rp::peripherals::SPI0;
19use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::{Delay, Duration}; 19use embassy_time::{Delay, Duration};
21use embedded_hal_bus::spi::ExclusiveDevice; 20use embedded_hal_bus::spi::ExclusiveDevice;
22use embedded_io_async::Write; 21use embedded_io_async::Write;
23use rand::RngCore; 22use rand::RngCore;
24use static_cell::make_static; 23use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
26 25
27#[embassy_executor::task] 26#[embassy_executor::task]
@@ -29,9 +28,9 @@ async fn ethernet_task(
29 runner: Runner< 28 runner: Runner<
30 'static, 29 'static,
31 W5500, 30 W5500,
32 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, 31 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
33 Input<'static, PIN_21>, 32 Input<'static>,
34 Output<'static, PIN_20>, 33 Output<'static>,
35 >, 34 >,
36) -> ! { 35) -> ! {
37 runner.run().await 36 runner.run().await
@@ -57,7 +56,8 @@ async fn main(spawner: Spawner) {
57 let w5500_reset = Output::new(p.PIN_20, Level::High); 56 let w5500_reset = Output::new(p.PIN_20, Level::High);
58 57
59 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 58 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
60 let state = make_static!(State::<8, 8>::new()); 59 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
60 let state = STATE.init(State::<8, 8>::new());
61 let (device, runner) = embassy_net_wiznet::new( 61 let (device, runner) = embassy_net_wiznet::new(
62 mac_addr, 62 mac_addr,
63 state, 63 state,
@@ -72,11 +72,13 @@ async fn main(spawner: Spawner) {
72 let seed = rng.next_u64(); 72 let seed = rng.next_u64();
73 73
74 // Init network stack 74 // Init network stack
75 let stack = &*make_static!(Stack::new( 75 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
76 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
77 let stack = &*STACK.init(Stack::new(
76 device, 78 device,
77 embassy_net::Config::dhcpv4(Default::default()), 79 embassy_net::Config::dhcpv4(Default::default()),
78 make_static!(StackResources::<2>::new()), 80 RESOURCES.init(StackResources::<2>::new()),
79 seed 81 seed,
80 )); 82 ));
81 83
82 // Launch network task 84 // Launch network task
diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs
index 76dabce1c..adb1d8941 100644
--- a/examples/rp/src/bin/ethernet_w5500_udp.rs
+++ b/examples/rp/src/bin/ethernet_w5500_udp.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -15,12 +14,12 @@ use embassy_net_wiznet::chip::W5500;
15use embassy_net_wiznet::*; 14use embassy_net_wiznet::*;
16use embassy_rp::clocks::RoscRng; 15use embassy_rp::clocks::RoscRng;
17use embassy_rp::gpio::{Input, Level, Output, Pull}; 16use embassy_rp::gpio::{Input, Level, Output, Pull};
18use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; 17use embassy_rp::peripherals::SPI0;
19use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; 18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::Delay; 19use embassy_time::Delay;
21use embedded_hal_bus::spi::ExclusiveDevice; 20use embedded_hal_bus::spi::ExclusiveDevice;
22use rand::RngCore; 21use rand::RngCore;
23use static_cell::make_static; 22use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
25 24
26#[embassy_executor::task] 25#[embassy_executor::task]
@@ -28,9 +27,9 @@ async fn ethernet_task(
28 runner: Runner< 27 runner: Runner<
29 'static, 28 'static,
30 W5500, 29 W5500,
31 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>, Delay>, 30 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
32 Input<'static, PIN_21>, 31 Input<'static>,
33 Output<'static, PIN_20>, 32 Output<'static>,
34 >, 33 >,
35) -> ! { 34) -> ! {
36 runner.run().await 35 runner.run().await
@@ -55,7 +54,8 @@ async fn main(spawner: Spawner) {
55 let w5500_reset = Output::new(p.PIN_20, Level::High); 54 let w5500_reset = Output::new(p.PIN_20, Level::High);
56 55
57 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; 56 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
58 let state = make_static!(State::<8, 8>::new()); 57 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
58 let state = STATE.init(State::<8, 8>::new());
59 let (device, runner) = embassy_net_wiznet::new( 59 let (device, runner) = embassy_net_wiznet::new(
60 mac_addr, 60 mac_addr,
61 state, 61 state,
@@ -70,11 +70,13 @@ async fn main(spawner: Spawner) {
70 let seed = rng.next_u64(); 70 let seed = rng.next_u64();
71 71
72 // Init network stack 72 // Init network stack
73 let stack = &*make_static!(Stack::new( 73 static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
74 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
75 let stack = &*STACK.init(Stack::new(
74 device, 76 device,
75 embassy_net::Config::dhcpv4(Default::default()), 77 embassy_net::Config::dhcpv4(Default::default()),
76 make_static!(StackResources::<2>::new()), 78 RESOURCES.init(StackResources::<2>::new()),
77 seed 79 seed,
78 )); 80 ));
79 81
80 // Launch network task 82 // Launch network task
diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs
index 129a8497f..eb3e6a2b9 100644
--- a/examples/rp/src/bin/flash.rs
+++ b/examples/rp/src/bin/flash.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/gpio_async.rs b/examples/rp/src/bin/gpio_async.rs
index 98209fe41..b79fb2a15 100644
--- a/examples/rp/src/bin/gpio_async.rs
+++ b/examples/rp/src/bin/gpio_async.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs
index 896cc15ee..011359253 100644
--- a/examples/rp/src/bin/gpout.rs
+++ b/examples/rp/src/bin/gpout.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs
index 7b53aae72..e31cc894c 100644
--- a/examples/rp/src/bin/i2c_async.rs
+++ b/examples/rp/src/bin/i2c_async.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs
index 9ddb48d69..c9c8a2760 100644
--- a/examples/rp/src/bin/i2c_blocking.rs
+++ b/examples/rp/src/bin/i2c_blocking.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/i2c_slave.rs b/examples/rp/src/bin/i2c_slave.rs
index 151b083a4..9fffb4646 100644
--- a/examples/rp/src/bin/i2c_slave.rs
+++ b/examples/rp/src/bin/i2c_slave.rs
@@ -1,7 +1,6 @@
1//! This example shows how to use the 2040 as an i2c slave. 1//! This example shows how to use the 2040 as an i2c slave.
2#![no_std] 2#![no_std]
3#![no_main] 3#![no_main]
4#![feature(type_alias_impl_trait)]
5 4
6use defmt::*; 5use defmt::*;
7use embassy_executor::Spawner; 6use embassy_executor::Spawner;
@@ -27,7 +26,7 @@ async fn device_task(mut dev: i2c_slave::I2cSlave<'static, I2C1>) -> ! {
27 loop { 26 loop {
28 let mut buf = [0u8; 128]; 27 let mut buf = [0u8; 128];
29 match dev.listen(&mut buf).await { 28 match dev.listen(&mut buf).await {
30 Ok(i2c_slave::Command::GeneralCall(len)) => info!("Device recieved general call write: {}", buf[..len]), 29 Ok(i2c_slave::Command::GeneralCall(len)) => info!("Device received general call write: {}", buf[..len]),
31 Ok(i2c_slave::Command::Read) => loop { 30 Ok(i2c_slave::Command::Read) => loop {
32 match dev.respond_to_read(&[state]).await { 31 match dev.respond_to_read(&[state]).await {
33 Ok(x) => match x { 32 Ok(x) => match x {
@@ -41,9 +40,9 @@ async fn device_task(mut dev: i2c_slave::I2cSlave<'static, I2C1>) -> ! {
41 Err(e) => error!("error while responding {}", e), 40 Err(e) => error!("error while responding {}", e),
42 } 41 }
43 }, 42 },
44 Ok(i2c_slave::Command::Write(len)) => info!("Device recieved write: {}", buf[..len]), 43 Ok(i2c_slave::Command::Write(len)) => info!("Device received write: {}", buf[..len]),
45 Ok(i2c_slave::Command::WriteRead(len)) => { 44 Ok(i2c_slave::Command::WriteRead(len)) => {
46 info!("device recieved write read: {:x}", buf[..len]); 45 info!("device received write read: {:x}", buf[..len]);
47 match buf[0] { 46 match buf[0] {
48 // Set the state 47 // Set the state
49 0xC2 => { 48 0xC2 => {
@@ -111,7 +110,7 @@ async fn main(spawner: Spawner) {
111 let c_sda = p.PIN_1; 110 let c_sda = p.PIN_1;
112 let c_scl = p.PIN_0; 111 let c_scl = p.PIN_0;
113 let mut config = i2c::Config::default(); 112 let mut config = i2c::Config::default();
114 config.frequency = 5_000; 113 config.frequency = 1_000_000;
115 let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config); 114 let controller = i2c::I2c::new_async(p.I2C0, c_sda, c_scl, Irqs, config);
116 115
117 unwrap!(spawner.spawn(controller_task(controller))); 116 unwrap!(spawner.spawn(controller_task(controller)));
diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs
index 43eaf8b0a..7cb546c91 100644
--- a/examples/rp/src/bin/multicore.rs
+++ b/examples/rp/src/bin/multicore.rs
@@ -4,13 +4,11 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Executor; 9use embassy_executor::Executor;
11use embassy_rp::gpio::{Level, Output}; 10use embassy_rp::gpio::{Level, Output};
12use embassy_rp::multicore::{spawn_core1, Stack}; 11use embassy_rp::multicore::{spawn_core1, Stack};
13use embassy_rp::peripherals::PIN_25;
14use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 12use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
15use embassy_sync::channel::Channel; 13use embassy_sync::channel::Channel;
16use embassy_time::Timer; 14use embassy_time::Timer;
@@ -32,10 +30,14 @@ fn main() -> ! {
32 let p = embassy_rp::init(Default::default()); 30 let p = embassy_rp::init(Default::default());
33 let led = Output::new(p.PIN_25, Level::Low); 31 let led = Output::new(p.PIN_25, Level::Low);
34 32
35 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { 33 spawn_core1(
36 let executor1 = EXECUTOR1.init(Executor::new()); 34 p.CORE1,
37 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); 35 unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) },
38 }); 36 move || {
37 let executor1 = EXECUTOR1.init(Executor::new());
38 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led))));
39 },
40 );
39 41
40 let executor0 = EXECUTOR0.init(Executor::new()); 42 let executor0 = EXECUTOR0.init(Executor::new());
41 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); 43 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task())));
@@ -53,7 +55,7 @@ async fn core0_task() {
53} 55}
54 56
55#[embassy_executor::task] 57#[embassy_executor::task]
56async fn core1_task(mut led: Output<'static, PIN_25>) { 58async fn core1_task(mut led: Output<'static>) {
57 info!("Hello from core 1"); 59 info!("Hello from core 1");
58 loop { 60 loop {
59 match CHANNEL.receive().await { 61 match CHANNEL.receive().await {
diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs
index 28f621437..26b80c11d 100644
--- a/examples/rp/src/bin/multiprio.rs
+++ b/examples/rp/src/bin/multiprio.rs
@@ -55,7 +55,6 @@
55 55
56#![no_std] 56#![no_std]
57#![no_main] 57#![no_main]
58#![feature(type_alias_impl_trait)]
59 58
60use cortex_m_rt::entry; 59use cortex_m_rt::entry;
61use defmt::{info, unwrap}; 60use defmt::{info, unwrap};
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs
index a6d6144be..ee248591b 100644
--- a/examples/rp/src/bin/pio_async.rs
+++ b/examples/rp/src/bin/pio_async.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6use defmt::info; 5use defmt::info;
7use embassy_executor::Spawner; 6use embassy_executor::Spawner;
8use embassy_rp::bind_interrupts; 7use embassy_rp::bind_interrupts;
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs
index 86e5017ac..02700269c 100644
--- a/examples/rp/src/bin/pio_dma.rs
+++ b/examples/rp/src/bin/pio_dma.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6use defmt::info; 5use defmt::info;
7use embassy_executor::Spawner; 6use embassy_executor::Spawner;
8use embassy_futures::join::join; 7use embassy_futures::join::join;
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs
index 5e5a6f9a3..3fab7b5f2 100644
--- a/examples/rp/src/bin/pio_hd44780.rs
+++ b/examples/rp/src/bin/pio_hd44780.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use core::fmt::Write; 7use core::fmt::Write;
9 8
diff --git a/examples/rp/src/bin/pio_i2s.rs b/examples/rp/src/bin/pio_i2s.rs
new file mode 100644
index 000000000..cf60e5b30
--- /dev/null
+++ b/examples/rp/src/bin/pio_i2s.rs
@@ -0,0 +1,125 @@
1//! This example shows generating audio and sending it to a connected i2s DAC using the PIO
2//! module of the RP2040.
3//!
4//! Connect the i2s DAC as follows:
5//! bclk : GPIO 18
6//! lrc : GPIO 19
7//! din : GPIO 20
8//! Then hold down the boot select button to trigger a rising triangle waveform.
9
10#![no_std]
11#![no_main]
12
13use core::mem;
14
15use embassy_executor::Spawner;
16use embassy_rp::peripherals::PIO0;
17use embassy_rp::pio::{Config, FifoJoin, InterruptHandler, Pio, ShiftConfig, ShiftDirection};
18use embassy_rp::{bind_interrupts, Peripheral};
19use fixed::traits::ToFixed;
20use static_cell::StaticCell;
21use {defmt_rtt as _, panic_probe as _};
22
23bind_interrupts!(struct Irqs {
24 PIO0_IRQ_0 => InterruptHandler<PIO0>;
25});
26
27const SAMPLE_RATE: u32 = 48_000;
28
29#[embassy_executor::main]
30async fn main(_spawner: Spawner) {
31 let mut p = embassy_rp::init(Default::default());
32
33 // Setup pio state machine for i2s output
34 let mut pio = Pio::new(p.PIO0, Irqs);
35
36 #[rustfmt::skip]
37 let pio_program = pio_proc::pio_asm!(
38 ".side_set 2",
39 " set x, 14 side 0b01", // side 0bWB - W = Word Clock, B = Bit Clock
40 "left_data:",
41 " out pins, 1 side 0b00",
42 " jmp x-- left_data side 0b01",
43 " out pins 1 side 0b10",
44 " set x, 14 side 0b11",
45 "right_data:",
46 " out pins 1 side 0b10",
47 " jmp x-- right_data side 0b11",
48 " out pins 1 side 0b00",
49 );
50
51 let bit_clock_pin = p.PIN_18;
52 let left_right_clock_pin = p.PIN_19;
53 let data_pin = p.PIN_20;
54
55 let data_pin = pio.common.make_pio_pin(data_pin);
56 let bit_clock_pin = pio.common.make_pio_pin(bit_clock_pin);
57 let left_right_clock_pin = pio.common.make_pio_pin(left_right_clock_pin);
58
59 let cfg = {
60 let mut cfg = Config::default();
61 cfg.use_program(
62 &pio.common.load_program(&pio_program.program),
63 &[&bit_clock_pin, &left_right_clock_pin],
64 );
65 cfg.set_out_pins(&[&data_pin]);
66 const BIT_DEPTH: u32 = 16;
67 const CHANNELS: u32 = 2;
68 let clock_frequency = SAMPLE_RATE * BIT_DEPTH * CHANNELS;
69 cfg.clock_divider = (125_000_000. / clock_frequency as f64 / 2.).to_fixed();
70 cfg.shift_out = ShiftConfig {
71 threshold: 32,
72 direction: ShiftDirection::Left,
73 auto_fill: true,
74 };
75 // join fifos to have twice the time to start the next dma transfer
76 cfg.fifo_join = FifoJoin::TxOnly;
77 cfg
78 };
79 pio.sm0.set_config(&cfg);
80 pio.sm0.set_pin_dirs(
81 embassy_rp::pio::Direction::Out,
82 &[&data_pin, &left_right_clock_pin, &bit_clock_pin],
83 );
84
85 // create two audio buffers (back and front) which will take turns being
86 // filled with new audio data and being sent to the pio fifo using dma
87 const BUFFER_SIZE: usize = 960;
88 static DMA_BUFFER: StaticCell<[u32; BUFFER_SIZE * 2]> = StaticCell::new();
89 let dma_buffer = DMA_BUFFER.init_with(|| [0u32; BUFFER_SIZE * 2]);
90 let (mut back_buffer, mut front_buffer) = dma_buffer.split_at_mut(BUFFER_SIZE);
91
92 // start pio state machine
93 pio.sm0.set_enable(true);
94 let tx = pio.sm0.tx();
95 let mut dma_ref = p.DMA_CH0.into_ref();
96
97 let mut fade_value: i32 = 0;
98 let mut phase: i32 = 0;
99
100 loop {
101 // trigger transfer of front buffer data to the pio fifo
102 // but don't await the returned future, yet
103 let dma_future = tx.dma_push(dma_ref.reborrow(), front_buffer);
104
105 // fade in audio when bootsel is pressed
106 let fade_target = if p.BOOTSEL.is_pressed() { i32::MAX } else { 0 };
107
108 // fill back buffer with fresh audio samples before awaiting the dma future
109 for s in back_buffer.iter_mut() {
110 // exponential approach of fade_value => fade_target
111 fade_value += (fade_target - fade_value) >> 14;
112 // generate triangle wave with amplitude and frequency based on fade value
113 phase = (phase + (fade_value >> 22)) & 0xffff;
114 let triangle_sample = (phase as i16 as i32).abs() - 16384;
115 let sample = (triangle_sample * (fade_value >> 15)) >> 16;
116 // duplicate mono sample into lower and upper half of dma word
117 *s = (sample as u16 as u32) * 0x10001;
118 }
119
120 // now await the dma future. once the dma finishes, the next buffer needs to be queued
121 // within DMA_DEPTH / SAMPLE_RATE = 8 / 48000 seconds = 166us
122 dma_future.await;
123 mem::swap(&mut back_buffer, &mut front_buffer);
124 }
125}
diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs
index 6d9d59df6..58bdadbc0 100644
--- a/examples/rp/src/bin/pio_rotary_encoder.rs
+++ b/examples/rp/src/bin/pio_rotary_encoder.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::info; 6use defmt::info;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/pio_stepper.rs b/examples/rp/src/bin/pio_stepper.rs
index 02fb20699..ab9ecf623 100644
--- a/examples/rp/src/bin/pio_stepper.rs
+++ b/examples/rp/src/bin/pio_stepper.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7use core::mem::{self, MaybeUninit}; 6use core::mem::{self, MaybeUninit};
8 7
9use defmt::info; 8use defmt::info;
diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs
index c0ea23607..53b696309 100644
--- a/examples/rp/src/bin/pio_uart.rs
+++ b/examples/rp/src/bin/pio_uart.rs
@@ -8,7 +8,6 @@
8 8
9#![no_std] 9#![no_std]
10#![no_main] 10#![no_main]
11#![feature(type_alias_impl_trait)]
12#![allow(async_fn_in_trait)] 11#![allow(async_fn_in_trait)]
13 12
14use defmt::{info, panic, trace}; 13use defmt::{info, panic, trace};
@@ -61,7 +60,6 @@ async fn main(_spawner: Spawner) {
61 60
62 // Create embassy-usb DeviceBuilder using the driver and config. 61 // Create embassy-usb DeviceBuilder using the driver and config.
63 // It needs some buffers for building the descriptors. 62 // It needs some buffers for building the descriptors.
64 let mut device_descriptor = [0; 256];
65 let mut config_descriptor = [0; 256]; 63 let mut config_descriptor = [0; 256];
66 let mut bos_descriptor = [0; 256]; 64 let mut bos_descriptor = [0; 256];
67 let mut control_buf = [0; 64]; 65 let mut control_buf = [0; 64];
@@ -71,7 +69,6 @@ async fn main(_spawner: Spawner) {
71 let mut builder = Builder::new( 69 let mut builder = Builder::new(
72 driver, 70 driver,
73 config, 71 config,
74 &mut device_descriptor,
75 &mut config_descriptor, 72 &mut config_descriptor,
76 &mut bos_descriptor, 73 &mut bos_descriptor,
77 &mut [], // no msos descriptors 74 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs
index 7b3259538..ac145933c 100644
--- a/examples/rp/src/bin/pio_ws2812.rs
+++ b/examples/rp/src/bin/pio_ws2812.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use defmt::*; 7use defmt::*;
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
@@ -13,7 +12,7 @@ use embassy_rp::pio::{
13 Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, 12 Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine,
14}; 13};
15use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; 14use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef};
16use embassy_time::Timer; 15use embassy_time::{Duration, Ticker, Timer};
17use fixed::types::U24F8; 16use fixed::types::U24F8;
18use fixed_macro::fixed; 17use fixed_macro::fixed;
19use smart_leds::RGB8; 18use smart_leds::RGB8;
@@ -108,6 +107,8 @@ impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> {
108 107
109 // DMA transfer 108 // DMA transfer
110 self.sm.tx().dma_push(self.dma.reborrow(), &words).await; 109 self.sm.tx().dma_push(self.dma.reborrow(), &words).await;
110
111 Timer::after_micros(55).await;
111 } 112 }
112} 113}
113 114
@@ -144,6 +145,7 @@ async fn main(_spawner: Spawner) {
144 let mut ws2812 = Ws2812::new(&mut common, sm0, p.DMA_CH0, p.PIN_16); 145 let mut ws2812 = Ws2812::new(&mut common, sm0, p.DMA_CH0, p.PIN_16);
145 146
146 // Loop forever making RGB values and pushing them out to the WS2812. 147 // Loop forever making RGB values and pushing them out to the WS2812.
148 let mut ticker = Ticker::every(Duration::from_millis(10));
147 loop { 149 loop {
148 for j in 0..(256 * 5) { 150 for j in 0..(256 * 5) {
149 debug!("New Colors:"); 151 debug!("New Colors:");
@@ -153,7 +155,7 @@ async fn main(_spawner: Spawner) {
153 } 155 }
154 ws2812.write(&data).await; 156 ws2812.write(&data).await;
155 157
156 Timer::after_millis(10).await; 158 ticker.next().await;
157 } 159 }
158 } 160 }
159} 161}
diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs
index a99e88003..4fb62546d 100644
--- a/examples/rp/src/bin/pwm.rs
+++ b/examples/rp/src/bin/pwm.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/pwm_input.rs b/examples/rp/src/bin/pwm_input.rs
index 0fc2e40c3..e7bcbfbd4 100644
--- a/examples/rp/src/bin/pwm_input.rs
+++ b/examples/rp/src/bin/pwm_input.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/rosc.rs b/examples/rp/src/bin/rosc.rs
index f841043b6..942b72319 100644
--- a/examples/rp/src/bin/rosc.rs
+++ b/examples/rp/src/bin/rosc.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs
index 667876db5..e9a5e43a8 100644
--- a/examples/rp/src/bin/rtc.rs
+++ b/examples/rp/src/bin/rtc.rs
@@ -2,7 +2,6 @@
2 2
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)]
6 5
7use defmt::*; 6use defmt::*;
8use embassy_executor::Spawner; 7use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs
index 602348f7a..4cc4f5210 100644
--- a/examples/rp/src/bin/spi.rs
+++ b/examples/rp/src/bin/spi.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs
index f5a2d334e..266584efc 100644
--- a/examples/rp/src/bin/spi_async.rs
+++ b/examples/rp/src/bin/spi_async.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7 6
8use defmt::*; 7use defmt::*;
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs
index 26c258e1c..e937b9d0a 100644
--- a/examples/rp/src/bin/spi_display.rs
+++ b/examples/rp/src/bin/spi_display.rs
@@ -5,7 +5,6 @@
5 5
6#![no_std] 6#![no_std]
7#![no_main] 7#![no_main]
8#![feature(type_alias_impl_trait)]
9 8
10use core::cell::RefCell; 9use core::cell::RefCell;
11 10
diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs
index 451c3c396..6a2816cd0 100644
--- a/examples/rp/src/bin/uart.rs
+++ b/examples/rp/src/bin/uart.rs
@@ -6,7 +6,6 @@
6 6
7#![no_std] 7#![no_std]
8#![no_main] 8#![no_main]
9#![feature(type_alias_impl_trait)]
10 9
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
12use embassy_rp::uart; 11use embassy_rp::uart;
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs
index 14e8810a4..fac61aa04 100644
--- a/examples/rp/src/bin/uart_buffered_split.rs
+++ b/examples/rp/src/bin/uart_buffered_split.rs
@@ -6,7 +6,6 @@
6 6
7#![no_std] 7#![no_std]
8#![no_main] 8#![no_main]
9#![feature(type_alias_impl_trait)]
10 9
11use defmt::*; 10use defmt::*;
12use embassy_executor::Spawner; 11use embassy_executor::Spawner;
@@ -15,7 +14,7 @@ use embassy_rp::peripherals::UART0;
15use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; 14use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config};
16use embassy_time::Timer; 15use embassy_time::Timer;
17use embedded_io_async::{Read, Write}; 16use embedded_io_async::{Read, Write};
18use static_cell::make_static; 17use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
20 19
21bind_interrupts!(struct Irqs { 20bind_interrupts!(struct Irqs {
@@ -27,8 +26,10 @@ async fn main(spawner: Spawner) {
27 let p = embassy_rp::init(Default::default()); 26 let p = embassy_rp::init(Default::default());
28 let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); 27 let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0);
29 28
30 let tx_buf = &mut make_static!([0u8; 16])[..]; 29 static TX_BUF: StaticCell<[u8; 16]> = StaticCell::new();
31 let rx_buf = &mut make_static!([0u8; 16])[..]; 30 let tx_buf = &mut TX_BUF.init([0; 16])[..];
31 static RX_BUF: StaticCell<[u8; 16]> = StaticCell::new();
32 let rx_buf = &mut RX_BUF.init([0; 16])[..];
32 let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); 33 let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default());
33 let (rx, mut tx) = uart.split(); 34 let (rx, mut tx) = uart.split();
34 35
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
index 42c8b432e..a45f40756 100644
--- a/examples/rp/src/bin/uart_unidir.rs
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -7,7 +7,6 @@
7 7
8#![no_std] 8#![no_std]
9#![no_main] 9#![no_main]
10#![feature(type_alias_impl_trait)]
11 10
12use defmt::*; 11use defmt::*;
13use embassy_executor::Spawner; 12use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index cc63029fb..f1b124efa 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::*; 8use defmt::*;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -17,7 +16,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState
17use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 16use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
18use embassy_usb::{Builder, Config, UsbDevice}; 17use embassy_usb::{Builder, Config, UsbDevice};
19use embedded_io_async::Write; 18use embedded_io_async::Write;
20use static_cell::make_static; 19use static_cell::StaticCell;
21use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
22 21
23bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
@@ -65,14 +64,16 @@ async fn main(spawner: Spawner) {
65 config.device_protocol = 0x01; 64 config.device_protocol = 0x01;
66 65
67 // Create embassy-usb DeviceBuilder using the driver and config. 66 // Create embassy-usb DeviceBuilder using the driver and config.
67 static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new();
68 static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new();
69 static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new();
68 let mut builder = Builder::new( 70 let mut builder = Builder::new(
69 driver, 71 driver,
70 config, 72 config,
71 &mut make_static!([0; 256])[..], 73 &mut CONFIG_DESC.init([0; 256])[..],
72 &mut make_static!([0; 256])[..], 74 &mut BOS_DESC.init([0; 256])[..],
73 &mut make_static!([0; 256])[..],
74 &mut [], // no msos descriptors 75 &mut [], // no msos descriptors
75 &mut make_static!([0; 128])[..], 76 &mut CONTROL_BUF.init([0; 128])[..],
76 ); 77 );
77 78
78 // Our MAC addr. 79 // Our MAC addr.
@@ -81,14 +82,16 @@ async fn main(spawner: Spawner) {
81 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; 82 let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88];
82 83
83 // Create classes on the builder. 84 // Create classes on the builder.
84 let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); 85 static STATE: StaticCell<State> = StaticCell::new();
86 let class = CdcNcmClass::new(&mut builder, STATE.init(State::new()), host_mac_addr, 64);
85 87
86 // Build the builder. 88 // Build the builder.
87 let usb = builder.build(); 89 let usb = builder.build();
88 90
89 unwrap!(spawner.spawn(usb_task(usb))); 91 unwrap!(spawner.spawn(usb_task(usb)));
90 92
91 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(make_static!(NetState::new()), our_mac_addr); 93 static NET_STATE: StaticCell<NetState<MTU, 4, 4>> = StaticCell::new();
94 let (runner, device) = class.into_embassy_net_device::<MTU, 4, 4>(NET_STATE.init(NetState::new()), our_mac_addr);
92 unwrap!(spawner.spawn(usb_ncm_task(runner))); 95 unwrap!(spawner.spawn(usb_ncm_task(runner)));
93 96
94 let config = embassy_net::Config::dhcpv4(Default::default()); 97 let config = embassy_net::Config::dhcpv4(Default::default());
@@ -102,11 +105,13 @@ async fn main(spawner: Spawner) {
102 let seed = 1234; // guaranteed random, chosen by a fair dice roll 105 let seed = 1234; // guaranteed random, chosen by a fair dice roll
103 106
104 // Init network stack 107 // Init network stack
105 let stack = &*make_static!(Stack::new( 108 static STACK: StaticCell<Stack<Device<'static, MTU>>> = StaticCell::new();
109 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
110 let stack = &*STACK.init(Stack::new(
106 device, 111 device,
107 config, 112 config,
108 make_static!(StackResources::<2>::new()), 113 RESOURCES.init(StackResources::<2>::new()),
109 seed 114 seed,
110 )); 115 ));
111 116
112 unwrap!(spawner.spawn(net_task(stack))); 117 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs
index 569c9b12b..710be8d13 100644
--- a/examples/rp/src/bin/usb_hid_keyboard.rs
+++ b/examples/rp/src/bin/usb_hid_keyboard.rs
@@ -1,6 +1,5 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait)]
4 3
5use core::sync::atomic::{AtomicBool, Ordering}; 4use core::sync::atomic::{AtomicBool, Ordering};
6 5
@@ -37,7 +36,6 @@ async fn main(_spawner: Spawner) {
37 36
38 // Create embassy-usb DeviceBuilder using the driver and config. 37 // Create embassy-usb DeviceBuilder using the driver and config.
39 // It needs some buffers for building the descriptors. 38 // It needs some buffers for building the descriptors.
40 let mut device_descriptor = [0; 256];
41 let mut config_descriptor = [0; 256]; 39 let mut config_descriptor = [0; 256];
42 let mut bos_descriptor = [0; 256]; 40 let mut bos_descriptor = [0; 256];
43 // You can also add a Microsoft OS descriptor. 41 // You can also add a Microsoft OS descriptor.
@@ -51,7 +49,6 @@ async fn main(_spawner: Spawner) {
51 let mut builder = Builder::new( 49 let mut builder = Builder::new(
52 driver, 50 driver,
53 config, 51 config,
54 &mut device_descriptor,
55 &mut config_descriptor, 52 &mut config_descriptor,
56 &mut bos_descriptor, 53 &mut bos_descriptor,
57 &mut msos_descriptor, 54 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs
new file mode 100644
index 000000000..e8b399cb1
--- /dev/null
+++ b/examples/rp/src/bin/usb_hid_mouse.rs
@@ -0,0 +1,180 @@
1#![no_std]
2#![no_main]
3
4use core::sync::atomic::{AtomicBool, Ordering};
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_futures::join::join;
9use embassy_rp::bind_interrupts;
10use embassy_rp::clocks::RoscRng;
11use embassy_rp::gpio::{Input, Pull};
12use embassy_rp::peripherals::USB;
13use embassy_rp::usb::{Driver, InterruptHandler};
14use embassy_time::Timer;
15use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
16use embassy_usb::control::OutResponse;
17use embassy_usb::{Builder, Config, Handler};
18use rand::Rng;
19use usbd_hid::descriptor::{MouseReport, SerializedDescriptor};
20use {defmt_rtt as _, panic_probe as _};
21
22bind_interrupts!(struct Irqs {
23 USBCTRL_IRQ => InterruptHandler<USB>;
24});
25
26#[embassy_executor::main]
27async fn main(_spawner: Spawner) {
28 let p = embassy_rp::init(Default::default());
29 // Create the driver, from the HAL.
30 let driver = Driver::new(p.USB, Irqs);
31
32 // Create embassy-usb Config
33 let mut config = Config::new(0xc0de, 0xcafe);
34 config.manufacturer = Some("Embassy");
35 config.product = Some("HID keyboard example");
36 config.serial_number = Some("12345678");
37 config.max_power = 100;
38 config.max_packet_size_0 = 64;
39
40 // Create embassy-usb DeviceBuilder using the driver and config.
41 // It needs some buffers for building the descriptors.
42 let mut config_descriptor = [0; 256];
43 let mut bos_descriptor = [0; 256];
44 // You can also add a Microsoft OS descriptor.
45 let mut msos_descriptor = [0; 256];
46 let mut control_buf = [0; 64];
47 let request_handler = MyRequestHandler {};
48 let mut device_handler = MyDeviceHandler::new();
49
50 let mut state = State::new();
51
52 let mut builder = Builder::new(
53 driver,
54 config,
55 &mut config_descriptor,
56 &mut bos_descriptor,
57 &mut msos_descriptor,
58 &mut control_buf,
59 );
60
61 builder.handler(&mut device_handler);
62
63 // Create classes on the builder.
64 let config = embassy_usb::class::hid::Config {
65 report_descriptor: MouseReport::desc(),
66 request_handler: Some(&request_handler),
67 poll_ms: 60,
68 max_packet_size: 64,
69 };
70 let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
71
72 // Build the builder.
73 let mut usb = builder.build();
74
75 // Run the USB device.
76 let usb_fut = usb.run();
77
78 // Set up the signal pin that will be used to trigger the keyboard.
79 let mut signal_pin = Input::new(p.PIN_16, Pull::None);
80
81 // Enable the schmitt trigger to slightly debounce.
82 signal_pin.set_schmitt(true);
83
84 let (reader, mut writer) = hid.split();
85
86 // Do stuff with the class!
87 let in_fut = async {
88 let mut rng = RoscRng;
89
90 loop {
91 // every 1 second
92 _ = Timer::after_secs(1).await;
93 let report = MouseReport {
94 buttons: 0,
95 x: rng.gen_range(-100..100), // random small x movement
96 y: rng.gen_range(-100..100), // random small y movement
97 wheel: 0,
98 pan: 0,
99 };
100 // Send the report.
101 match writer.write_serialize(&report).await {
102 Ok(()) => {}
103 Err(e) => warn!("Failed to send report: {:?}", e),
104 }
105 }
106 };
107
108 let out_fut = async {
109 reader.run(false, &request_handler).await;
110 };
111
112 // Run everything concurrently.
113 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
114 join(usb_fut, join(in_fut, out_fut)).await;
115}
116
117struct MyRequestHandler {}
118
119impl RequestHandler for MyRequestHandler {
120 fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option<usize> {
121 info!("Get report for {:?}", id);
122 None
123 }
124
125 fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse {
126 info!("Set report for {:?}: {=[u8]}", id, data);
127 OutResponse::Accepted
128 }
129
130 fn set_idle_ms(&self, id: Option<ReportId>, dur: u32) {
131 info!("Set idle rate for {:?} to {:?}", id, dur);
132 }
133
134 fn get_idle_ms(&self, id: Option<ReportId>) -> Option<u32> {
135 info!("Get idle rate for {:?}", id);
136 None
137 }
138}
139
140struct MyDeviceHandler {
141 configured: AtomicBool,
142}
143
144impl MyDeviceHandler {
145 fn new() -> Self {
146 MyDeviceHandler {
147 configured: AtomicBool::new(false),
148 }
149 }
150}
151
152impl Handler for MyDeviceHandler {
153 fn enabled(&mut self, enabled: bool) {
154 self.configured.store(false, Ordering::Relaxed);
155 if enabled {
156 info!("Device enabled");
157 } else {
158 info!("Device disabled");
159 }
160 }
161
162 fn reset(&mut self) {
163 self.configured.store(false, Ordering::Relaxed);
164 info!("Bus reset, the Vbus current limit is 100mA");
165 }
166
167 fn addressed(&mut self, addr: u8) {
168 self.configured.store(false, Ordering::Relaxed);
169 info!("USB address set to: {}", addr);
170 }
171
172 fn configured(&mut self, configured: bool) {
173 self.configured.store(configured, Ordering::Relaxed);
174 if configured {
175 info!("Device configured, it may now draw up to the configured current limit from Vbus.")
176 } else {
177 info!("Device is no longer configured, the Vbus current limit is 100mA.");
178 }
179 }
180}
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs
index 791f15e56..af401ed63 100644
--- a/examples/rp/src/bin/usb_logger.rs
+++ b/examples/rp/src/bin/usb_logger.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use embassy_executor::Spawner; 8use embassy_executor::Spawner;
10use embassy_rp::bind_interrupts; 9use embassy_rp::bind_interrupts;
diff --git a/examples/rp/src/bin/usb_midi.rs b/examples/rp/src/bin/usb_midi.rs
index d5cdae319..11db1b2e1 100644
--- a/examples/rp/src/bin/usb_midi.rs
+++ b/examples/rp/src/bin/usb_midi.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::{info, panic}; 8use defmt::{info, panic};
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -47,7 +46,6 @@ async fn main(_spawner: Spawner) {
47 46
48 // Create embassy-usb DeviceBuilder using the driver and config. 47 // Create embassy-usb DeviceBuilder using the driver and config.
49 // It needs some buffers for building the descriptors. 48 // It needs some buffers for building the descriptors.
50 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256]; 49 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256]; 50 let mut bos_descriptor = [0; 256];
53 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
@@ -55,7 +53,6 @@ async fn main(_spawner: Spawner) {
55 let mut builder = Builder::new( 53 let mut builder = Builder::new(
56 driver, 54 driver,
57 config, 55 config,
58 &mut device_descriptor,
59 &mut config_descriptor, 56 &mut config_descriptor,
60 &mut bos_descriptor, 57 &mut bos_descriptor,
61 &mut [], // no msos descriptors 58 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/usb_raw.rs b/examples/rp/src/bin/usb_raw.rs
index f59262e5c..97e7e0244 100644
--- a/examples/rp/src/bin/usb_raw.rs
+++ b/examples/rp/src/bin/usb_raw.rs
@@ -48,7 +48,6 @@
48 48
49#![no_std] 49#![no_std]
50#![no_main] 50#![no_main]
51#![feature(type_alias_impl_trait)]
52 51
53use defmt::info; 52use defmt::info;
54use embassy_executor::Spawner; 53use embassy_executor::Spawner;
@@ -94,7 +93,6 @@ async fn main(_spawner: Spawner) {
94 93
95 // Create embassy-usb DeviceBuilder using the driver and config. 94 // Create embassy-usb DeviceBuilder using the driver and config.
96 // It needs some buffers for building the descriptors. 95 // It needs some buffers for building the descriptors.
97 let mut device_descriptor = [0; 256];
98 let mut config_descriptor = [0; 256]; 96 let mut config_descriptor = [0; 256];
99 let mut bos_descriptor = [0; 256]; 97 let mut bos_descriptor = [0; 256];
100 let mut msos_descriptor = [0; 256]; 98 let mut msos_descriptor = [0; 256];
@@ -107,7 +105,6 @@ async fn main(_spawner: Spawner) {
107 let mut builder = Builder::new( 105 let mut builder = Builder::new(
108 driver, 106 driver,
109 config, 107 config,
110 &mut device_descriptor,
111 &mut config_descriptor, 108 &mut config_descriptor,
112 &mut bos_descriptor, 109 &mut bos_descriptor,
113 &mut msos_descriptor, 110 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs
index 288be5a4e..331c3da4c 100644
--- a/examples/rp/src/bin/usb_raw_bulk.rs
+++ b/examples/rp/src/bin/usb_raw_bulk.rs
@@ -26,7 +26,6 @@
26 26
27#![no_std] 27#![no_std]
28#![no_main] 28#![no_main]
29#![feature(type_alias_impl_trait)]
30 29
31use defmt::info; 30use defmt::info;
32use embassy_executor::Spawner; 31use embassy_executor::Spawner;
@@ -72,7 +71,6 @@ async fn main(_spawner: Spawner) {
72 71
73 // Create embassy-usb DeviceBuilder using the driver and config. 72 // Create embassy-usb DeviceBuilder using the driver and config.
74 // It needs some buffers for building the descriptors. 73 // It needs some buffers for building the descriptors.
75 let mut device_descriptor = [0; 256];
76 let mut config_descriptor = [0; 256]; 74 let mut config_descriptor = [0; 256];
77 let mut bos_descriptor = [0; 256]; 75 let mut bos_descriptor = [0; 256];
78 let mut msos_descriptor = [0; 256]; 76 let mut msos_descriptor = [0; 256];
@@ -81,7 +79,6 @@ async fn main(_spawner: Spawner) {
81 let mut builder = Builder::new( 79 let mut builder = Builder::new(
82 driver, 80 driver,
83 config, 81 config,
84 &mut device_descriptor,
85 &mut config_descriptor, 82 &mut config_descriptor,
86 &mut bos_descriptor, 83 &mut bos_descriptor,
87 &mut msos_descriptor, 84 &mut msos_descriptor,
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index 30347d920..3c9bc96dd 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::{info, panic}; 8use defmt::{info, panic};
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
@@ -47,7 +46,6 @@ async fn main(_spawner: Spawner) {
47 46
48 // Create embassy-usb DeviceBuilder using the driver and config. 47 // Create embassy-usb DeviceBuilder using the driver and config.
49 // It needs some buffers for building the descriptors. 48 // It needs some buffers for building the descriptors.
50 let mut device_descriptor = [0; 256];
51 let mut config_descriptor = [0; 256]; 49 let mut config_descriptor = [0; 256];
52 let mut bos_descriptor = [0; 256]; 50 let mut bos_descriptor = [0; 256];
53 let mut control_buf = [0; 64]; 51 let mut control_buf = [0; 64];
@@ -57,7 +55,6 @@ async fn main(_spawner: Spawner) {
57 let mut builder = Builder::new( 55 let mut builder = Builder::new(
58 driver, 56 driver,
59 config, 57 config,
60 &mut device_descriptor,
61 &mut config_descriptor, 58 &mut config_descriptor,
62 &mut bos_descriptor, 59 &mut bos_descriptor,
63 &mut [], // no msos descriptors 60 &mut [], // no msos descriptors
diff --git a/examples/rp/src/bin/usb_serial_with_logger.rs b/examples/rp/src/bin/usb_serial_with_logger.rs
new file mode 100644
index 000000000..f9cfdef94
--- /dev/null
+++ b/examples/rp/src/bin/usb_serial_with_logger.rs
@@ -0,0 +1,115 @@
1//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip as well as how to create multiple usb classes for one device
2//!
3//! This creates a USB serial port that echos. It will also print out logging information on a separate serial device
4
5#![no_std]
6#![no_main]
7
8use defmt::{info, panic};
9use embassy_executor::Spawner;
10use embassy_futures::join::join;
11use embassy_rp::bind_interrupts;
12use embassy_rp::peripherals::USB;
13use embassy_rp::usb::{Driver, Instance, InterruptHandler};
14use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
15use embassy_usb::driver::EndpointError;
16use embassy_usb::{Builder, Config};
17use {defmt_rtt as _, panic_probe as _};
18
19bind_interrupts!(struct Irqs {
20 USBCTRL_IRQ => InterruptHandler<USB>;
21});
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) {
25 info!("Hello there!");
26
27 let p = embassy_rp::init(Default::default());
28
29 // Create the driver, from the HAL.
30 let driver = Driver::new(p.USB, Irqs);
31
32 // Create embassy-usb Config
33 let mut config = Config::new(0xc0de, 0xcafe);
34 config.manufacturer = Some("Embassy");
35 config.product = Some("USB-serial example");
36 config.serial_number = Some("12345678");
37 config.max_power = 100;
38 config.max_packet_size_0 = 64;
39
40 // Required for windows compatibility.
41 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
42 config.device_class = 0xEF;
43 config.device_sub_class = 0x02;
44 config.device_protocol = 0x01;
45 config.composite_with_iads = true;
46
47 // Create embassy-usb DeviceBuilder using the driver and config.
48 // It needs some buffers for building the descriptors.
49 let mut config_descriptor = [0; 256];
50 let mut bos_descriptor = [0; 256];
51 let mut control_buf = [0; 64];
52
53 let mut state = State::new();
54 let mut logger_state = State::new();
55
56 let mut builder = Builder::new(
57 driver,
58 config,
59 &mut config_descriptor,
60 &mut bos_descriptor,
61 &mut [], // no msos descriptors
62 &mut control_buf,
63 );
64
65 // Create classes on the builder.
66 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
67
68 // Create a class for the logger
69 let logger_class = CdcAcmClass::new(&mut builder, &mut logger_state, 64);
70
71 // Creates the logger and returns the logger future
72 // Note: You'll need to use log::info! afterwards instead of info! for this to work (this also applies to all the other log::* macros)
73 let log_fut = embassy_usb_logger::with_class!(1024, log::LevelFilter::Info, logger_class);
74
75 // Build the builder.
76 let mut usb = builder.build();
77
78 // Run the USB device.
79 let usb_fut = usb.run();
80
81 // Do stuff with the class!
82 let echo_fut = async {
83 loop {
84 class.wait_connection().await;
85 log::info!("Connected");
86 let _ = echo(&mut class).await;
87 log::info!("Disconnected");
88 }
89 };
90
91 // Run everything concurrently.
92 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
93 join(usb_fut, join(echo_fut, log_fut)).await;
94}
95
96struct Disconnected {}
97
98impl From<EndpointError> for Disconnected {
99 fn from(val: EndpointError) -> Self {
100 match val {
101 EndpointError::BufferOverflow => panic!("Buffer overflow"),
102 EndpointError::Disabled => Disconnected {},
103 }
104 }
105}
106
107async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
108 let mut buf = [0; 64];
109 loop {
110 let n = class.read_packet(&mut buf).await?;
111 let data = &buf[..n];
112 info!("data: {:x}", data);
113 class.write_packet(data).await?;
114 }
115}
diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs
index b6af518af..b9d4ef22f 100644
--- a/examples/rp/src/bin/watchdog.rs
+++ b/examples/rp/src/bin/watchdog.rs
@@ -4,7 +4,6 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use defmt::info; 8use defmt::info;
10use embassy_executor::Spawner; 9use embassy_executor::Spawner;
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs
index ad1fa6462..b60852359 100644
--- a/examples/rp/src/bin/wifi_ap_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7#![allow(async_fn_in_trait)] 6#![allow(async_fn_in_trait)]
8 7
9use core::str::from_utf8; 8use core::str::from_utf8;
@@ -15,11 +14,11 @@ use embassy_net::tcp::TcpSocket;
15use embassy_net::{Config, Stack, StackResources}; 14use embassy_net::{Config, Stack, StackResources};
16use embassy_rp::bind_interrupts; 15use embassy_rp::bind_interrupts;
17use embassy_rp::gpio::{Level, Output}; 16use embassy_rp::gpio::{Level, Output};
18use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 17use embassy_rp::peripherals::{DMA_CH0, PIO0};
19use embassy_rp::pio::{InterruptHandler, Pio}; 18use embassy_rp::pio::{InterruptHandler, Pio};
20use embassy_time::Duration; 19use embassy_time::Duration;
21use embedded_io_async::Write; 20use embedded_io_async::Write;
22use static_cell::make_static; 21use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
25bind_interrupts!(struct Irqs { 24bind_interrupts!(struct Irqs {
@@ -27,9 +26,7 @@ bind_interrupts!(struct Irqs {
27}); 26});
28 27
29#[embassy_executor::task] 28#[embassy_executor::task]
30async fn wifi_task( 29async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! {
31 runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>,
32) -> ! {
33 runner.run().await 30 runner.run().await
34} 31}
35 32
@@ -59,7 +56,8 @@ async fn main(spawner: Spawner) {
59 let mut pio = Pio::new(p.PIO0, Irqs); 56 let mut pio = Pio::new(p.PIO0, Irqs);
60 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 57 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
61 58
62 let state = make_static!(cyw43::State::new()); 59 static STATE: StaticCell<cyw43::State> = StaticCell::new();
60 let state = STATE.init(cyw43::State::new());
63 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 61 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
64 unwrap!(spawner.spawn(wifi_task(runner))); 62 unwrap!(spawner.spawn(wifi_task(runner)));
65 63
@@ -79,11 +77,13 @@ async fn main(spawner: Spawner) {
79 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. 77 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
80 78
81 // Init network stack 79 // Init network stack
82 let stack = &*make_static!(Stack::new( 80 static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new();
81 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
82 let stack = &*STACK.init(Stack::new(
83 net_device, 83 net_device,
84 config, 84 config,
85 make_static!(StackResources::<2>::new()), 85 RESOURCES.init(StackResources::<2>::new()),
86 seed 86 seed,
87 )); 87 ));
88 88
89 unwrap!(spawner.spawn(net_task(stack))); 89 unwrap!(spawner.spawn(net_task(stack)));
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs
index 14ace74e9..18eefe41f 100644
--- a/examples/rp/src/bin/wifi_blinky.rs
+++ b/examples/rp/src/bin/wifi_blinky.rs
@@ -4,17 +4,16 @@
4 4
5#![no_std] 5#![no_std]
6#![no_main] 6#![no_main]
7#![feature(type_alias_impl_trait)]
8 7
9use cyw43_pio::PioSpi; 8use cyw43_pio::PioSpi;
10use defmt::*; 9use defmt::*;
11use embassy_executor::Spawner; 10use embassy_executor::Spawner;
12use embassy_rp::bind_interrupts; 11use embassy_rp::bind_interrupts;
13use embassy_rp::gpio::{Level, Output}; 12use embassy_rp::gpio::{Level, Output};
14use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 13use embassy_rp::peripherals::{DMA_CH0, PIO0};
15use embassy_rp::pio::{InterruptHandler, Pio}; 14use embassy_rp::pio::{InterruptHandler, Pio};
16use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
17use static_cell::make_static; 16use static_cell::StaticCell;
18use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
19 18
20bind_interrupts!(struct Irqs { 19bind_interrupts!(struct Irqs {
@@ -22,9 +21,7 @@ bind_interrupts!(struct Irqs {
22}); 21});
23 22
24#[embassy_executor::task] 23#[embassy_executor::task]
25async fn wifi_task( 24async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! {
26 runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>,
27) -> ! {
28 runner.run().await 25 runner.run().await
29} 26}
30 27
@@ -46,7 +43,8 @@ async fn main(spawner: Spawner) {
46 let mut pio = Pio::new(p.PIO0, Irqs); 43 let mut pio = Pio::new(p.PIO0, Irqs);
47 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 44 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
48 45
49 let state = make_static!(cyw43::State::new()); 46 static STATE: StaticCell<cyw43::State> = StaticCell::new();
47 let state = STATE.init(cyw43::State::new());
50 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 48 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
51 unwrap!(spawner.spawn(wifi_task(runner))); 49 unwrap!(spawner.spawn(wifi_task(runner)));
52 50
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs
index 7adf52b88..e0f85a6b0 100644
--- a/examples/rp/src/bin/wifi_scan.rs
+++ b/examples/rp/src/bin/wifi_scan.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7#![allow(async_fn_in_trait)] 6#![allow(async_fn_in_trait)]
8 7
9use core::str; 8use core::str;
@@ -14,9 +13,9 @@ use embassy_executor::Spawner;
14use embassy_net::Stack; 13use embassy_net::Stack;
15use embassy_rp::bind_interrupts; 14use embassy_rp::bind_interrupts;
16use embassy_rp::gpio::{Level, Output}; 15use embassy_rp::gpio::{Level, Output};
17use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 16use embassy_rp::peripherals::{DMA_CH0, PIO0};
18use embassy_rp::pio::{InterruptHandler, Pio}; 17use embassy_rp::pio::{InterruptHandler, Pio};
19use static_cell::make_static; 18use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
21 20
22bind_interrupts!(struct Irqs { 21bind_interrupts!(struct Irqs {
@@ -24,9 +23,7 @@ bind_interrupts!(struct Irqs {
24}); 23});
25 24
26#[embassy_executor::task] 25#[embassy_executor::task]
27async fn wifi_task( 26async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! {
28 runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>,
29) -> ! {
30 runner.run().await 27 runner.run().await
31} 28}
32 29
@@ -56,7 +53,8 @@ async fn main(spawner: Spawner) {
56 let mut pio = Pio::new(p.PIO0, Irqs); 53 let mut pio = Pio::new(p.PIO0, Irqs);
57 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 54 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
58 55
59 let state = make_static!(cyw43::State::new()); 56 static STATE: StaticCell<cyw43::State> = StaticCell::new();
57 let state = STATE.init(cyw43::State::new());
60 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 58 let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
61 unwrap!(spawner.spawn(wifi_task(runner))); 59 unwrap!(spawner.spawn(wifi_task(runner)));
62 60
@@ -65,7 +63,7 @@ async fn main(spawner: Spawner) {
65 .set_power_management(cyw43::PowerManagementMode::PowerSave) 63 .set_power_management(cyw43::PowerManagementMode::PowerSave)
66 .await; 64 .await;
67 65
68 let mut scanner = control.scan().await; 66 let mut scanner = control.scan(Default::default()).await;
69 while let Some(bss) = scanner.next().await { 67 while let Some(bss) = scanner.next().await {
70 if let Ok(ssid_str) = str::from_utf8(&bss.ssid) { 68 if let Ok(ssid_str) = str::from_utf8(&bss.ssid) {
71 info!("scanned {} == {:x}", ssid_str, bss.bssid); 69 info!("scanned {} == {:x}", ssid_str, bss.bssid);
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs
index ec6b4ee74..f1afc4a00 100644
--- a/examples/rp/src/bin/wifi_tcp_server.rs
+++ b/examples/rp/src/bin/wifi_tcp_server.rs
@@ -3,7 +3,6 @@
3 3
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![feature(type_alias_impl_trait)]
7#![allow(async_fn_in_trait)] 6#![allow(async_fn_in_trait)]
8 7
9use core::str::from_utf8; 8use core::str::from_utf8;
@@ -15,11 +14,11 @@ use embassy_net::tcp::TcpSocket;
15use embassy_net::{Config, Stack, StackResources}; 14use embassy_net::{Config, Stack, StackResources};
16use embassy_rp::bind_interrupts; 15use embassy_rp::bind_interrupts;
17use embassy_rp::gpio::{Level, Output}; 16use embassy_rp::gpio::{Level, Output};
18use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; 17use embassy_rp::peripherals::{DMA_CH0, PIO0};
19use embassy_rp::pio::{InterruptHandler, Pio}; 18use embassy_rp::pio::{InterruptHandler, Pio};
20use embassy_time::{Duration, Timer}; 19use embassy_time::{Duration, Timer};
21use embedded_io_async::Write; 20use embedded_io_async::Write;
22use static_cell::make_static; 21use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
24 23
25bind_interrupts!(struct Irqs { 24bind_interrupts!(struct Irqs {
@@ -30,9 +29,7 @@ const WIFI_NETWORK: &str = "EmbassyTest";
30const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; 29const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud";
31 30
32#[embassy_executor::task] 31#[embassy_executor::task]
33async fn wifi_task( 32async fn wifi_task(runner: cyw43::Runner<'static, Output<'static>, PioSpi<'static, PIO0, 0, DMA_CH0>>) -> ! {
34 runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>,
35) -> ! {
36 runner.run().await 33 runner.run().await
37} 34}
38 35
@@ -62,7 +59,8 @@ async fn main(spawner: Spawner) {
62 let mut pio = Pio::new(p.PIO0, Irqs); 59 let mut pio = Pio::new(p.PIO0, Irqs);
63 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); 60 let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0);
64 61
65 let state = make_static!(cyw43::State::new()); 62 static STATE: StaticCell<cyw43::State> = StaticCell::new();
63 let state = STATE.init(cyw43::State::new());
66 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; 64 let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await;
67 unwrap!(spawner.spawn(wifi_task(runner))); 65 unwrap!(spawner.spawn(wifi_task(runner)));
68 66
@@ -82,11 +80,13 @@ async fn main(spawner: Spawner) {
82 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. 80 let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random.
83 81
84 // Init network stack 82 // Init network stack
85 let stack = &*make_static!(Stack::new( 83 static STACK: StaticCell<Stack<cyw43::NetDriver<'static>>> = StaticCell::new();
84 static RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
85 let stack = &*STACK.init(Stack::new(
86 net_device, 86 net_device,
87 config, 87 config,
88 make_static!(StackResources::<2>::new()), 88 RESOURCES.init(StackResources::<2>::new()),
89 seed 89 seed,
90 )); 90 ));
91 91
92 unwrap!(spawner.spawn(net_task(stack))); 92 unwrap!(spawner.spawn(net_task(stack)));