From a29972413bcfb30e6e28766491229c6ac38eed22 Mon Sep 17 00:00:00 2001 From: Mathias Date: Fri, 19 Aug 2022 08:48:52 +0200 Subject: Fix uart rp2040 blocking example --- examples/rp/src/bin/uart.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs index c63b31cae..05177a6b4 100644 --- a/examples/rp/src/bin/uart.rs +++ b/examples/rp/src/bin/uart.rs @@ -10,7 +10,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let config = uart::Config::default(); - let mut uart = uart::Uart::new_with_rtscts(p.UART0, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, config); + let mut uart = uart::Uart::new_with_rtscts_blocking(p.UART0, p.PIN_0, p.PIN_1, p.PIN_3, p.PIN_2, config); uart.blocking_write("Hello World!\r\n".as_bytes()).unwrap(); loop { -- cgit From a730e2cd0f4f282a78cc5d9897c584ec4f5a44a3 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 24 Aug 2022 23:46:07 +0200 Subject: rp: add usb device support. --- examples/rp/src/bin/usb_ethernet.rs | 264 ++++++++++++++++++++++++++++++++++++ examples/rp/src/bin/usb_serial.rs | 103 ++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 examples/rp/src/bin/usb_ethernet.rs create mode 100644 examples/rp/src/bin/usb_serial.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs new file mode 100644 index 000000000..2cb0010f1 --- /dev/null +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -0,0 +1,264 @@ +#![no_std] +#![no_main] +#![feature(generic_associated_types)] +#![feature(type_alias_impl_trait)] + +use core::sync::atomic::{AtomicBool, Ordering}; +use core::task::Waker; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_net::tcp::TcpSocket; +use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources}; +use embassy_rp::usb::Driver; +use embassy_rp::{interrupt, peripherals}; +use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; +use embassy_sync::channel::Channel; +use embassy_usb::{Builder, Config, UsbDevice}; +use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; +use embedded_io::asynch::{Read, Write}; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +type MyDriver = Driver<'static, peripherals::USB>; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + STATIC_CELL.init_with(move || $val) + }}; +} + +#[embassy_executor::task] +async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { + device.run().await +} + +#[embassy_executor::task] +async fn usb_ncm_rx_task(mut class: Receiver<'static, MyDriver>) { + loop { + warn!("WAITING for connection"); + LINK_UP.store(false, Ordering::Relaxed); + + class.wait_connection().await.unwrap(); + + warn!("Connected"); + LINK_UP.store(true, Ordering::Relaxed); + + loop { + let mut p = unwrap!(PacketBox::new(embassy_net::Packet::new())); + let n = match class.read_packet(&mut p[..]).await { + Ok(n) => n, + Err(e) => { + warn!("error reading packet: {:?}", e); + break; + } + }; + + let buf = p.slice(0..n); + if RX_CHANNEL.try_send(buf).is_err() { + warn!("Failed pushing rx'd packet to channel."); + } + } + } +} + +#[embassy_executor::task] +async fn usb_ncm_tx_task(mut class: Sender<'static, MyDriver>) { + loop { + let pkt = TX_CHANNEL.recv().await; + if let Err(e) = class.write_packet(&pkt[..]).await { + warn!("Failed to TX packet: {:?}", e); + } + } +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + // Create the driver, from the HAL. + let irq = interrupt::take!(USBCTRL_IRQ); + let driver = Driver::new(p.USB, irq); + + // Create embassy-usb Config + let mut config = Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-Ethernet example"); + config.serial_number = Some("12345678"); + config.max_power = 100; + config.max_packet_size_0 = 64; + + // Required for Windows support. + config.composite_with_iads = true; + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + + struct Resources { + device_descriptor: [u8; 256], + config_descriptor: [u8; 256], + bos_descriptor: [u8; 256], + control_buf: [u8; 128], + serial_state: State<'static>, + } + let res: &mut Resources = singleton!(Resources { + device_descriptor: [0; 256], + config_descriptor: [0; 256], + bos_descriptor: [0; 256], + control_buf: [0; 128], + serial_state: State::new(), + }); + + // Create embassy-usb DeviceBuilder using the driver and config. + let mut builder = Builder::new( + driver, + config, + &mut res.device_descriptor, + &mut res.config_descriptor, + &mut res.bos_descriptor, + &mut res.control_buf, + None, + ); + + // WARNINGS for Android ethernet tethering: + // - On Pixel 4a, it refused to work on Android 11, worked on Android 12. + // - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte), + // it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled. + // This is due to regex spaghetti: https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-12.0.0_r84/core/res/res/values/config.xml#417 + // and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757 + + // Our MAC addr. + let our_mac_addr = [0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC]; + // Host's MAC addr. This is the MAC the host "thinks" its USB-to-ethernet adapter has. + let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; + + // Create classes on the builder. + let class = CdcNcmClass::new(&mut builder, &mut res.serial_state, host_mac_addr, 64); + + // Build the builder. + let usb = builder.build(); + + unwrap!(spawner.spawn(usb_task(usb))); + + let (tx, rx) = class.split(); + unwrap!(spawner.spawn(usb_ncm_rx_task(rx))); + unwrap!(spawner.spawn(usb_ncm_tx_task(tx))); + + let config = embassy_net::ConfigStrategy::Dhcp; + //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { + // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), + // dns_servers: Vec::new(), + // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), + //}); + + // Generate random seed + let seed = 1234; // guaranteed random, chosen by a fair dice roll + + // Init network stack + let device = Device { mac_addr: our_mac_addr }; + let stack = &*singleton!(Stack::new( + device, + config, + singleton!(StackResources::<1, 2, 8>::new()), + seed + )); + + unwrap!(spawner.spawn(net_task(stack))); + + // And now we can use it! + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + + loop { + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + + info!("Received connection from {:?}", socket.remote_endpoint()); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("read error: {:?}", e); + break; + } + }; + + info!("rxd {:02x}", &buf[..n]); + + match socket.write_all(&buf[..n]).await { + Ok(()) => {} + Err(e) => { + warn!("write error: {:?}", e); + break; + } + }; + } + } +} + +static TX_CHANNEL: Channel = Channel::new(); +static RX_CHANNEL: Channel = Channel::new(); +static LINK_UP: AtomicBool = AtomicBool::new(false); + +struct Device { + mac_addr: [u8; 6], +} + +impl embassy_net::Device for Device { + fn register_waker(&mut self, waker: &Waker) { + // loopy loopy wakey wakey + waker.wake_by_ref() + } + + fn link_state(&mut self) -> embassy_net::LinkState { + match LINK_UP.load(Ordering::Relaxed) { + true => embassy_net::LinkState::Up, + false => embassy_net::LinkState::Down, + } + } + + fn capabilities(&self) -> embassy_net::DeviceCapabilities { + let mut caps = embassy_net::DeviceCapabilities::default(); + caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header + caps.medium = embassy_net::Medium::Ethernet; + caps + } + + fn is_transmit_ready(&mut self) -> bool { + true + } + + fn transmit(&mut self, pkt: PacketBuf) { + if TX_CHANNEL.try_send(pkt).is_err() { + warn!("TX failed") + } + } + + fn receive<'a>(&mut self) -> Option { + RX_CHANNEL.try_recv().ok() + } + + fn ethernet_address(&self) -> [u8; 6] { + self.mac_addr + } +} diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs new file mode 100644 index 000000000..74be1f598 --- /dev/null +++ b/examples/rp/src/bin/usb_serial.rs @@ -0,0 +1,103 @@ +#![no_std] +#![no_main] +#![feature(generic_associated_types)] +#![feature(type_alias_impl_trait)] + +use defmt::{info, panic}; +use embassy_executor::Spawner; +use embassy_rp::interrupt; +use embassy_rp::usb::{Driver, Instance}; +use embassy_usb::driver::EndpointError; +use embassy_usb::{Builder, Config}; +use embassy_usb_serial::{CdcAcmClass, State}; +use futures::future::join; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello there!"); + + let p = embassy_rp::init(Default::default()); + + // Create the driver, from the HAL. + let irq = interrupt::take!(USBCTRL_IRQ); + let driver = Driver::new(p.USB, 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 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 control_buf, + None, + ); + + // Create classes on the builder. + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Do stuff with the class! + let echo_fut = async { + 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 for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> 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?; + } +} -- cgit From 464ae67108c74efe38326b6ac8fedd29857e9412 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 30 Aug 2022 19:25:36 +0200 Subject: net: feature-gate nightly-only async traits to allow building on stable. --- examples/rp/src/bin/usb_ethernet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 2cb0010f1..2df7f62f6 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -16,7 +16,7 @@ use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; use embassy_usb::{Builder, Config, UsbDevice}; use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; -use embedded_io::asynch::{Read, Write}; +use embedded_io::asynch::Write; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; -- cgit From 07c64d902e001ab0943382e9da35f9280a5533d0 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 30 Aug 2022 00:30:47 +0200 Subject: example --- examples/rp/src/bin/spi.rs | 4 ++-- examples/rp/src/bin/spi_async.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 examples/rp/src/bin/spi_async.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index 88003ee17..e50297ae4 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::Spi; +use embassy_rp::spi::{Blocking, Spi}; use embassy_rp::{gpio, spi}; use gpio::{Level, Output}; use {defmt_rtt as _, panic_probe as _}; @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { // create SPI let mut config = spi::Config::default(); config.frequency = 2_000_000; - let mut spi = Spi::new(p.SPI1, clk, mosi, miso, config); + let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); // Configure CS let mut cs = Output::new(touch_cs, Level::Low); diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs new file mode 100644 index 000000000..f21377ede --- /dev/null +++ b/examples/rp/src/bin/spi_async.rs @@ -0,0 +1,31 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::spi::{Async, Spi}; +use embassy_rp::{gpio, spi}; +use embassy_time::{Duration, Timer}; +use gpio::{Level, Output}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let miso = p.PIN_12; + let mosi = p.PIN_11; + let clk = p.PIN_10; + + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, spi::Config::default()); + + loop { + let tx_buf = [1_u8, 2, 3, 4, 5, 6]; + let mut rx_buf = [0_u8; 6]; + spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); + info!("{:?}", rx_buf); + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From 44150c483017c18979e58d8557aac3df031ba47a Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 30 Aug 2022 01:18:28 +0200 Subject: impl embedded-hal-async --- examples/rp/src/bin/spi_async.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index f21377ede..359ad50e7 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -4,10 +4,8 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::{Async, Spi}; -use embassy_rp::{gpio, spi}; +use embassy_rp::spi::{Async, Config, Spi}; use embassy_time::{Duration, Timer}; -use gpio::{Level, Output}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -19,7 +17,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_11; let clk = p.PIN_10; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, spi::Config::default()); + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; -- cgit From c8ecc557109bd14bea0564e4a1505a26947e1851 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 30 Aug 2022 01:39:08 +0200 Subject: Fix example --- examples/rp/src/bin/spi_display.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index f0e54d87f..d0fbd6847 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{Level, Output}; use embassy_rp::spi; -use embassy_rp::spi::Spi; +use embassy_rp::spi::{Spi, Blocking}; use embassy_time::Delay; use embedded_graphics::image::{Image, ImageRawLE}; use embedded_graphics::mono_font::ascii::FONT_10X20; @@ -48,7 +48,8 @@ async fn main(_spawner: Spawner) { config.phase = spi::Phase::CaptureOnSecondTransition; config.polarity = spi::Polarity::IdleHigh; - let spi_bus = RefCell::new(Spi::new(p.SPI1, clk, mosi, miso, config)); + let spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); + let spi_bus = RefCell::new(spi); let display_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(display_cs, Level::High)); let touch_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(touch_cs, Level::High)); -- cgit From 6d347af9fae3a9c594e13900796ec57537c402e6 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 30 Aug 2022 06:50:58 +0200 Subject: transfer_in_place --- examples/rp/src/bin/spi_display.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index d0fbd6847..23cd4355e 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{Level, Output}; use embassy_rp::spi; -use embassy_rp::spi::{Spi, Blocking}; +use embassy_rp::spi::{Blocking, Spi}; use embassy_time::Delay; use embedded_graphics::image::{Image, ImageRawLE}; use embedded_graphics::mono_font::ascii::FONT_10X20; -- cgit From 99dd2a9386c83f4e625f4c849c8b5e519e12a87c Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 30 Aug 2022 22:55:53 +0200 Subject: Reorder args --- examples/rp/src/bin/spi_async.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index 359ad50e7..b2df0dd11 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_11; let clk = p.PIN_10; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, Config::default()); + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; -- cgit From 9ff5c507741cfadc8a1fc125a353d8438433494f Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Wed, 31 Aug 2022 22:28:47 +0200 Subject: Cleanup examples --- examples/rp/src/bin/spi.rs | 4 ++-- examples/rp/src/bin/spi_async.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index e50297ae4..a830a17a2 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::{Blocking, Spi}; +use embassy_rp::spi::Spi; use embassy_rp::{gpio, spi}; use gpio::{Level, Output}; use {defmt_rtt as _, panic_probe as _}; @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { // create SPI let mut config = spi::Config::default(); config.frequency = 2_000_000; - let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); + let mut spi = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); // Configure CS let mut cs = Output::new(touch_cs, Level::Low); diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index b2df0dd11..671a9caaf 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::{Async, Config, Spi}; +use embassy_rp::spi::{Config, Spi}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_11; let clk = p.PIN_10; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + let mut spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; -- cgit From 897b72c872183221e088611aa6f30989800afd2b Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 22 Sep 2022 16:28:56 +0200 Subject: Update Rust nightly. Removes feature(generic_associated_types) --- examples/rp/src/bin/usb_ethernet.rs | 1 - examples/rp/src/bin/usb_serial.rs | 1 - 2 files changed, 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 2df7f62f6..166ffe175 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -1,6 +1,5 @@ #![no_std] #![no_main] -#![feature(generic_associated_types)] #![feature(type_alias_impl_trait)] use core::sync::atomic::{AtomicBool, Ordering}; diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 74be1f598..00cf3e93f 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -1,6 +1,5 @@ #![no_std] #![no_main] -#![feature(generic_associated_types)] #![feature(type_alias_impl_trait)] use defmt::{info, panic}; -- cgit From 10d1ad2343825388277dc54db649c9349a0b6de8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 22 Sep 2022 16:48:35 +0200 Subject: Replace futures::future::join -> embassy_futures::join::join. --- examples/rp/src/bin/usb_serial.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 00cf3e93f..bf92a1636 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -4,12 +4,12 @@ use defmt::{info, panic}; use embassy_executor::Spawner; +use embassy_futures::join::join; use embassy_rp::interrupt; use embassy_rp::usb::{Driver, Instance}; use embassy_usb::driver::EndpointError; use embassy_usb::{Builder, Config}; use embassy_usb_serial::{CdcAcmClass, State}; -use futures::future::join; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] -- cgit From f27a47a37b59bf3b9079f4d4d5f43caf7b7872f8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 26 Sep 2022 13:00:21 +0200 Subject: usb: move classes into the `embassy-usb` crate. --- examples/rp/src/bin/usb_ethernet.rs | 2 +- examples/rp/src/bin/usb_serial.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 166ffe175..1057fe7fd 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -13,8 +13,8 @@ use embassy_rp::usb::Driver; use embassy_rp::{interrupt, peripherals}; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::channel::Channel; +use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; use embassy_usb::{Builder, Config, UsbDevice}; -use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; use embedded_io::asynch::Write; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index bf92a1636..b7d6493b4 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -7,9 +7,9 @@ use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_rp::interrupt; use embassy_rp::usb::{Driver, Instance}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::{Builder, Config}; -use embassy_usb_serial::{CdcAcmClass, State}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] -- cgit From 72c2e985bb481fbc2e138a8e98b9dbb27878f370 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 29 Sep 2022 11:02:43 +0200 Subject: Update embedded-hal versions and explicitly pin --- examples/rp/src/bin/spi_display.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 23cd4355e..778cad3fa 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -108,9 +108,9 @@ mod shared_spi { use core::cell::RefCell; use core::fmt::Debug; - use embedded_hal_1::digital::blocking::OutputPin; + use embedded_hal_1::digital::OutputPin; use embedded_hal_1::spi; - use embedded_hal_1::spi::blocking::SpiDevice; + use embedded_hal_1::spi::SpiDevice; #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum SpiDeviceWithCsError { @@ -153,7 +153,7 @@ mod shared_spi { impl<'a, BUS, CS> SpiDevice for SpiDeviceWithCs<'a, BUS, CS> where - BUS: spi::blocking::SpiBusFlush, + BUS: spi::SpiBusFlush, CS: OutputPin, { type Bus = BUS; @@ -182,7 +182,7 @@ mod shared_spi { /// Driver for the XPT2046 resistive touchscreen sensor mod touch { - use embedded_hal_1::spi::blocking::{SpiBus, SpiBusRead, SpiBusWrite, SpiDevice}; + use embedded_hal_1::spi::{SpiBus, SpiBusRead, SpiBusWrite, SpiDevice}; struct Calibration { x1: i32, @@ -246,8 +246,8 @@ mod touch { mod my_display_interface { use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; - use embedded_hal_1::digital::blocking::OutputPin; - use embedded_hal_1::spi::blocking::{SpiBusWrite, SpiDevice}; + use embedded_hal_1::digital::OutputPin; + use embedded_hal_1::spi::{SpiBusWrite, SpiDevice}; /// SPI display interface. /// -- cgit From 9f77dbf5ae442c1cac0c652b4ef25bf1c82ed9d4 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Thu, 29 Sep 2022 02:01:58 -0700 Subject: rp i2c: blocking example i2c example talking to mcp23017 i2c gpio expander. --- examples/rp/src/bin/i2c.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 examples/rp/src/bin/i2c.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/i2c.rs b/examples/rp/src/bin/i2c.rs new file mode 100644 index 000000000..a5991d0da --- /dev/null +++ b/examples/rp/src/bin/i2c.rs @@ -0,0 +1,70 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::i2c::{self, Config}; +use embassy_time::{Duration, Timer}; +use embedded_hal_1::i2c::blocking::I2c; +use {defmt_rtt as _, panic_probe as _}; + +#[allow(dead_code)] +mod mcp23017 { + pub const ADDR: u8 = 0x20; // default addr + + pub const IODIRA: u8 = 0x00; + pub const IPOLA: u8 = 0x02; + pub const GPINTENA: u8 = 0x04; + pub const DEFVALA: u8 = 0x06; + pub const INTCONA: u8 = 0x08; + pub const IOCONA: u8 = 0x0A; + pub const GPPUA: u8 = 0x0C; + pub const INTFA: u8 = 0x0E; + pub const INTCAPA: u8 = 0x10; + pub const GPIOA: u8 = 0x12; + pub const OLATA: u8 = 0x14; + pub const IODIRB: u8 = 0x01; + pub const IPOLB: u8 = 0x03; + pub const GPINTENB: u8 = 0x05; + pub const DEFVALB: u8 = 0x07; + pub const INTCONB: u8 = 0x09; + pub const IOCONB: u8 = 0x0B; + pub const GPPUB: u8 = 0x0D; + pub const INTFB: u8 = 0x0F; + pub const INTCAPB: u8 = 0x11; + pub const GPIOB: u8 = 0x13; + pub const OLATB: u8 = 0x15; +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let sda = p.PIN_14; + let scl = p.PIN_15; + + info!("set up i2c "); + let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); + + use mcp23017::*; + + info!("init mcp23017 config for IxpandO"); + // init - a outputs, b inputs + i2c.write(ADDR, &[IODIRA, 0x00]).unwrap(); + i2c.write(ADDR, &[IODIRB, 0xff]).unwrap(); + i2c.write(ADDR, &[GPPUB, 0xff]).unwrap(); // pullups + + let mut val = 0xaa; + loop { + let mut portb = [0]; + + i2c.write(mcp23017::ADDR, &[GPIOA, val]).unwrap(); + i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).unwrap(); + + info!("portb = {:02x}", portb[0]); + val = !val; + + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From d5abd32da21998178216693a4d549a0f2683a4bb Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 1 Oct 2022 01:09:40 -0700 Subject: rename to i2c_blocking --- examples/rp/src/bin/i2c.rs | 70 ------------------------------------- examples/rp/src/bin/i2c_blocking.rs | 70 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 70 deletions(-) delete mode 100644 examples/rp/src/bin/i2c.rs create mode 100644 examples/rp/src/bin/i2c_blocking.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/i2c.rs b/examples/rp/src/bin/i2c.rs deleted file mode 100644 index a5991d0da..000000000 --- a/examples/rp/src/bin/i2c.rs +++ /dev/null @@ -1,70 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use defmt::*; -use embassy_executor::Spawner; -use embassy_rp::i2c::{self, Config}; -use embassy_time::{Duration, Timer}; -use embedded_hal_1::i2c::blocking::I2c; -use {defmt_rtt as _, panic_probe as _}; - -#[allow(dead_code)] -mod mcp23017 { - pub const ADDR: u8 = 0x20; // default addr - - pub const IODIRA: u8 = 0x00; - pub const IPOLA: u8 = 0x02; - pub const GPINTENA: u8 = 0x04; - pub const DEFVALA: u8 = 0x06; - pub const INTCONA: u8 = 0x08; - pub const IOCONA: u8 = 0x0A; - pub const GPPUA: u8 = 0x0C; - pub const INTFA: u8 = 0x0E; - pub const INTCAPA: u8 = 0x10; - pub const GPIOA: u8 = 0x12; - pub const OLATA: u8 = 0x14; - pub const IODIRB: u8 = 0x01; - pub const IPOLB: u8 = 0x03; - pub const GPINTENB: u8 = 0x05; - pub const DEFVALB: u8 = 0x07; - pub const INTCONB: u8 = 0x09; - pub const IOCONB: u8 = 0x0B; - pub const GPPUB: u8 = 0x0D; - pub const INTFB: u8 = 0x0F; - pub const INTCAPB: u8 = 0x11; - pub const GPIOB: u8 = 0x13; - pub const OLATB: u8 = 0x15; -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = embassy_rp::init(Default::default()); - - let sda = p.PIN_14; - let scl = p.PIN_15; - - info!("set up i2c "); - let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); - - use mcp23017::*; - - info!("init mcp23017 config for IxpandO"); - // init - a outputs, b inputs - i2c.write(ADDR, &[IODIRA, 0x00]).unwrap(); - i2c.write(ADDR, &[IODIRB, 0xff]).unwrap(); - i2c.write(ADDR, &[GPPUB, 0xff]).unwrap(); // pullups - - let mut val = 0xaa; - loop { - let mut portb = [0]; - - i2c.write(mcp23017::ADDR, &[GPIOA, val]).unwrap(); - i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).unwrap(); - - info!("portb = {:02x}", portb[0]); - val = !val; - - Timer::after(Duration::from_secs(1)).await; - } -} diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs new file mode 100644 index 000000000..a5991d0da --- /dev/null +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -0,0 +1,70 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::i2c::{self, Config}; +use embassy_time::{Duration, Timer}; +use embedded_hal_1::i2c::blocking::I2c; +use {defmt_rtt as _, panic_probe as _}; + +#[allow(dead_code)] +mod mcp23017 { + pub const ADDR: u8 = 0x20; // default addr + + pub const IODIRA: u8 = 0x00; + pub const IPOLA: u8 = 0x02; + pub const GPINTENA: u8 = 0x04; + pub const DEFVALA: u8 = 0x06; + pub const INTCONA: u8 = 0x08; + pub const IOCONA: u8 = 0x0A; + pub const GPPUA: u8 = 0x0C; + pub const INTFA: u8 = 0x0E; + pub const INTCAPA: u8 = 0x10; + pub const GPIOA: u8 = 0x12; + pub const OLATA: u8 = 0x14; + pub const IODIRB: u8 = 0x01; + pub const IPOLB: u8 = 0x03; + pub const GPINTENB: u8 = 0x05; + pub const DEFVALB: u8 = 0x07; + pub const INTCONB: u8 = 0x09; + pub const IOCONB: u8 = 0x0B; + pub const GPPUB: u8 = 0x0D; + pub const INTFB: u8 = 0x0F; + pub const INTCAPB: u8 = 0x11; + pub const GPIOB: u8 = 0x13; + pub const OLATB: u8 = 0x15; +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let sda = p.PIN_14; + let scl = p.PIN_15; + + info!("set up i2c "); + let mut i2c = i2c::I2c::new_blocking(p.I2C1, scl, sda, Config::default()); + + use mcp23017::*; + + info!("init mcp23017 config for IxpandO"); + // init - a outputs, b inputs + i2c.write(ADDR, &[IODIRA, 0x00]).unwrap(); + i2c.write(ADDR, &[IODIRB, 0xff]).unwrap(); + i2c.write(ADDR, &[GPPUB, 0xff]).unwrap(); // pullups + + let mut val = 0xaa; + loop { + let mut portb = [0]; + + i2c.write(mcp23017::ADDR, &[GPIOA, val]).unwrap(); + i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).unwrap(); + + info!("portb = {:02x}", portb[0]); + val = !val; + + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From c96581879cf054d9e4fec9272e5cecb165844cbb Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sat, 1 Oct 2022 01:33:36 -0700 Subject: update embedded-hal api Also pin to alpha.9 since its a breaking change --- examples/rp/src/bin/i2c_blocking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index a5991d0da..7623e33c8 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::i2c::{self, Config}; use embassy_time::{Duration, Timer}; -use embedded_hal_1::i2c::blocking::I2c; +use embedded_hal_1::i2c::I2c; use {defmt_rtt as _, panic_probe as _}; #[allow(dead_code)] -- cgit From 1ee4bb22deb19e93a7c68e04875889e3e4e31c29 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 28 Sep 2022 09:35:19 -0700 Subject: embassy-rp i2c: async (non-blocking) example Simple example exercising an mcp23017 GPIO expander, configured on RP2040 GPIOs 14+15 (i2c1) with 8 inputs and 8 outputs. Input bit 0 controls whether to display a mcp23017 register dump. --- examples/rp/src/bin/i2c_async.rs | 102 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 examples/rp/src/bin/i2c_async.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs new file mode 100644 index 000000000..d1a2e3cd7 --- /dev/null +++ b/examples/rp/src/bin/i2c_async.rs @@ -0,0 +1,102 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::i2c::{self, Config}; +use embassy_rp::interrupt; +use embassy_time::{Duration, Timer}; +use embedded_hal_async::i2c::I2c; +use {defmt_rtt as _, panic_probe as _}; + +#[allow(dead_code)] +mod mcp23017 { + pub const ADDR: u8 = 0x20; // default addr + + macro_rules! mcpregs { + ($($name:ident : $val:expr),* $(,)?) => { + $( + pub const $name: u8 = $val; + )* + + pub fn regname(reg: u8) -> &'static str { + match reg { + $( + $val => stringify!($name), + )* + _ => panic!("bad reg"), + } + } + } + } + + // These are correct for IOCON.BANK=0 + mcpregs! { + IODIRA: 0x00, + IPOLA: 0x02, + GPINTENA: 0x04, + DEFVALA: 0x06, + INTCONA: 0x08, + IOCONA: 0x0A, + GPPUA: 0x0C, + INTFA: 0x0E, + INTCAPA: 0x10, + GPIOA: 0x12, + OLATA: 0x14, + IODIRB: 0x01, + IPOLB: 0x03, + GPINTENB: 0x05, + DEFVALB: 0x07, + INTCONB: 0x09, + IOCONB: 0x0B, + GPPUB: 0x0D, + INTFB: 0x0F, + INTCAPB: 0x11, + GPIOB: 0x13, + OLATB: 0x15, + } +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let sda = p.PIN_14; + let scl = p.PIN_15; + let irq = interrupt::take!(I2C1_IRQ); + + info!("set up i2c "); + let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, irq, Config::default()); + + use mcp23017::*; + + info!("init mcp23017 config for IxpandO"); + // init - a outputs, b inputs + i2c.write(ADDR, &[IODIRA, 0x00]).await.unwrap(); + i2c.write(ADDR, &[IODIRB, 0xff]).await.unwrap(); + i2c.write(ADDR, &[GPPUB, 0xff]).await.unwrap(); // pullups + + let mut val = 1; + loop { + let mut portb = [0]; + + i2c.write_read(mcp23017::ADDR, &[GPIOB], &mut portb).await.unwrap(); + info!("portb = {:02x}", portb[0]); + i2c.write(mcp23017::ADDR, &[GPIOA, val | portb[0]]).await.unwrap(); + val = val.rotate_left(1); + + // get a register dump + info!("getting register dump"); + let mut regs = [0; 22]; + i2c.write_read(ADDR, &[0], &mut regs).await.unwrap(); + // always get the regdump but only display it if portb'0 is set + if portb[0] & 1 != 0 { + for (idx, reg) in regs.into_iter().enumerate() { + info!("{} => {:02x}", regname(idx as u8), reg); + } + } + + Timer::after(Duration::from_millis(100)).await; + } +} -- cgit From 80e58426fcf40b6cea28368e43a7289e827461cf Mon Sep 17 00:00:00 2001 From: Mathias Date: Wed, 26 Oct 2022 10:01:52 +0200 Subject: Add flash example & flash HIL test --- examples/rp/src/bin/flash.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 examples/rp/src/bin/flash.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs new file mode 100644 index 000000000..17549e4be --- /dev/null +++ b/examples/rp/src/bin/flash.rs @@ -0,0 +1,84 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE}; +use embassy_rp::peripherals::FLASH; +use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use {defmt_rtt as _, panic_probe as _}; + +const ADDR_OFFSET: u32 = 0x100000; +const FLASH_SIZE: usize = 2 * 1024 * 1024; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH); + + erase_write_sector(&mut flash, 0x00); + + multiwrite_bytes(&mut flash, ERASE_SIZE as u32); + + loop {} +} + +fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) { + info!(">>>> [multiwrite_bytes]"); + let mut read_buf = [0u8; ERASE_SIZE]; + defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf)); + + info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32); + info!("Contents start with {=[u8]}", read_buf[0..4]); + + defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32)); + + defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf)); + info!("Contents after erase starts with {=[u8]}", read_buf[0..4]); + if read_buf.iter().any(|x| *x != 0xFF) { + defmt::panic!("unexpected"); + } + + defmt::unwrap!(flash.write(ADDR_OFFSET + offset, &[0x01])); + defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 1, &[0x02])); + defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 2, &[0x03])); + defmt::unwrap!(flash.write(ADDR_OFFSET + offset + 3, &[0x04])); + + defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf)); + info!("Contents after write starts with {=[u8]}", read_buf[0..4]); + if &read_buf[0..4] != &[0x01, 0x02, 0x03, 0x04] { + defmt::panic!("unexpected"); + } +} + +fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) { + info!(">>>> [erase_write_sector]"); + let mut buf = [0u8; ERASE_SIZE]; + defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf)); + + info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32); + info!("Contents start with {=[u8]}", buf[0..4]); + + defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32)); + + defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf)); + info!("Contents after erase starts with {=[u8]}", buf[0..4]); + if buf.iter().any(|x| *x != 0xFF) { + defmt::panic!("unexpected"); + } + + for b in buf.iter_mut() { + *b = 0xDA; + } + + defmt::unwrap!(flash.write(ADDR_OFFSET + offset, &buf)); + + defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf)); + info!("Contents after write starts with {=[u8]}", buf[0..4]); + if buf.iter().any(|x| *x != 0xDA) { + defmt::panic!("unexpected"); + } +} -- cgit From 1669e395654430dff6dffda0cef9522f9ccfd213 Mon Sep 17 00:00:00 2001 From: Mathias Date: Wed, 26 Oct 2022 14:47:32 +0200 Subject: Buffer data to be written to flash in ram if it does not already reside in ram --- examples/rp/src/bin/flash.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index 17549e4be..d4dfca759 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs @@ -18,7 +18,6 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH); - erase_write_sector(&mut flash, 0x00); multiwrite_bytes(&mut flash, ERASE_SIZE as u32); -- cgit From 3c6c382465131c6f76567f976198b77e327df4b2 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 27 Oct 2022 07:10:27 +0200 Subject: Remove random delay from example, and move flash functions to allow using without embedded-storage in scope --- examples/rp/src/bin/flash.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index d4dfca759..8d6b379f4 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE}; use embassy_rp::peripherals::FLASH; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; const ADDR_OFFSET: u32 = 0x100000; @@ -17,6 +17,12 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); info!("Hello World!"); + // add some delay to give an attached debug probe time to parse the + // defmt RTT header. Reading that header might touch flash memory, which + // interferes with flash write operations. + // https://github.com/knurling-rs/defmt/pull/683 + Timer::after(Duration::from_millis(10)).await; + let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH); erase_write_sector(&mut flash, 0x00); -- cgit From eb149a0bd42d7690e78e5f2b37579c1f68be613b Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 15 Nov 2022 16:12:07 +0100 Subject: embassy-rp: Add basic ADC module --- examples/rp/src/bin/adc.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 examples/rp/src/bin/adc.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs new file mode 100644 index 000000000..2a9e93732 --- /dev/null +++ b/examples/rp/src/bin/adc.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::adc::{Adc, Config}; +use embassy_rp::interrupt; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let irq = interrupt::take!(ADC_IRQ_FIFO); + let mut adc = Adc::new(p.ADC, irq, Config::default()); + + let mut p26 = p.PIN_26; + let mut p27 = p.PIN_27; + let mut p28 = p.PIN_28; + + loop { + let level = adc.read(&mut p26).await; + info!("Pin 26 ADC: {}", level); + let level = adc.read(&mut p27).await; + info!("Pin 27 ADC: {}", level); + let level = adc.read(&mut p28).await; + info!("Pin 28 ADC: {}", level); + let temp = adc.read_temperature().await; + info!("Temp: {}", temp); + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From a444a65ebfcea674e74dcedc7f26a7aa37f59c69 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 17 Nov 2022 09:26:15 +0100 Subject: feat: embassy-usb-logger and example for rpi pico * Add embassy-usb-logger which allows logging over USB for any device implementing embassy-usb * Add example using logger for rpi pico. --- examples/rp/src/bin/usb_logger.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 examples/rp/src/bin/usb_logger.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs new file mode 100644 index 000000000..52417a02e --- /dev/null +++ b/examples/rp/src/bin/usb_logger.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Spawner; +use embassy_rp::interrupt; +use embassy_rp::peripherals::USB; +use embassy_rp::usb::Driver; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn logger_task(driver: Driver<'static, USB>) { + embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let irq = interrupt::take!(USBCTRL_IRQ); + let driver = Driver::new(p.USB, irq); + spawner.spawn(logger_task(driver)).unwrap(); + + let mut counter = 0; + loop { + counter += 1; + log::info!("Tick {}", counter); + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From 35db6e639bf5de017551164e9cbfaa2e5e46fca3 Mon Sep 17 00:00:00 2001 From: Simon Berg Date: Wed, 27 Jul 2022 22:45:46 +0200 Subject: PIO support for RPi Pico --- examples/rp/src/bin/pio_async.rs | 105 +++++++++++++++++++++++++++++++++++++++ examples/rp/src/bin/pio_dma.rs | 67 +++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 examples/rp/src/bin/pio_async.rs create mode 100644 examples/rp/src/bin/pio_dma.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs new file mode 100644 index 000000000..e9211db3b --- /dev/null +++ b/examples/rp/src/bin/pio_async.rs @@ -0,0 +1,105 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +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_instr_util; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { + // Setup sm0 + + // Send data serially to pin + let prg = pio_proc::pio_asm!( + ".origin 16", + "set pindirs, 1", + ".wrap_target", + "out pins,1 [19]", + ".wrap", + ); + + let origin = prg.program.origin.unwrap_or(0); + let out_pin = sm.make_pio_pin(pin); + let pio_pins = [&out_pin]; + sm.set_out_pins(&pio_pins); + sm.write_instr(origin as usize, &prg.program.code); + pio_instr_util::exec_jmp(&mut sm, origin); + sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); + sm.set_set_range(0, 1); + sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + sm.set_autopull(true); + sm.set_out_shift_dir(ShiftDirection::Left); + + sm.set_enable(true); + + let mut v = 0x0f0caffa; + loop { + sm.wait_push(v).await; + v ^= 0xffff; + info!("Pushed {:032b} to FIFO", v); + } +} + +#[embassy_executor::task] +async fn pio_task_sm1(mut sm: PioStateMachineInstance) { + // Setupm sm1 + + // Read 0b10101 repeatedly until ISR is full + let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); + + let origin = prg.program.origin.unwrap_or(0); + sm.write_instr(origin as usize, &prg.program.code); + pio_instr_util::exec_jmp(&mut sm, origin); + sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); + sm.set_set_range(0, 0); + sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + sm.set_autopush(true); + sm.set_in_shift_dir(ShiftDirection::Right); + sm.set_enable(true); + loop { + let rx = sm.wait_pull().await; + info!("Pulled {:032b} from FIFO", rx); + } +} + +#[embassy_executor::task] +async fn pio_task_sm2(mut sm: PioStateMachineInstance) { + // Setup sm2 + + // Repeatedly trigger IRQ 3 + let prg = pio_proc::pio_asm!( + ".origin 0", + ".wrap_target", + "set x,10", + "delay:", + "jmp x-- delay [15]", + "irq 3 [15]", + ".wrap", + ); + let origin = prg.program.origin.unwrap_or(0); + + sm.write_instr(origin as usize, &prg.program.code); + sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + pio_instr_util::exec_jmp(&mut sm, origin); + sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); + sm.set_enable(true); + loop { + sm.wait_irq(3).await; + info!("IRQ trigged"); + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let pio = p.PIO0; + + let (_, sm0, sm1, sm2, ..) = pio.split(); + + spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap(); + spawner.spawn(pio_task_sm1(sm1)).unwrap(); + spawner.spawn(pio_task_sm2(sm2)).unwrap(); +} diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs new file mode 100644 index 000000000..bdcdf200c --- /dev/null +++ b/examples/rp/src/bin/pio_dma.rs @@ -0,0 +1,67 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +use defmt::info; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_rp::pio::{PioPeripherial, PioStateMachine, ShiftDirection}; +use embassy_rp::{pio_instr_util, Peripheral}; +use {defmt_rtt as _, panic_probe as _}; + +fn swap_nibbles(v: u32) -> u32 { + let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; + let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; + (v & 0x0000_ffff) << 16 | (v & 0xffff_0000) >> 16 +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let pio = p.PIO0; + let (_, mut sm, ..) = pio.split(); + + let prg = pio_proc::pio_asm!( + ".origin 0", + "set pindirs,1", + ".wrap_target", + "set y,7", + "loop:", + "out x,4", + "in x,4", + "jmp y--, loop", + ".wrap", + ); + + let origin = prg.program.origin.unwrap_or(0); + sm.write_instr(origin as usize, &prg.program.code); + pio_instr_util::exec_jmp(&mut sm, origin); + sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); + sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + sm.set_autopull(true); + sm.set_autopush(true); + sm.set_pull_threshold(32); + sm.set_push_threshold(32); + sm.set_out_shift_dir(ShiftDirection::Right); + sm.set_in_shift_dir(ShiftDirection::Left); + + sm.set_enable(true); + + let mut dma_out_ref = p.DMA_CH0.into_ref(); + let mut dma_in_ref = p.DMA_CH1.into_ref(); + let mut dout = [0x12345678u32; 29]; + for i in 1..dout.len() { + dout[i] = (dout[i - 1] & 0x0fff_ffff) * 13 + 7; + } + let mut din = [0u32; 29]; + loop { + join( + sm.dma_push(dma_out_ref.reborrow(), &dout), + sm.dma_pull(dma_in_ref.reborrow(), &mut din), + ) + .await; + for i in 0..din.len() { + assert_eq!(din[i], swap_nibbles(dout[i])); + } + info!("Swapped {} words", dout.len()); + } +} -- cgit From cd59046e6c179809ee19fb2592e65cf5a0a07980 Mon Sep 17 00:00:00 2001 From: Simon Berg Date: Tue, 6 Dec 2022 21:42:30 +0100 Subject: Added RelocateProgram class for adjusting PIO-programs for different origins. --- examples/rp/src/bin/pio_async.rs | 31 +++++++++++++++++++------------ examples/rp/src/bin/pio_dma.rs | 10 ++++++---- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index e9211db3b..45a8c73f7 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -6,6 +6,7 @@ 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_instr_util; +use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::task] @@ -21,15 +22,17 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { ".wrap", ); - let origin = prg.program.origin.unwrap_or(0); + let relocated = RelocatedProgram::new(&prg.program); let out_pin = sm.make_pio_pin(pin); let pio_pins = [&out_pin]; sm.set_out_pins(&pio_pins); - sm.write_instr(origin as usize, &prg.program.code); - pio_instr_util::exec_jmp(&mut sm, origin); + sm.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); sm.set_set_range(0, 1); - sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + let pio::Wrap { source, target } = relocated.wrap(); + sm.set_wrap(source, target); + sm.set_autopull(true); sm.set_out_shift_dir(ShiftDirection::Left); @@ -50,12 +53,14 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance) { // Read 0b10101 repeatedly until ISR is full let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); - let origin = prg.program.origin.unwrap_or(0); - sm.write_instr(origin as usize, &prg.program.code); - pio_instr_util::exec_jmp(&mut sm, origin); + let relocated = RelocatedProgram::new(&prg.program); + sm.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); sm.set_set_range(0, 0); - sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + let pio::Wrap { source, target } = relocated.wrap(); + sm.set_wrap(source, target); + sm.set_autopush(true); sm.set_in_shift_dir(ShiftDirection::Right); sm.set_enable(true); @@ -79,11 +84,13 @@ async fn pio_task_sm2(mut sm: PioStateMachineInstance) { "irq 3 [15]", ".wrap", ); - let origin = prg.program.origin.unwrap_or(0); + let relocated = RelocatedProgram::new(&prg.program); + sm.write_instr(relocated.origin() as usize, relocated.code()); + + let pio::Wrap { source, target } = relocated.wrap(); + sm.set_wrap(source, target); - sm.write_instr(origin as usize, &prg.program.code); - sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); - pio_instr_util::exec_jmp(&mut sm, origin); + pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); sm.set_enable(true); loop { diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index bdcdf200c..b19ef4083 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -5,6 +5,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_rp::pio::{PioPeripherial, PioStateMachine, ShiftDirection}; +use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; @@ -32,11 +33,12 @@ async fn main(_spawner: Spawner) { ".wrap", ); - let origin = prg.program.origin.unwrap_or(0); - sm.write_instr(origin as usize, &prg.program.code); - pio_instr_util::exec_jmp(&mut sm, origin); + let relocated = RelocatedProgram::new(&prg.program); + sm.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); - sm.set_wrap(prg.program.wrap.source + origin, prg.program.wrap.target + origin); + let pio::Wrap { source, target } = relocated.wrap(); + sm.set_wrap(source, target); sm.set_autopull(true); sm.set_autopush(true); sm.set_pull_threshold(32); -- cgit From 1ee58492fbc58b721dc5ed9037c6787af257cbeb Mon Sep 17 00:00:00 2001 From: kalkyl Date: Sat, 10 Dec 2022 08:26:35 +0100 Subject: embassy-rp: Add multicore support --- examples/rp/src/bin/multicore.rs | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 examples/rp/src/bin/multicore.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs new file mode 100644 index 000000000..46d3cd17c --- /dev/null +++ b/examples/rp/src/bin/multicore.rs @@ -0,0 +1,62 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Executor; +use embassy_executor::_export::StaticCell; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::PIN_25; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use embassy_time::{Duration, Timer}; +use embassy_rp::multicore::{Multicore, Stack}; +use {defmt_rtt as _, panic_probe as _}; + +static mut CORE1_STACK: Stack<4096> = Stack::new(); +static EXECUTOR0: StaticCell = StaticCell::new(); +static EXECUTOR1: StaticCell = StaticCell::new(); +static CHANNEL: Channel = Channel::new(); + +enum LedState { + On, + Off, +} + +#[cortex_m_rt::entry] +fn main() -> ! { + let p = embassy_rp::init(Default::default()); + let led = Output::new(p.PIN_25, Level::Low); + + let mut mc = Multicore::new(); + let (_, core1) = mc.cores(); + let _ = core1.spawn(unsafe { &mut CORE1_STACK.mem }, move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); + }); + + let executor0 = EXECUTOR0.init(Executor::new()); + executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); +} + +#[embassy_executor::task] +async fn core0_task() { + info!("Hello from core 0"); + loop { + CHANNEL.send(LedState::On).await; + Timer::after(Duration::from_millis(100)).await; + CHANNEL.send(LedState::Off).await; + Timer::after(Duration::from_millis(400)).await; + } +} + +#[embassy_executor::task] +async fn core1_task(mut led: Output<'static, PIN_25>) { + info!("Hello from core 1"); + loop { + match CHANNEL.recv().await { + LedState::On => led.set_high(), + LedState::Off => led.set_low(), + } + } +} \ No newline at end of file -- cgit From 34eaade14fbf521d2e0e37bdeb870787a184ee2e Mon Sep 17 00:00:00 2001 From: kalkyl Date: Sat, 10 Dec 2022 08:33:09 +0100 Subject: fmt --- examples/rp/src/bin/multicore.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 46d3cd17c..cfb91e21f 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -6,11 +6,11 @@ use defmt::*; use embassy_executor::Executor; use embassy_executor::_export::StaticCell; use embassy_rp::gpio::{Level, Output}; +use embassy_rp::multicore::{Multicore, Stack}; use embassy_rp::peripherals::PIN_25; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_time::{Duration, Timer}; -use embassy_rp::multicore::{Multicore, Stack}; use {defmt_rtt as _, panic_probe as _}; static mut CORE1_STACK: Stack<4096> = Stack::new(); @@ -59,4 +59,4 @@ async fn core1_task(mut led: Output<'static, PIN_25>) { LedState::Off => led.set_low(), } } -} \ No newline at end of file +} -- cgit From 96d6c7243b7b5f7f8c90dab666ded0ca0cf29c75 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Sat, 10 Dec 2022 13:43:29 +0100 Subject: Cleanup --- examples/rp/src/bin/multicore.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index cfb91e21f..53941da60 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Executor; use embassy_executor::_export::StaticCell; use embassy_rp::gpio::{Level, Output}; -use embassy_rp::multicore::{Multicore, Stack}; +use embassy_rp::multicore::{MultiCore, Stack}; use embassy_rp::peripherals::PIN_25; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; @@ -28,9 +28,8 @@ fn main() -> ! { let p = embassy_rp::init(Default::default()); let led = Output::new(p.PIN_25, Level::Low); - let mut mc = Multicore::new(); - let (_, core1) = mc.cores(); - let _ = core1.spawn(unsafe { &mut CORE1_STACK.mem }, move || { + let mut mc = MultiCore::new(); + let _ = mc.cores.1.spawn(unsafe { &mut CORE1_STACK.mem }, move || { let executor1 = EXECUTOR1.init(Executor::new()); executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); }); -- cgit From 13d9d8fde109c09e310cbf1735917a768f4a1cf6 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Tue, 13 Dec 2022 13:49:51 +0100 Subject: Refactor after review --- examples/rp/src/bin/multicore.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 53941da60..376b2b61e 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Executor; use embassy_executor::_export::StaticCell; use embassy_rp::gpio::{Level, Output}; -use embassy_rp::multicore::{MultiCore, Stack}; +use embassy_rp::multicore::{spawn_core1, Stack}; use embassy_rp::peripherals::PIN_25; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; @@ -28,8 +28,7 @@ fn main() -> ! { let p = embassy_rp::init(Default::default()); let led = Output::new(p.PIN_25, Level::Low); - let mut mc = MultiCore::new(); - let _ = mc.cores.1.spawn(unsafe { &mut CORE1_STACK.mem }, move || { + spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { let executor1 = EXECUTOR1.init(Executor::new()); executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); }); -- cgit From e9219405ca04e23b6543fb841fd97df54cf72f94 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 7 Dec 2022 16:03:03 +0100 Subject: usb/cdc-ncm: add embassy-net Device implementation. --- examples/rp/src/bin/usb_ethernet.rs | 140 +++++------------------------------- 1 file changed, 17 insertions(+), 123 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 1057fe7fd..d0aec874a 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -2,18 +2,14 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::sync::atomic::{AtomicBool, Ordering}; -use core::task::Waker; - use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; -use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources}; +use embassy_net::{Stack, StackResources}; use embassy_rp::usb::Driver; use embassy_rp::{interrupt, peripherals}; -use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; -use embassy_sync::channel::Channel; -use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; +use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; +use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io::asynch::Write; use static_cell::StaticCell; @@ -25,56 +21,25 @@ macro_rules! singleton { ($val:expr) => {{ type T = impl Sized; static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) + let (x,) = STATIC_CELL.init(($val,)); + x }}; } +const MTU: usize = 1514; + #[embassy_executor::task] async fn usb_task(mut device: UsbDevice<'static, MyDriver>) -> ! { device.run().await } #[embassy_executor::task] -async fn usb_ncm_rx_task(mut class: Receiver<'static, MyDriver>) { - loop { - warn!("WAITING for connection"); - LINK_UP.store(false, Ordering::Relaxed); - - class.wait_connection().await.unwrap(); - - warn!("Connected"); - LINK_UP.store(true, Ordering::Relaxed); - - loop { - let mut p = unwrap!(PacketBox::new(embassy_net::Packet::new())); - let n = match class.read_packet(&mut p[..]).await { - Ok(n) => n, - Err(e) => { - warn!("error reading packet: {:?}", e); - break; - } - }; - - let buf = p.slice(0..n); - if RX_CHANNEL.try_send(buf).is_err() { - warn!("Failed pushing rx'd packet to channel."); - } - } - } -} - -#[embassy_executor::task] -async fn usb_ncm_tx_task(mut class: Sender<'static, MyDriver>) { - loop { - let pkt = TX_CHANNEL.recv().await; - if let Err(e) = class.write_packet(&pkt[..]).await { - warn!("Failed to TX packet: {:?}", e); - } - } +async fn usb_ncm_task(class: Runner<'static, MyDriver, MTU>) -> ! { + class.run().await } #[embassy_executor::task] -async fn net_task(stack: &'static Stack) -> ! { +async fn net_task(stack: &'static Stack>) -> ! { stack.run().await } @@ -100,55 +65,32 @@ async fn main(spawner: Spawner) { config.device_sub_class = 0x02; config.device_protocol = 0x01; - struct Resources { - device_descriptor: [u8; 256], - config_descriptor: [u8; 256], - bos_descriptor: [u8; 256], - control_buf: [u8; 128], - serial_state: State<'static>, - } - let res: &mut Resources = singleton!(Resources { - device_descriptor: [0; 256], - config_descriptor: [0; 256], - bos_descriptor: [0; 256], - control_buf: [0; 128], - serial_state: State::new(), - }); - // Create embassy-usb DeviceBuilder using the driver and config. let mut builder = Builder::new( driver, config, - &mut res.device_descriptor, - &mut res.config_descriptor, - &mut res.bos_descriptor, - &mut res.control_buf, + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 256])[..], + &mut singleton!([0; 128])[..], None, ); - // WARNINGS for Android ethernet tethering: - // - On Pixel 4a, it refused to work on Android 11, worked on Android 12. - // - if the host's MAC address has the "locally-administered" bit set (bit 1 of first byte), - // it doesn't work! The "Ethernet tethering" option in settings doesn't get enabled. - // This is due to regex spaghetti: https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-mainline-12.0.0_r84/core/res/res/values/config.xml#417 - // and this nonsense in the linux kernel: https://github.com/torvalds/linux/blob/c00c5e1d157bec0ef0b0b59aa5482eb8dc7e8e49/drivers/net/usb/usbnet.c#L1751-L1757 - // Our MAC addr. let our_mac_addr = [0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC]; // Host's MAC addr. This is the MAC the host "thinks" its USB-to-ethernet adapter has. let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, &mut res.serial_state, host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (tx, rx) = class.split(); - unwrap!(spawner.spawn(usb_ncm_rx_task(rx))); - unwrap!(spawner.spawn(usb_ncm_tx_task(tx))); + let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::ConfigStrategy::Dhcp; //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { @@ -161,7 +103,6 @@ async fn main(spawner: Spawner) { let seed = 1234; // guaranteed random, chosen by a fair dice roll // Init network stack - let device = Device { mac_addr: our_mac_addr }; let stack = &*singleton!(Stack::new( device, config, @@ -214,50 +155,3 @@ async fn main(spawner: Spawner) { } } } - -static TX_CHANNEL: Channel = Channel::new(); -static RX_CHANNEL: Channel = Channel::new(); -static LINK_UP: AtomicBool = AtomicBool::new(false); - -struct Device { - mac_addr: [u8; 6], -} - -impl embassy_net::Device for Device { - fn register_waker(&mut self, waker: &Waker) { - // loopy loopy wakey wakey - waker.wake_by_ref() - } - - fn link_state(&mut self) -> embassy_net::LinkState { - match LINK_UP.load(Ordering::Relaxed) { - true => embassy_net::LinkState::Up, - false => embassy_net::LinkState::Down, - } - } - - fn capabilities(&self) -> embassy_net::DeviceCapabilities { - let mut caps = embassy_net::DeviceCapabilities::default(); - caps.max_transmission_unit = 1514; // 1500 IP + 14 ethernet header - caps.medium = embassy_net::Medium::Ethernet; - caps - } - - fn is_transmit_ready(&mut self) -> bool { - true - } - - fn transmit(&mut self, pkt: PacketBuf) { - if TX_CHANNEL.try_send(pkt).is_err() { - warn!("TX failed") - } - } - - fn receive<'a>(&mut self) -> Option { - RX_CHANNEL.try_recv().ok() - } - - fn ethernet_address(&self) -> [u8; 6] { - self.mac_addr - } -} -- cgit From 849a0e174fa1601236050afb72290174675c585f Mon Sep 17 00:00:00 2001 From: Aaron Tsui Date: Tue, 20 Dec 2022 09:11:39 +0800 Subject: add convert_to_celsius function in the adc module modify RP2040 adc example to get inside biased bipolar diode voltage, then convert this temperature sensor data into Celsius degree, according to chapter 4.9.5. Temperature Sensor in RP2040 datasheet. --- examples/rp/src/bin/adc.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 2a9e93732..25e5126b4 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -27,7 +27,12 @@ async fn main(_spawner: Spawner) { let level = adc.read(&mut p28).await; info!("Pin 28 ADC: {}", level); let temp = adc.read_temperature().await; - info!("Temp: {}", temp); + info!("Temp: {} degrees", convert_to_celsius(temp)); Timer::after(Duration::from_secs(1)).await; } } + +fn convert_to_celsius(raw_temp: u16) -> f32 { + // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet + 27.0 - (raw_temp as f32 * 3.3 / 4096.0 -0.706)/0.001721 as f32 +} \ No newline at end of file -- cgit From 5ae91ed3b64a086b15a949477a5762a3876307c5 Mon Sep 17 00:00:00 2001 From: Aaron Tsui Date: Tue, 20 Dec 2022 14:59:49 +0800 Subject: cargo fmt --- examples/rp/src/bin/adc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 25e5126b4..4202fd394 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -34,5 +34,5 @@ async fn main(_spawner: Spawner) { fn convert_to_celsius(raw_temp: u16) -> f32 { // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet - 27.0 - (raw_temp as f32 * 3.3 / 4096.0 -0.706)/0.001721 as f32 -} \ No newline at end of file + 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32 +} -- cgit From aa92ce6dc71cf176eb6e99632fda72c875d071e6 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Thu, 22 Dec 2022 23:03:05 +0100 Subject: embassy-rp: Add split() to BufferedUart --- examples/rp/src/bin/uart_buffered_split.rs | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 examples/rp/src/bin/uart_buffered_split.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs new file mode 100644 index 000000000..36f31c906 --- /dev/null +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -0,0 +1,57 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_executor::_export::StaticCell; +use embassy_rp::interrupt; +use embassy_rp::peripherals::UART0; +use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config}; +use embassy_time::{Duration, Timer}; +use embedded_io::asynch::{Read, Write}; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); + + let irq = interrupt::take!(UART0_IRQ); + let tx_buf = &mut singleton!([0u8; 16])[..]; + let rx_buf = &mut singleton!([0u8; 16])[..]; + let mut uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); + let (rx, mut tx) = uart.split(); + + unwrap!(spawner.spawn(reader(rx))); + + info!("Writing..."); + loop { + let data = [ + 1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, + ]; + info!("TX {:?}", data); + tx.write_all(&data).await.unwrap(); + Timer::after(Duration::from_secs(1)).await; + } +} + +#[embassy_executor::task] +async fn reader(mut rx: BufferedUartRx<'static, UART0>) { + info!("Reading..."); + loop { + let mut buf = [0; 31]; + rx.read_exact(&mut buf).await.unwrap(); + info!("RX {:?}", buf); + } +} -- cgit From eaad0cc1dc09e604d137b3a1bdfd3438ff990621 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Sat, 24 Dec 2022 02:51:06 +0100 Subject: embassy-rp: Add Watchdog --- examples/rp/src/bin/watchdog.rs | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 examples/rp/src/bin/watchdog.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs new file mode 100644 index 000000000..13af22a2d --- /dev/null +++ b/examples/rp/src/bin/watchdog.rs @@ -0,0 +1,48 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_rp::gpio; +use embassy_rp::watchdog::*; +use embassy_time::{Duration, Timer}; +use gpio::{Level, Output}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello world!"); + + let mut watchdog = Watchdog::new(p.WATCHDOG); + let mut led = Output::new(p.PIN_25, Level::Low); + + // Set the LED high for 2 seconds so we know when we're about to start the watchdog + led.set_high(); + Timer::after(Duration::from_secs(2)).await; + + // Set to watchdog to reset if it's not reloaded within 1.05 seconds, and start it + watchdog.start(Duration::from_millis(1_050)); + info!("Started the watchdog timer"); + + // Blink once a second for 5 seconds, refreshing the watchdog timer once a second to avoid a reset + for _ in 1..=5 { + led.set_low(); + Timer::after(Duration::from_millis(500)).await; + led.set_high(); + Timer::after(Duration::from_millis(500)).await; + info!("Feeding watchdog"); + watchdog.feed(); + } + + info!("Stopped feeding, device will reset in 1.05 seconds"); + // Blink 10 times per second, not feeding the watchdog. + // The processor should reset in 1.05 seconds, or 5 blinks time + loop { + led.set_low(); + Timer::after(Duration::from_millis(100)).await; + led.set_high(); + Timer::after(Duration::from_millis(100)).await; + } +} -- cgit From e090ab19151fbea6736d5eac0e1497ef9c36626b Mon Sep 17 00:00:00 2001 From: kalkyl Date: Sat, 24 Dec 2022 03:22:51 +0100 Subject: Remove lifetime, use pac fields --- examples/rp/src/bin/watchdog.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs index 13af22a2d..ece5cfe38 100644 --- a/examples/rp/src/bin/watchdog.rs +++ b/examples/rp/src/bin/watchdog.rs @@ -22,11 +22,11 @@ async fn main(_spawner: Spawner) { led.set_high(); Timer::after(Duration::from_secs(2)).await; - // Set to watchdog to reset if it's not reloaded within 1.05 seconds, and start it + // Set to watchdog to reset if it's not fed within 1.05 seconds, and start it watchdog.start(Duration::from_millis(1_050)); info!("Started the watchdog timer"); - // Blink once a second for 5 seconds, refreshing the watchdog timer once a second to avoid a reset + // Blink once a second for 5 seconds, feed the watchdog timer once a second to avoid a reset for _ in 1..=5 { led.set_low(); Timer::after(Duration::from_millis(500)).await; @@ -38,7 +38,7 @@ async fn main(_spawner: Spawner) { info!("Stopped feeding, device will reset in 1.05 seconds"); // Blink 10 times per second, not feeding the watchdog. - // The processor should reset in 1.05 seconds, or 5 blinks time + // The processor should reset in 1.05 seconds. loop { led.set_low(); Timer::after(Duration::from_millis(100)).await; -- cgit From a24037edf9d04087111c1d1dc71c92cc0ad83709 Mon Sep 17 00:00:00 2001 From: Timo Kröger Date: Sun, 1 Jan 2023 22:02:45 +0100 Subject: rp: Fix BufferedUart drop code Only unregister the interrupt handler when both parts are inactive --- examples/rp/src/bin/uart_buffered_split.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index 36f31c906..a8a682274 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -29,7 +29,7 @@ async fn main(spawner: Spawner) { let irq = interrupt::take!(UART0_IRQ); let tx_buf = &mut singleton!([0u8; 16])[..]; let rx_buf = &mut singleton!([0u8; 16])[..]; - let mut uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); + let uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); let (rx, mut tx) = uart.split(); unwrap!(spawner.spawn(reader(rx))); -- cgit From 6d4c6e0481f0738b8306172e7c5d54aa2758b74e Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Wed, 4 Jan 2023 20:27:07 +0100 Subject: rp2040: add {tx,rx}-only constructors to UART --- examples/rp/src/bin/uart_unidir.rs | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 examples/rp/src/bin/uart_unidir.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs new file mode 100644 index 000000000..f56e7009f --- /dev/null +++ b/examples/rp/src/bin/uart_unidir.rs @@ -0,0 +1,42 @@ +//! test TX-only and RX-only UARTs. You need to connect GPIO0 to GPIO5 for +//! this to work + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::peripherals::UART1; +use embassy_rp::uart::{Async, Config, UartRx, UartTx}; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); + let uart_rx = UartRx::new(p.UART1, p.PIN_5, p.DMA_CH1, Config::default()); + + unwrap!(spawner.spawn(reader(uart_rx))); + + info!("Writing..."); + loop { + let data = [1u8, 2, 3, 4, 5, 6, 7, 8]; + info!("TX {:?}", data); + uart_tx.write(&data).await.unwrap(); + Timer::after(Duration::from_secs(1)).await; + } +} + +#[embassy_executor::task] +async fn reader(mut rx: UartRx<'static, UART1, Async>) { + info!("Reading..."); + loop { + // read a total of 4 transmissions (32 / 8) and then print the result + let mut buf = [0; 32]; + rx.read(&mut buf).await.unwrap(); + info!("RX {:?}", buf); + } +} -- cgit From 8f4fae9b36f017a8ab65491ef49b72499a9486dc Mon Sep 17 00:00:00 2001 From: Paweł Jan Czochański Date: Wed, 18 Jan 2023 10:10:33 +0100 Subject: Add smoltcp dhcp socket configuration --- examples/rp/src/bin/usb_ethernet.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index d0aec874a..e9b727127 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -92,8 +92,8 @@ async fn main(spawner: Spawner) { let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); - let config = embassy_net::ConfigStrategy::Dhcp; - //let config = embassy_net::ConfigStrategy::Static(embassy_net::Config { + let config = embassy_net::Config::Dhcp(Default::default()); + //let config = embassy_net::Config::Static(embassy_net::StaticConfig { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), @@ -103,12 +103,7 @@ async fn main(spawner: Spawner) { let seed = 1234; // guaranteed random, chosen by a fair dice roll // Init network stack - let stack = &*singleton!(Stack::new( - device, - config, - singleton!(StackResources::<1, 2, 8>::new()), - seed - )); + let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<1>::new()), seed)); unwrap!(spawner.spawn(net_task(stack))); -- cgit From fe15a7beee5f948b1e4c1cb8ab8e5cc85efb4662 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 19 Jan 2023 14:40:58 +0100 Subject: net: allocate space for 2 sockets, needed for dhcp. --- examples/rp/src/bin/usb_ethernet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index e9b727127..104b25d39 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -103,7 +103,7 @@ async fn main(spawner: Spawner) { let seed = 1234; // guaranteed random, chosen by a fair dice roll // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<1>::new()), seed)); + let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); unwrap!(spawner.spawn(net_task(stack))); -- cgit From 3af991ab63d14cfad6f50d28bfb944d1895d1c70 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 7 Feb 2023 22:49:14 +0100 Subject: usb: unify ControlHandler+DeviceStateHandler, route all control requests to all handlers. - Allows classes to handle vendor requests. - Allows classes to use a single handler for multiple interfaces. - Allows classes to access the other events (previously only `reset` was available). --- examples/rp/src/bin/usb_ethernet.rs | 1 - examples/rp/src/bin/usb_serial.rs | 1 - 2 files changed, 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 104b25d39..66a6ed4d0 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -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. diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index b7d6493b4..a991082ee 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -53,7 +53,6 @@ async fn main(_spawner: Spawner) { &mut config_descriptor, &mut bos_descriptor, &mut control_buf, - None, ); // Create classes on the builder. -- cgit From e641db1f7565c3eb46bae04b5a8c9aef01900f53 Mon Sep 17 00:00:00 2001 From: sekoia Date: Wed, 15 Feb 2023 14:10:07 +0100 Subject: Fix a typo in "PioPeripheral" --- examples/rp/src/bin/pio_async.rs | 2 +- examples/rp/src/bin/pio_dma.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 45a8c73f7..e616d8c5a 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -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 _}; diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index b19ef4083..145e4a656 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -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 _}; -- cgit From 12d6e37b3f471186f96275b585f5512704154a17 Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Sat, 11 Mar 2023 02:58:28 -0500 Subject: Example using the PIO to drive WS2812 aka Neopixel RGB leds This example also uses a pio program compiled at runtime, rather than one built at compile time. There's no reason to do that, but it's probably useful to have an example that does this as well. --- examples/rp/src/bin/ws2812-pio.rs | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 examples/rp/src/bin/ws2812-pio.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs new file mode 100644 index 000000000..5f8a3baee --- /dev/null +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -0,0 +1,142 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::gpio::{self, Pin}; +use embassy_rp::pio::{ + FifoJoin, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, +}; +use embassy_rp::pio_instr_util; +use embassy_rp::relocate::RelocatedProgram; +use embassy_time::{Duration, Timer}; +use smart_leds::RGB8; +use {defmt_rtt as _, panic_probe as _}; +pub struct Ws2812 { + sm: PioStateMachineInstance, +} + +impl Ws2812 { + pub fn new(mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { + // Setup sm0 + + // prepare the PIO program + let side_set = pio::SideSet::new(false, 1, false); + let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set); + + const T1: u8 = 2; // start bit + const T2: u8 = 5; // data bit + const T3: u8 = 3; // stop bit + const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32; + + let mut wrap_target = a.label(); + let mut wrap_source = a.label(); + let mut do_zero = a.label(); + a.set_with_side_set(pio::SetDestination::PINDIRS, 1, 0); + a.bind(&mut wrap_target); + // Do stop bit + a.out_with_delay_and_side_set(pio::OutDestination::X, 1, T3 - 1, 0); + // Do start bit + a.jmp_with_delay_and_side_set(pio::JmpCondition::XIsZero, &mut do_zero, T1 - 1, 1); + // Do data bit = 1 + a.jmp_with_delay_and_side_set(pio::JmpCondition::Always, &mut wrap_target, T2 - 1, 1); + a.bind(&mut do_zero); + // Do data bit = 0 + a.nop_with_delay_and_side_set(T2 - 1, 0); + a.bind(&mut wrap_source); + + let prg = a.assemble_with_wrap(wrap_source, wrap_target); + + let relocated = RelocatedProgram::new(&prg); + sm.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + + // Pin config + let out_pin = sm.make_pio_pin(pin); + sm.set_set_pins(&[&out_pin]); + sm.set_sideset_base_pin(&out_pin); + sm.set_sideset_count(1); + + // Clock config + // TODO CLOCK_FREQ should come from embassy_rp + const CLOCK_FREQ: u32 = 125_000_000; + const WS2812_FREQ: u32 = 800_000; + + let bit_freq = WS2812_FREQ * CYCLES_PER_BIT; + let mut int = CLOCK_FREQ / bit_freq; + let rem = CLOCK_FREQ - (int * bit_freq); + let frac = (rem * 256) / bit_freq; + // 65536.0 is represented as 0 in the pio's clock divider + if int == 65536 { + int = 0; + } + + sm.set_clkdiv((int << 8) | frac); + let pio::Wrap { source, target } = relocated.wrap(); + sm.set_wrap(source, target); + + // FIFO config + sm.set_autopull(true); + sm.set_fifo_join(FifoJoin::TxOnly); + sm.set_pull_threshold(24); + sm.set_out_shift_dir(ShiftDirection::Left); + + sm.set_enable(true); + + Self { sm } + } + + pub async fn write(&mut self, colors: &[RGB8]) { + for color in colors { + let word = (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); + self.sm.wait_push(word).await; + } + } +} + +/// Input a value 0 to 255 to get a color value +/// The colours are a transition r - g - b - back to r. +fn wheel(mut wheel_pos: u8) -> RGB8 { + wheel_pos = 255 - wheel_pos; + if wheel_pos < 85 { + return (255 - wheel_pos * 3, 0, wheel_pos * 3).into(); + } + if wheel_pos < 170 { + wheel_pos -= 85; + return (0, wheel_pos * 3, 255 - wheel_pos * 3).into(); + } + wheel_pos -= 170; + (wheel_pos * 3, 255 - wheel_pos * 3, 0).into() +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Start"); + let p = embassy_rp::init(Default::default()); + + let (_pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); + + // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit + // feather boards for the 2040 both have one built in. + const NUM_LEDS: usize = 1; + let mut data = [RGB8::default(); NUM_LEDS]; + + // For the thing plus, use pin 8 + // For the feather, use pin 16 + let mut ws2812 = Ws2812::new(sm0, p.PIN_8.degrade()); + + // Loop forever making RGB values and pushing them out to the WS2812. + loop { + for j in 0..(256 * 5) { + debug!("New Colors:"); + for i in 0..NUM_LEDS { + data[i] = wheel((((i * 256) as u16 / NUM_LEDS as u16 + j as u16) & 255) as u8); + debug!("R: {} G: {} B: {}", data[i].r, data[i].g, data[i].b); + } + ws2812.write(&data).await; + + Timer::after(Duration::from_micros(5)).await; + } + } +} -- cgit From be37eee13dbd7833e0d74ea57d31d3e5c58cd47f Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 6 Apr 2023 22:25:24 +0200 Subject: Update embedded-hal crates. --- examples/rp/src/bin/spi_display.rs | 158 ++++++++----------------------------- 1 file changed, 35 insertions(+), 123 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 778cad3fa..85a19ce07 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -5,10 +5,13 @@ use core::cell::RefCell; use defmt::*; +use embassy_embedded_hal::shared_bus::blocking::spi::SpiDeviceWithConfig; use embassy_executor::Spawner; use embassy_rp::gpio::{Level, Output}; use embassy_rp::spi; use embassy_rp::spi::{Blocking, Spi}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::blocking_mutex::Mutex; use embassy_time::Delay; use embedded_graphics::image::{Image, ImageRawLE}; use embedded_graphics::mono_font::ascii::FONT_10X20; @@ -21,10 +24,9 @@ use st7789::{Orientation, ST7789}; use {defmt_rtt as _, panic_probe as _}; use crate::my_display_interface::SPIDeviceInterface; -use crate::shared_spi::SpiDeviceWithCs; use crate::touch::Touch; -//const DISPLAY_FREQ: u32 = 64_000_000; +const DISPLAY_FREQ: u32 = 64_000_000; const TOUCH_FREQ: u32 = 200_000; #[embassy_executor::main] @@ -43,16 +45,20 @@ async fn main(_spawner: Spawner) { //let touch_irq = p.PIN_17; // create SPI - let mut config = spi::Config::default(); - config.frequency = TOUCH_FREQ; // use the lowest freq - config.phase = spi::Phase::CaptureOnSecondTransition; - config.polarity = spi::Polarity::IdleHigh; + let mut display_config = spi::Config::default(); + display_config.frequency = DISPLAY_FREQ; + display_config.phase = spi::Phase::CaptureOnSecondTransition; + display_config.polarity = spi::Polarity::IdleHigh; + let mut touch_config = spi::Config::default(); + touch_config.frequency = TOUCH_FREQ; + touch_config.phase = spi::Phase::CaptureOnSecondTransition; + touch_config.polarity = spi::Polarity::IdleHigh; - let spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); - let spi_bus = RefCell::new(spi); + let spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, touch_config.clone()); + let spi_bus: Mutex = Mutex::new(RefCell::new(spi)); - let display_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(display_cs, Level::High)); - let touch_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(touch_cs, Level::High)); + let display_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(display_cs, Level::High), display_config); + let touch_spi = SpiDeviceWithConfig::new(&spi_bus, Output::new(touch_cs, Level::High), touch_config); let mut touch = Touch::new(touch_spi); @@ -104,85 +110,9 @@ async fn main(_spawner: Spawner) { } } -mod shared_spi { - use core::cell::RefCell; - use core::fmt::Debug; - - use embedded_hal_1::digital::OutputPin; - use embedded_hal_1::spi; - use embedded_hal_1::spi::SpiDevice; - - #[derive(Copy, Clone, Eq, PartialEq, Debug)] - pub enum SpiDeviceWithCsError { - #[allow(unused)] // will probably use in the future when adding a flush() to SpiBus - Spi(BUS), - Cs(CS), - } - - impl spi::Error for SpiDeviceWithCsError - where - BUS: spi::Error + Debug, - CS: Debug, - { - fn kind(&self) -> spi::ErrorKind { - match self { - Self::Spi(e) => e.kind(), - Self::Cs(_) => spi::ErrorKind::Other, - } - } - } - - pub struct SpiDeviceWithCs<'a, BUS, CS> { - bus: &'a RefCell, - cs: CS, - } - - impl<'a, BUS, CS> SpiDeviceWithCs<'a, BUS, CS> { - pub fn new(bus: &'a RefCell, cs: CS) -> Self { - Self { bus, cs } - } - } - - impl<'a, BUS, CS> spi::ErrorType for SpiDeviceWithCs<'a, BUS, CS> - where - BUS: spi::ErrorType, - CS: OutputPin, - { - type Error = SpiDeviceWithCsError; - } - - impl<'a, BUS, CS> SpiDevice for SpiDeviceWithCs<'a, BUS, CS> - where - BUS: spi::SpiBusFlush, - CS: OutputPin, - { - type Bus = BUS; - - fn transaction( - &mut self, - f: impl FnOnce(&mut Self::Bus) -> Result, - ) -> Result { - let mut bus = self.bus.borrow_mut(); - self.cs.set_low().map_err(SpiDeviceWithCsError::Cs)?; - - let f_res = f(&mut bus); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - let f_res = f_res.map_err(SpiDeviceWithCsError::Spi)?; - flush_res.map_err(SpiDeviceWithCsError::Spi)?; - cs_res.map_err(SpiDeviceWithCsError::Cs)?; - - Ok(f_res) - } - } -} - /// Driver for the XPT2046 resistive touchscreen sensor mod touch { - use embedded_hal_1::spi::{SpiBus, SpiBusRead, SpiBusWrite, SpiDevice}; + use embedded_hal_1::spi::{Operation, SpiDevice}; struct Calibration { x1: i32, @@ -209,7 +139,6 @@ mod touch { impl Touch where SPI: SpiDevice, - SPI::Bus: SpiBus, { pub fn new(spi: SPI) -> Self { Self { spi } @@ -219,13 +148,12 @@ mod touch { let mut x = [0; 2]; let mut y = [0; 2]; self.spi - .transaction(|bus| { - bus.write(&[0x90])?; - bus.read(&mut x)?; - bus.write(&[0xd0])?; - bus.read(&mut y)?; - Ok(()) - }) + .transaction(&mut [ + Operation::Write(&[0x90]), + Operation::Read(&mut x), + Operation::Write(&[0xd0]), + Operation::Read(&mut y), + ]) .unwrap(); let x = (u16::from_be_bytes(x) >> 3) as i32; @@ -247,7 +175,7 @@ mod touch { mod my_display_interface { use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; use embedded_hal_1::digital::OutputPin; - use embedded_hal_1::spi::{SpiBusWrite, SpiDevice}; + use embedded_hal_1::spi::SpiDeviceWrite; /// SPI display interface. /// @@ -259,8 +187,7 @@ mod my_display_interface { impl SPIDeviceInterface where - SPI: SpiDevice, - SPI::Bus: SpiBusWrite, + SPI: SpiDeviceWrite, DC: OutputPin, { /// Create new SPI interface for communciation with a display driver @@ -271,42 +198,27 @@ mod my_display_interface { impl WriteOnlyDataCommand for SPIDeviceInterface where - SPI: SpiDevice, - SPI::Bus: SpiBusWrite, + SPI: SpiDeviceWrite, DC: OutputPin, { fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> { - let r = self.spi.transaction(|bus| { - // 1 = data, 0 = command - if let Err(_) = self.dc.set_low() { - return Ok(Err(DisplayError::DCError)); - } - - // Send words over SPI - send_u8(bus, cmds)?; + // 1 = data, 0 = command + self.dc.set_low().map_err(|_| DisplayError::DCError)?; - Ok(Ok(())) - }); - r.map_err(|_| DisplayError::BusWriteError)? + send_u8(&mut self.spi, cmds).map_err(|_| DisplayError::BusWriteError)?; + Ok(()) } fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError> { - let r = self.spi.transaction(|bus| { - // 1 = data, 0 = command - if let Err(_) = self.dc.set_high() { - return Ok(Err(DisplayError::DCError)); - } - - // Send words over SPI - send_u8(bus, buf)?; + // 1 = data, 0 = command + self.dc.set_high().map_err(|_| DisplayError::DCError)?; - Ok(Ok(())) - }); - r.map_err(|_| DisplayError::BusWriteError)? + send_u8(&mut self.spi, buf).map_err(|_| DisplayError::BusWriteError)?; + Ok(()) } } - fn send_u8(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { + fn send_u8(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { match words { DataFormat::U8(slice) => spi.write(slice), DataFormat::U16(slice) => { -- cgit From a4866ad2782b5f66ed1ea67620d4117b0d474ab5 Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 21 Apr 2023 00:57:28 +0200 Subject: rp: add PWM api --- examples/rp/src/bin/pwm.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/rp/src/bin/pwm.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs new file mode 100644 index 000000000..69d315553 --- /dev/null +++ b/examples/rp/src/bin/pwm.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_embedded_hal::SetConfig; +use embassy_executor::Spawner; +use embassy_rp::pwm::{Config, Pwm}; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let mut c: Config = Default::default(); + c.top = 0x8000; + c.compare_b = 8; + let mut pwm = Pwm::new_output_b(p.PWM_CH4, p.PIN_25, c.clone()); + + loop { + info!("current LED duty cycle: {}/32768", c.compare_b); + Timer::after(Duration::from_secs(1)).await; + c.compare_b = c.compare_b.rotate_left(4); + pwm.set_config(&c); + } +} -- cgit From 73f25093c7793ad2e8bd6fceeca46d9b5b1031ad Mon Sep 17 00:00:00 2001 From: ceekdee Date: Sun, 23 Apr 2023 18:32:34 -0500 Subject: Add lora-phy examples. --- examples/rp/src/bin/lora_lorawan.rs | 80 ++++++++++++++ examples/rp/src/bin/lora_p2p_receive.rs | 115 ++++++++++++++++++++ examples/rp/src/bin/lora_p2p_send.rs | 103 ++++++++++++++++++ examples/rp/src/bin/lora_p2p_send_multicore.rs | 139 +++++++++++++++++++++++++ 4 files changed, 437 insertions(+) create mode 100644 examples/rp/src/bin/lora_lorawan.rs create mode 100644 examples/rp/src/bin/lora_p2p_receive.rs create mode 100644 examples/rp/src/bin/lora_p2p_send.rs create mode 100644 examples/rp/src/bin/lora_p2p_send_multicore.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/lora_lorawan.rs b/examples/rp/src/bin/lora_lorawan.rs new file mode 100644 index 000000000..a9c84bf95 --- /dev/null +++ b/examples/rp/src/bin/lora_lorawan.rs @@ -0,0 +1,80 @@ +//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. +//! It demonstrates LoRaWAN join functionality. +#![no_std] +#![no_main] +#![macro_use] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_lora::iv::GenericSx126xInterfaceVariant; +use embassy_lora::LoraTimer; +use embassy_rp::gpio::{Input, Level, Output, Pin, Pull}; +use embassy_rp::spi::{Config, Spi}; +use embassy_time::Delay; +use lora_phy::mod_params::*; +use lora_phy::sx1261_2::SX1261_2; +use lora_phy::LoRa; +use lorawan::default_crypto::DefaultFactory as Crypto; +use lorawan_device::async_device::lora_radio::LoRaRadio; +use lorawan_device::async_device::{region, Device, JoinMode}; +use {defmt_rtt as _, panic_probe as _}; + +const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let miso = p.PIN_12; + let mosi = p.PIN_11; + let clk = p.PIN_10; + let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + + let nss = Output::new(p.PIN_3.degrade(), Level::High); + let reset = Output::new(p.PIN_15.degrade(), Level::High); + let dio1 = Input::new(p.PIN_20.degrade(), Pull::None); + let busy = Input::new(p.PIN_2.degrade(), Pull::None); + + let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap(); + + let mut delay = Delay; + + let lora = { + match LoRa::new( + SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv), + true, + &mut delay, + ) + .await + { + Ok(l) => l, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let radio = LoRaRadio::new(lora); + let region: region::Configuration = region::Configuration::new(LORAWAN_REGION); + let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), embassy_rp::clocks::RoscRng); + + defmt::info!("Joining LoRaWAN network"); + + // TODO: Adjust the EUI and Keys according to your network credentials + match device + .join(&JoinMode::OTAA { + deveui: [0, 0, 0, 0, 0, 0, 0, 0], + appeui: [0, 0, 0, 0, 0, 0, 0, 0], + appkey: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }) + .await + { + Ok(()) => defmt::info!("LoRaWAN network joined"), + Err(err) => { + info!("Radio error = {}", err); + return; + } + }; +} diff --git a/examples/rp/src/bin/lora_p2p_receive.rs b/examples/rp/src/bin/lora_p2p_receive.rs new file mode 100644 index 000000000..250419202 --- /dev/null +++ b/examples/rp/src/bin/lora_p2p_receive.rs @@ -0,0 +1,115 @@ +//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. +//! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example. +#![no_std] +#![no_main] +#![macro_use] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_lora::iv::GenericSx126xInterfaceVariant; +use embassy_rp::gpio::{Input, Level, Output, Pin, Pull}; +use embassy_rp::spi::{Config, Spi}; +use embassy_time::{Delay, Duration, Timer}; +use lora_phy::mod_params::*; +use lora_phy::sx1261_2::SX1261_2; +use lora_phy::LoRa; +use {defmt_rtt as _, panic_probe as _}; + +const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let miso = p.PIN_12; + let mosi = p.PIN_11; + let clk = p.PIN_10; + let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + + let nss = Output::new(p.PIN_3.degrade(), Level::High); + let reset = Output::new(p.PIN_15.degrade(), Level::High); + let dio1 = Input::new(p.PIN_20.degrade(), Pull::None); + let busy = Input::new(p.PIN_2.degrade(), Pull::None); + + let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap(); + + let mut delay = Delay; + + let mut lora = { + match LoRa::new( + SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv), + false, + &mut delay, + ) + .await + { + Ok(l) => l, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let mut debug_indicator = Output::new(p.PIN_25, Level::Low); + + let mut receiving_buffer = [00u8; 100]; + + let mdltn_params = { + match lora.create_modulation_params( + SpreadingFactor::_10, + Bandwidth::_250KHz, + CodingRate::_4_8, + LORA_FREQUENCY_IN_HZ, + ) { + Ok(mp) => mp, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let rx_pkt_params = { + match lora.create_rx_packet_params(4, false, receiving_buffer.len() as u8, true, false, &mdltn_params) { + Ok(pp) => pp, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + match lora + .prepare_for_rx(&mdltn_params, &rx_pkt_params, None, true, false, 0, 0x00ffffffu32) + .await + { + Ok(()) => {} + Err(err) => { + info!("Radio error = {}", err); + return; + } + }; + + loop { + receiving_buffer = [00u8; 100]; + match lora.rx(&rx_pkt_params, &mut receiving_buffer).await { + Ok((received_len, _rx_pkt_status)) => { + if (received_len == 3) + && (receiving_buffer[0] == 0x01u8) + && (receiving_buffer[1] == 0x02u8) + && (receiving_buffer[2] == 0x03u8) + { + info!("rx successful"); + debug_indicator.set_high(); + Timer::after(Duration::from_secs(5)).await; + debug_indicator.set_low(); + } else { + info!("rx unknown packet"); + } + } + Err(err) => info!("rx unsuccessful = {}", err), + } + } +} diff --git a/examples/rp/src/bin/lora_p2p_send.rs b/examples/rp/src/bin/lora_p2p_send.rs new file mode 100644 index 000000000..3a0544b17 --- /dev/null +++ b/examples/rp/src/bin/lora_p2p_send.rs @@ -0,0 +1,103 @@ +//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. +//! It demonstrates LORA P2P send functionality. +#![no_std] +#![no_main] +#![macro_use] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_lora::iv::GenericSx126xInterfaceVariant; +use embassy_rp::gpio::{Input, Level, Output, Pin, Pull}; +use embassy_rp::spi::{Config, Spi}; +use embassy_time::Delay; +use lora_phy::mod_params::*; +use lora_phy::sx1261_2::SX1261_2; +use lora_phy::LoRa; +use {defmt_rtt as _, panic_probe as _}; + +const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + + let miso = p.PIN_12; + let mosi = p.PIN_11; + let clk = p.PIN_10; + let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + + let nss = Output::new(p.PIN_3.degrade(), Level::High); + let reset = Output::new(p.PIN_15.degrade(), Level::High); + let dio1 = Input::new(p.PIN_20.degrade(), Pull::None); + let busy = Input::new(p.PIN_2.degrade(), Pull::None); + + let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap(); + + let mut delay = Delay; + + let mut lora = { + match LoRa::new( + SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv), + false, + &mut delay, + ) + .await + { + Ok(l) => l, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let mdltn_params = { + match lora.create_modulation_params( + SpreadingFactor::_10, + Bandwidth::_250KHz, + CodingRate::_4_8, + LORA_FREQUENCY_IN_HZ, + ) { + Ok(mp) => mp, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let mut tx_pkt_params = { + match lora.create_tx_packet_params(4, false, true, false, &mdltn_params) { + Ok(pp) => pp, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + match lora.prepare_for_tx(&mdltn_params, 20, false).await { + Ok(()) => {} + Err(err) => { + info!("Radio error = {}", err); + return; + } + }; + + let buffer = [0x01u8, 0x02u8, 0x03u8]; + match lora.tx(&mdltn_params, &mut tx_pkt_params, &buffer, 0xffffff).await { + Ok(()) => { + info!("TX DONE"); + } + Err(err) => { + info!("Radio error = {}", err); + return; + } + }; + + match lora.sleep(&mut delay).await { + Ok(()) => info!("Sleep successful"), + Err(err) => info!("Sleep unsuccessful = {}", err), + } +} diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs new file mode 100644 index 000000000..5585606d8 --- /dev/null +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs @@ -0,0 +1,139 @@ +//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. +//! It demonstrates LORA P2P send functionality using the second core, with data provided by the first core. +#![no_std] +#![no_main] +#![macro_use] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Executor; +use embassy_executor::_export::StaticCell; +use embassy_lora::iv::GenericSx126xInterfaceVariant; +use embassy_rp::gpio::{AnyPin, Input, Level, Output, Pin, Pull}; +use embassy_rp::multicore::{spawn_core1, Stack}; +use embassy_rp::peripherals::SPI1; +use embassy_rp::spi::{Async, Config, Spi}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use embassy_time::{Delay, Duration, Timer}; +use lora_phy::mod_params::*; +use lora_phy::sx1261_2::SX1261_2; +use lora_phy::LoRa; +use {defmt_rtt as _, panic_probe as _}; + +static mut CORE1_STACK: Stack<4096> = Stack::new(); +static EXECUTOR0: StaticCell = StaticCell::new(); +static EXECUTOR1: StaticCell = StaticCell::new(); +static CHANNEL: Channel = Channel::new(); + +const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region + +#[cortex_m_rt::entry] +fn main() -> ! { + let p = embassy_rp::init(Default::default()); + + let miso = p.PIN_12; + let mosi = p.PIN_11; + let clk = p.PIN_10; + let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + + let nss = Output::new(p.PIN_3.degrade(), Level::High); + let reset = Output::new(p.PIN_15.degrade(), Level::High); + let dio1 = Input::new(p.PIN_20.degrade(), Pull::None); + let busy = Input::new(p.PIN_2.degrade(), Pull::None); + + let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap(); + + spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(spi, iv)))); + }); + + let executor0 = EXECUTOR0.init(Executor::new()); + executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); +} + +#[embassy_executor::task] +async fn core0_task() { + info!("Hello from core 0"); + loop { + CHANNEL.send([0x01u8, 0x02u8, 0x03u8]).await; + Timer::after(Duration::from_millis(60 * 1000)).await; + } +} + +#[embassy_executor::task] +async fn core1_task( + spi: Spi<'static, SPI1, Async>, + iv: GenericSx126xInterfaceVariant, Input<'static, AnyPin>>, +) { + info!("Hello from core 1"); + let mut delay = Delay; + + let mut lora = { + match LoRa::new( + SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv), + false, + &mut delay, + ) + .await + { + Ok(l) => l, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let mdltn_params = { + match lora.create_modulation_params( + SpreadingFactor::_10, + Bandwidth::_250KHz, + CodingRate::_4_8, + LORA_FREQUENCY_IN_HZ, + ) { + Ok(mp) => mp, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + let mut tx_pkt_params = { + match lora.create_tx_packet_params(4, false, true, false, &mdltn_params) { + Ok(pp) => pp, + Err(err) => { + info!("Radio error = {}", err); + return; + } + } + }; + + loop { + let buffer: [u8; 3] = CHANNEL.recv().await; + match lora.prepare_for_tx(&mdltn_params, 20, false).await { + Ok(()) => {} + Err(err) => { + info!("Radio error = {}", err); + return; + } + }; + + match lora.tx(&mdltn_params, &mut tx_pkt_params, &buffer, 0xffffff).await { + Ok(()) => { + info!("TX DONE"); + } + Err(err) => { + info!("Radio error = {}", err); + return; + } + }; + + match lora.sleep(&mut delay).await { + Ok(()) => info!("Sleep successful"), + Err(err) => info!("Sleep unsuccessful = {}", err), + } + } +} -- cgit From 58e727d3b9aa9d54f7c20f618fada176dcd533a9 Mon Sep 17 00:00:00 2001 From: pennae Date: Tue, 25 Apr 2023 20:16:27 +0200 Subject: rp/pio: move non-sm-specific methods to PioCommon pin and irq operations affect the entire pio block. with pins this is not very problematic since pins themselves are resources, but irqs are not treated like that and can thus interfere across state machines. the ability to wait for an irq on a state machine is kept to make synchronization with user code easier, and since we can't inspect loaded programs at build time we wouldn't gain much from disallowing waits from state machines anyway. --- examples/rp/src/bin/pio_async.rs | 20 +++++++++++++------- examples/rp/src/bin/ws2812-pio.rs | 11 ++++++----- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index e616d8c5a..3cfeec71f 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -4,13 +4,15 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; -use embassy_rp::pio::{Pio0, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2}; +use embassy_rp::pio::{ + Pio0, PioCommon, PioCommonInstance, 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 _}; -#[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { +fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance, pin: AnyPin) { // Setup sm0 // Send data serially to pin @@ -23,11 +25,11 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { ); let relocated = RelocatedProgram::new(&prg.program); - let out_pin = sm.make_pio_pin(pin); + let out_pin = pio.make_pio_pin(pin); let pio_pins = [&out_pin]; sm.set_out_pins(&pio_pins); sm.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); sm.set_set_range(0, 1); let pio::Wrap { source, target } = relocated.wrap(); @@ -35,7 +37,10 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance, pin: AnyPin) { sm.set_autopull(true); sm.set_out_shift_dir(ShiftDirection::Left); +} +#[embassy_executor::task] +async fn pio_task_sm0(mut sm: PioStateMachineInstance) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -104,9 +109,10 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (_, sm0, sm1, sm2, ..) = pio.split(); + let (mut pio0, mut sm0, sm1, sm2, ..) = pio.split(); - spawner.spawn(pio_task_sm0(sm0, p.PIN_0.degrade())).unwrap(); + setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); + spawner.spawn(pio_task_sm0(sm0)).unwrap(); spawner.spawn(pio_task_sm1(sm1)).unwrap(); spawner.spawn(pio_task_sm2(sm2)).unwrap(); } diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 5f8a3baee..211c60c49 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, + FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, + ShiftDirection, SmInstance, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; @@ -18,7 +19,7 @@ pub struct Ws2812 { } impl Ws2812 { - pub fn new(mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { + pub fn new(pio: PioCommonInstance

, mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { // Setup sm0 // prepare the PIO program @@ -53,7 +54,7 @@ impl Ws2812 { pio_instr_util::exec_jmp(&mut sm, relocated.origin()); // Pin config - let out_pin = sm.make_pio_pin(pin); + let out_pin = pio.make_pio_pin(pin); sm.set_set_pins(&[&out_pin]); sm.set_sideset_base_pin(&out_pin); sm.set_sideset_count(1); @@ -115,7 +116,7 @@ async fn main(_spawner: Spawner) { info!("Start"); let p = embassy_rp::init(Default::default()); - let (_pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); + let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit // feather boards for the 2040 both have one built in. @@ -124,7 +125,7 @@ async fn main(_spawner: Spawner) { // For the thing plus, use pin 8 // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(sm0, p.PIN_8.degrade()); + let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); // Loop forever making RGB values and pushing them out to the WS2812. loop { -- cgit From f4ade6af8bb2571ce2de0531d9c9715a7b8b941c Mon Sep 17 00:00:00 2001 From: pennae Date: Tue, 25 Apr 2023 20:40:18 +0200 Subject: rp/pio: write instr memory only from common instruction memory is a shared resource. writing it only from PioCommon clarifies this, and perhaps makes it more obvious that multiple state machines can share the same instructions. this also allows *freeing* of instruction memory to reprogram the system, although this interface is not entirely safe yet. it's safe in the sense rusts understands things, but state machines may misbehave if their instruction memory is freed and rewritten while they are running. fixing this is out of scope for now since it requires some larger changes to how state machines are handled. the interface provided currently is already unsafe in that it lets people execute instruction memory that has never been written, so this isn't much of a drawback for now. --- examples/rp/src/bin/pio_async.rs | 28 ++++++++++++++++++---------- examples/rp/src/bin/pio_dma.rs | 6 +++--- examples/rp/src/bin/ws2812-pio.rs | 4 ++-- 3 files changed, 23 insertions(+), 15 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 3cfeec71f..1b075b8fd 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -28,7 +28,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachin let out_pin = pio.make_pio_pin(pin); let pio_pins = [&out_pin]; sm.set_out_pins(&pio_pins); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio.write_instr(relocated.origin() as usize, relocated.code()); pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); sm.set_set_range(0, 1); @@ -51,16 +51,15 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance) { } } -#[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance) { +fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); let relocated = RelocatedProgram::new(&prg.program); - sm.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + pio.write_instr(relocated.origin() as usize, relocated.code()); + pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); sm.set_set_range(0, 0); let pio::Wrap { source, target } = relocated.wrap(); @@ -68,6 +67,10 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance) { sm.set_autopush(true); sm.set_in_shift_dir(ShiftDirection::Right); +} + +#[embassy_executor::task] +async fn pio_task_sm1(mut sm: PioStateMachineInstance) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -75,8 +78,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance) { } } -#[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance) { +fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -90,13 +92,17 @@ async fn pio_task_sm2(mut sm: PioStateMachineInstance) { ".wrap", ); let relocated = RelocatedProgram::new(&prg.program); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio.write_instr(relocated.origin() as usize, relocated.code()); let pio::Wrap { source, target } = relocated.wrap(); sm.set_wrap(source, target); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); +} + +#[embassy_executor::task] +async fn pio_task_sm2(mut sm: PioStateMachineInstance) { sm.set_enable(true); loop { sm.wait_irq(3).await; @@ -109,9 +115,11 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (mut pio0, mut sm0, sm1, sm2, ..) = pio.split(); + let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); + setup_pio_task_sm1(&mut pio0, &mut sm1); + setup_pio_task_sm2(&mut pio0, &mut sm2); spawner.spawn(pio_task_sm0(sm0)).unwrap(); spawner.spawn(pio_task_sm1(sm1)).unwrap(); spawner.spawn(pio_task_sm2(sm2)).unwrap(); diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 145e4a656..7d4919f75 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{PioPeripheral, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; @@ -19,7 +19,7 @@ fn swap_nibbles(v: u32) -> u32 { async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (_, mut sm, ..) = pio.split(); + let (mut pio0, mut sm, ..) = pio.split(); let prg = pio_proc::pio_asm!( ".origin 0", @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { ); let relocated = RelocatedProgram::new(&prg.program); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio0.write_instr(relocated.origin() as usize, relocated.code()); pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); let pio::Wrap { source, target } = relocated.wrap(); diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 211c60c49..041e8ae11 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -19,7 +19,7 @@ pub struct Ws2812 { } impl Ws2812 { - pub fn new(pio: PioCommonInstance

, mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { + pub fn new(mut pio: PioCommonInstance

, mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { // Setup sm0 // prepare the PIO program @@ -50,7 +50,7 @@ impl Ws2812 { let prg = a.assemble_with_wrap(wrap_source, wrap_target); let relocated = RelocatedProgram::new(&prg); - sm.write_instr(relocated.origin() as usize, relocated.code()); + pio.write_instr(relocated.origin() as usize, relocated.code()); pio_instr_util::exec_jmp(&mut sm, relocated.origin()); // Pin config -- cgit From b58b9ff390fb885f0cca2ad15fc89d537f3a9818 Mon Sep 17 00:00:00 2001 From: pennae Date: Sat, 29 Apr 2023 10:30:04 +0200 Subject: rp/uart: report errors from dma receive --- examples/rp/src/bin/uart_unidir.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index f56e7009f..4119a309f 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs @@ -7,6 +7,7 @@ use defmt::*; use embassy_executor::Spawner; +use embassy_rp::interrupt; use embassy_rp::peripherals::UART1; use embassy_rp::uart::{Async, Config, UartRx, UartTx}; use embassy_time::{Duration, Timer}; @@ -17,7 +18,13 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); - let uart_rx = UartRx::new(p.UART1, p.PIN_5, p.DMA_CH1, Config::default()); + let uart_rx = UartRx::new( + p.UART1, + p.PIN_5, + interrupt::take!(UART1_IRQ), + p.DMA_CH1, + Config::default(), + ); unwrap!(spawner.spawn(reader(uart_rx))); -- cgit From 8e22d574478d7480bc0473ed0ad9dac7d02602a8 Mon Sep 17 00:00:00 2001 From: pennae Date: Tue, 2 May 2023 10:44:00 +0200 Subject: rp/pio: add hd44780 example add an hd44780 example for pio. hd44780 with busy polling is a pretty complicated protocol if the busy polling is to be done by the peripheral, and this example exercises many pio features that we don't have good examples for yet. --- examples/rp/src/bin/pio_hd44780.rs | 244 +++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 examples/rp/src/bin/pio_hd44780.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs new file mode 100644 index 000000000..6bcd0652b --- /dev/null +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -0,0 +1,244 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::fmt::Write; + +use embassy_executor::Spawner; +use embassy_rp::dma::{AnyChannel, Channel}; +use embassy_rp::gpio::Pin; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{ + FifoJoin, PioCommon, PioInstanceBase, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, + SmInstanceBase, +}; +use embassy_rp::pwm::{Config, Pwm}; +use embassy_rp::relocate::RelocatedProgram; +use embassy_rp::{into_ref, Peripheral, PeripheralRef}; +use embassy_time::{Duration, Instant, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + // this test assumes a 2x16 HD44780 display attached as follow: + // rs = PIN0 + // rw = PIN1 + // e = PIN2 + // db4 = PIN3 + // db5 = PIN4 + // db6 = PIN5 + // db7 = PIN6 + // additionally a pwm signal for a bias voltage charge pump is provided on pin 15, + // allowing direct connection of the display to the RP2040 without level shifters. + let p = embassy_rp::init(Default::default()); + + let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, { + let mut c = Config::default(); + c.divider = 125.into(); + c.top = 100; + c.compare_b = 50; + c + }); + + let mut hd = HD44780::new( + p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, + ) + .await; + + loop { + struct Buf([u8; N], usize); + impl Write for Buf { + fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { + for b in s.as_bytes() { + if self.1 >= N { + return Err(core::fmt::Error); + } + self.0[self.1] = *b; + self.1 += 1; + } + Ok(()) + } + } + let mut buf = Buf([0; 16], 0); + write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap(); + hd.add_line(&buf.0[0..buf.1]).await; + Timer::after(Duration::from_secs(1)).await; + } +} + +pub struct HD44780<'l> { + dma: PeripheralRef<'l, AnyChannel>, + sm: PioStateMachineInstance, SmInstanceBase<0>>, + + buf: [u8; 40], +} + +impl<'l> HD44780<'l> { + pub async fn new( + pio: PIO0, + dma: impl Peripheral

+ 'l, + rs: impl Pin, + rw: impl Pin, + e: impl Pin, + db4: impl Pin, + db5: impl Pin, + db6: impl Pin, + db7: impl Pin, + ) -> HD44780<'l> { + into_ref!(dma); + + let db7pin = db7.pin(); + let (mut common, mut sm0, ..) = pio.split(); + + // takes command words ( <0:4>) + let prg = pio_proc::pio_asm!( + r#" + .side_set 1 opt + + loop: + out x, 24 + delay: + jmp x--, delay + out pins, 4 side 1 + out null, 4 side 0 + jmp !osre, loop + irq 0 + "#, + ); + + let rs = common.make_pio_pin(rs); + let rw = common.make_pio_pin(rw); + let e = common.make_pio_pin(e); + let db4 = common.make_pio_pin(db4); + let db5 = common.make_pio_pin(db5); + let db6 = common.make_pio_pin(db6); + let db7 = common.make_pio_pin(db7); + + sm0.set_set_pins(&[&rs, &rw]); + embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11); + sm0.set_set_pins(&[&e]); + embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1); + sm0.set_set_pins(&[&db4, &db5, &db6, &db7]); + embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111); + + let relocated = RelocatedProgram::new(&prg.program); + common.write_instr(relocated.origin() as usize, relocated.code()); + embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin()); + sm0.set_clkdiv(125 * 256); + let pio::Wrap { source, target } = relocated.wrap(); + sm0.set_wrap(source, target); + sm0.set_side_enable(true); + sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); + sm0.set_sideset_base_pin(&e); + sm0.set_sideset_count(2); + sm0.set_out_shift_dir(ShiftDirection::Left); + sm0.set_fifo_join(FifoJoin::TxOnly); + sm0.set_autopull(true); + sm0.set_pull_threshold(32); + + sm0.set_enable(true); + // init to 8 bit thrice + sm0.push_tx((50000 << 8) | 0x30); + sm0.push_tx((5000 << 8) | 0x30); + sm0.push_tx((200 << 8) | 0x30); + // init 4 bit + sm0.push_tx((200 << 8) | 0x20); + // set font and lines + sm0.push_tx((50 << 8) | 0x20); + sm0.push_tx(0b1100_0000); + + sm0.wait_irq(0).await; + sm0.set_enable(false); + + // takes command sequences ( , data...) + // many side sets are only there to free up a delay bit! + let prg = pio_proc::pio_asm!( + r#" + .origin 7 + .side_set 1 + + .wrap_target + pull side 0 + out x 1 side 0 ; !rs + out y 7 side 0 ; #data - 1 + + ; rs/rw to e: >= 60ns + ; e high time: >= 500ns + ; e low time: >= 500ns + ; read data valid after e falling: ~5ns + ; write data hold after e falling: ~10ns + + loop: + pull side 0 + jmp !x data side 0 + command: + set pins 0b00 side 0 + jmp shift side 0 + data: + set pins 0b01 side 0 + shift: + out pins 4 side 1 [9] + nop side 0 [9] + out pins 4 side 1 [9] + mov osr null side 0 [7] + out pindirs 4 side 0 + set pins 0b10 side 0 + busy: + nop side 1 [9] + jmp pin more side 0 [9] + mov osr ~osr side 1 [9] + nop side 0 [4] + out pindirs 4 side 0 + jmp y-- loop side 0 + .wrap + more: + nop side 1 [9] + jmp busy side 0 [9] + "# + ); + + let relocated = RelocatedProgram::new(&prg.program); + common.write_instr(relocated.origin() as usize, relocated.code()); + embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin()); + let pio::Wrap { source, target } = relocated.wrap(); + sm0.set_clkdiv(8 * 256); // ~64ns/insn + sm0.set_side_enable(false); + sm0.set_jmp_pin(db7pin); + sm0.set_wrap(source, target); + sm0.set_set_pins(&[&rs, &rw]); + sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); + sm0.set_sideset_base_pin(&e); + sm0.set_sideset_count(1); + sm0.set_out_shift_dir(ShiftDirection::Left); + sm0.set_fifo_join(FifoJoin::TxOnly); + + sm0.set_enable(true); + + // display on and cursor on and blinking, reset display + sm0.dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await; + + Self { + dma: dma.map_into(), + sm: sm0, + buf: [0x20; 40], + } + } + + pub async fn add_line(&mut self, s: &[u8]) { + // move cursor to 0:0, prepare 16 characters + self.buf[..3].copy_from_slice(&[0x80, 0x80, 15]); + // move line 2 up + self.buf.copy_within(22..38, 3); + // move cursor to 1:0, prepare 16 characters + self.buf[19..22].copy_from_slice(&[0x80, 0xc0, 15]); + // file line 2 with spaces + self.buf[22..38].fill(0x20); + // copy input line + let len = s.len().min(16); + self.buf[22..22 + len].copy_from_slice(&s[0..len]); + // set cursor to 1:15 + self.buf[38..].copy_from_slice(&[0x80, 0xcf]); + + self.sm.dma_push(self.dma.reborrow(), &self.buf).await; + } +} -- cgit From 3229b5e809688d99a592bbfd1f803e1fb9d62050 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 26 Apr 2023 00:23:18 +0200 Subject: rp/pio: remove PioPeripheral merge into PioInstance instead. PioPeripheral was mostly a wrapper around PioInstance anyway, and the way the wrapping was done required PioInstanceBase types where PIO{N} could've been used instead. --- examples/rp/src/bin/pio_async.rs | 16 ++++++++-------- examples/rp/src/bin/pio_dma.rs | 2 +- examples/rp/src/bin/pio_hd44780.rs | 5 ++--- examples/rp/src/bin/ws2812-pio.rs | 4 ++-- 4 files changed, 13 insertions(+), 14 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 1b075b8fd..16a09327f 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -4,15 +4,15 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; +use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ - Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, - Sm1, Sm2, + PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance, pin: AnyPin) { +fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance, pin: AnyPin) { // Setup sm0 // Send data serially to pin @@ -40,7 +40,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance) { +async fn pio_task_sm0(mut sm: PioStateMachineInstance) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -51,7 +51,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance) { } } -fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full @@ -70,7 +70,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance) { +async fn pio_task_sm1(mut sm: PioStateMachineInstance) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -78,7 +78,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance) { } } -fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -102,7 +102,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance) { +async fn pio_task_sm2(mut sm: PioStateMachineInstance) { sm.set_enable(true); loop { sm.wait_irq(3).await; diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 7d4919f75..ccbc70fe2 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{PioCommon, PioInstance, PioStateMachine, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 6bcd0652b..1b24897b0 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -9,8 +9,7 @@ use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::gpio::Pin; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ - FifoJoin, PioCommon, PioInstanceBase, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, - SmInstanceBase, + FifoJoin, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase, }; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; @@ -68,7 +67,7 @@ async fn main(_spawner: Spawner) { pub struct HD44780<'l> { dma: PeripheralRef<'l, AnyChannel>, - sm: PioStateMachineInstance, SmInstanceBase<0>>, + sm: PioStateMachineInstance>, buf: [u8; 40], } diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 041e8ae11..592caf244 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,8 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, - ShiftDirection, SmInstance, + FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, + SmInstance, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; -- cgit From 8839f3f62ab85a1abd066fcbfa15693965e6fae8 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 26 Apr 2023 19:43:57 +0200 Subject: rp/pio: PioInstance::split -> Pio::new not requiring a PioInstance for splitting lets us split from a PeripheralRef or borrowed PIO as well, mirroring every other peripheral in embassy_rp. pio pins still have to be constructed from owned pin instances for now. --- examples/rp/src/bin/pio_async.rs | 24 +++++++++++++++--------- examples/rp/src/bin/pio_dma.rs | 10 +++++++--- examples/rp/src/bin/pio_hd44780.rs | 10 ++++++---- examples/rp/src/bin/ws2812-pio.rs | 18 +++++++++++------- 4 files changed, 39 insertions(+), 23 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 16a09327f..69a22f238 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -6,7 +6,7 @@ use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ - PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2, + Pio, PioCommon, PioCommonInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; @@ -40,7 +40,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance) { +async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, Sm0>) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -70,7 +70,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance) { +async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, Sm1>) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -102,7 +102,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachin } #[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance) { +async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, Sm2>) { sm.set_enable(true); loop { sm.wait_irq(3).await; @@ -115,11 +115,17 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); - - setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); - setup_pio_task_sm1(&mut pio0, &mut sm1); - setup_pio_task_sm2(&mut pio0, &mut sm2); + let Pio { + mut common, + mut sm0, + mut sm1, + mut sm2, + .. + } = Pio::new(pio); + + setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade()); + setup_pio_task_sm1(&mut common, &mut sm1); + setup_pio_task_sm2(&mut common, &mut sm2); spawner.spawn(pio_task_sm0(sm0)).unwrap(); spawner.spawn(pio_task_sm1(sm1)).unwrap(); spawner.spawn(pio_task_sm2(sm2)).unwrap(); diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index ccbc70fe2..33c320b8f 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{PioCommon, PioInstance, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; @@ -19,7 +19,11 @@ fn swap_nibbles(v: u32) -> u32 { async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let pio = p.PIO0; - let (mut pio0, mut sm, ..) = pio.split(); + let Pio { + mut common, + sm0: mut sm, + .. + } = Pio::new(pio); let prg = pio_proc::pio_asm!( ".origin 0", @@ -34,7 +38,7 @@ async fn main(_spawner: Spawner) { ); let relocated = RelocatedProgram::new(&prg.program); - pio0.write_instr(relocated.origin() as usize, relocated.code()); + common.write_instr(relocated.origin() as usize, relocated.code()); pio_instr_util::exec_jmp(&mut sm, relocated.origin()); sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); let pio::Wrap { source, target } = relocated.wrap(); diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 1b24897b0..994d4600a 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -9,7 +9,7 @@ use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::gpio::Pin; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ - FifoJoin, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase, + FifoJoin, Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase, }; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; @@ -67,14 +67,14 @@ async fn main(_spawner: Spawner) { pub struct HD44780<'l> { dma: PeripheralRef<'l, AnyChannel>, - sm: PioStateMachineInstance>, + sm: PioStateMachineInstance<'l, PIO0, SmInstanceBase<0>>, buf: [u8; 40], } impl<'l> HD44780<'l> { pub async fn new( - pio: PIO0, + pio: impl Peripheral

+ 'l, dma: impl Peripheral

+ 'l, rs: impl Pin, rw: impl Pin, @@ -87,7 +87,9 @@ impl<'l> HD44780<'l> { into_ref!(dma); let db7pin = db7.pin(); - let (mut common, mut sm0, ..) = pio.split(); + let Pio { + mut common, mut sm0, .. + } = Pio::new(pio); // takes command words ( <0:4>) let prg = pio_proc::pio_asm!( diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 592caf244..42c731bd7 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, + FifoJoin, Pio, PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, }; use embassy_rp::pio_instr_util; @@ -14,12 +14,16 @@ use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; -pub struct Ws2812 { - sm: PioStateMachineInstance, +pub struct Ws2812<'d, P: PioInstance, S: SmInstance> { + sm: PioStateMachineInstance<'d, P, S>, } -impl Ws2812 { - pub fn new(mut pio: PioCommonInstance

, mut sm: PioStateMachineInstance, pin: gpio::AnyPin) -> Self { +impl<'d, P: PioInstance, S: SmInstance> Ws2812<'d, P, S> { + pub fn new( + mut pio: PioCommonInstance<'d, P>, + mut sm: PioStateMachineInstance<'d, P, S>, + pin: gpio::AnyPin, + ) -> Self { // Setup sm0 // prepare the PIO program @@ -116,7 +120,7 @@ async fn main(_spawner: Spawner) { info!("Start"); let p = embassy_rp::init(Default::default()); - let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split(); + let Pio { common, sm0, .. } = Pio::new(p.PIO0); // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit // feather boards for the 2040 both have one built in. @@ -125,7 +129,7 @@ async fn main(_spawner: Spawner) { // For the thing plus, use pin 8 // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade()); + let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade()); // Loop forever making RGB values and pushing them out to the WS2812. loop { -- cgit From a167c77d3928e1304ccccec6ddf7572d1e3c4cd9 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 26 Apr 2023 20:27:31 +0200 Subject: rp/pio: make PioCommon a struct the PioCommon trait does not serve much of a purpose; there can be only two implementations and they only differ in a few associated constants. --- examples/rp/src/bin/pio_async.rs | 10 ++++------ examples/rp/src/bin/pio_dma.rs | 2 +- examples/rp/src/bin/pio_hd44780.rs | 4 +--- examples/rp/src/bin/ws2812-pio.rs | 9 ++------- 4 files changed, 8 insertions(+), 17 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 69a22f238..50b001b69 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -5,14 +5,12 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{ - Pio, PioCommon, PioCommonInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2, -}; +use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance, pin: AnyPin) { +fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstance, pin: AnyPin) { // Setup sm0 // Send data serially to pin @@ -51,7 +49,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, Sm0>) { } } -fn setup_pio_task_sm1(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full @@ -78,7 +76,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, Sm1>) { } } -fn setup_pio_task_sm2(pio: &mut PioCommonInstance, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { // Setup sm2 // Repeatedly trigger IRQ 3 diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 33c320b8f..0f1f6df12 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Pio, PioStateMachine, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 994d4600a..20c6a0565 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -8,9 +8,7 @@ use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::gpio::Pin; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{ - FifoJoin, Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase, -}; +use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase}; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 42c731bd7..a2121df42 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,8 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, Pio, PioCommon, PioCommonInstance, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, - SmInstance, + FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; @@ -19,11 +18,7 @@ pub struct Ws2812<'d, P: PioInstance, S: SmInstance> { } impl<'d, P: PioInstance, S: SmInstance> Ws2812<'d, P, S> { - pub fn new( - mut pio: PioCommonInstance<'d, P>, - mut sm: PioStateMachineInstance<'d, P, S>, - pin: gpio::AnyPin, - ) -> Self { + pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self { // Setup sm0 // prepare the PIO program -- cgit From 7a36072a15b2164a903ae3f36ee251eaf311216d Mon Sep 17 00:00:00 2001 From: pennae Date: Tue, 2 May 2023 17:55:40 +0200 Subject: rp/pio: drop SmInstance{,Base} these are just overly convoluted ways of writing down numbers. --- examples/rp/src/bin/pio_async.rs | 14 +++++++------- examples/rp/src/bin/pio_hd44780.rs | 4 ++-- examples/rp/src/bin/ws2812-pio.rs | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 50b001b69..5fea7034b 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -5,12 +5,12 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::gpio::{AnyPin, Pin}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0, Sm1, Sm2}; +use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstance, pin: AnyPin) { +fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstance, pin: AnyPin) { // Setup sm0 // Send data serially to pin @@ -38,7 +38,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstanc } #[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, Sm0>) { +async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -49,7 +49,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, Sm0>) { } } -fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full @@ -68,7 +68,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachineInstanc } #[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, Sm1>) { +async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -76,7 +76,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, Sm1>) { } } -fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -100,7 +100,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachineInstanc } #[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, Sm2>) { +async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, 2>) { sm.set_enable(true); loop { sm.wait_irq(3).await; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 20c6a0565..59b4c1f52 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -8,7 +8,7 @@ use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::gpio::Pin; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstanceBase}; +use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection}; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; @@ -65,7 +65,7 @@ async fn main(_spawner: Spawner) { pub struct HD44780<'l> { dma: PeripheralRef<'l, AnyChannel>, - sm: PioStateMachineInstance<'l, PIO0, SmInstanceBase<0>>, + sm: PioStateMachineInstance<'l, PIO0, 0>, buf: [u8; 40], } diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index a2121df42..0975559d7 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -6,18 +6,18 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, SmInstance, + FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; -pub struct Ws2812<'d, P: PioInstance, S: SmInstance> { +pub struct Ws2812<'d, P: PioInstance, const S: usize> { sm: PioStateMachineInstance<'d, P, S>, } -impl<'d, P: PioInstance, S: SmInstance> Ws2812<'d, P, S> { +impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self { // Setup sm0 -- cgit From 4ccb2bc95aab6202d6f53882a59265427cdd5655 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 3 May 2023 08:15:46 +0200 Subject: rp/pio: add PioPin trait pio can only access pins in bank 0, so it doesn't make sense to even allow wrapping of other banks' pins. --- examples/rp/src/bin/pio_async.rs | 7 +++---- examples/rp/src/bin/pio_hd44780.rs | 17 ++++++++--------- examples/rp/src/bin/ws2812-pio.rs | 7 +++---- 3 files changed, 14 insertions(+), 17 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 5fea7034b..154cc6b65 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -3,14 +3,13 @@ #![feature(type_alias_impl_trait)] use defmt::info; use embassy_executor::Spawner; -use embassy_rp::gpio::{AnyPin, Pin}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection}; +use embassy_rp::pio::{Pio, PioCommon, PioPin, PioStateMachine, PioStateMachineInstance, ShiftDirection}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstance, pin: AnyPin) { +fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstance, pin: impl PioPin) { // Setup sm0 // Send data serially to pin @@ -121,7 +120,7 @@ async fn main(spawner: Spawner) { .. } = Pio::new(pio); - setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade()); + setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); setup_pio_task_sm1(&mut common, &mut sm1); setup_pio_task_sm2(&mut common, &mut sm2); spawner.spawn(pio_task_sm0(sm0)).unwrap(); diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 59b4c1f52..6d56bc233 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -6,9 +6,8 @@ use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; -use embassy_rp::gpio::Pin; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection}; +use embassy_rp::pio::{FifoJoin, Pio, PioPin, PioStateMachine, PioStateMachineInstance, ShiftDirection}; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; @@ -74,13 +73,13 @@ impl<'l> HD44780<'l> { pub async fn new( pio: impl Peripheral

+ 'l, dma: impl Peripheral

+ 'l, - rs: impl Pin, - rw: impl Pin, - e: impl Pin, - db4: impl Pin, - db5: impl Pin, - db6: impl Pin, - db7: impl Pin, + rs: impl PioPin, + rw: impl PioPin, + e: impl PioPin, + db4: impl PioPin, + db5: impl PioPin, + db6: impl PioPin, + db7: impl PioPin, ) -> HD44780<'l> { into_ref!(dma); diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 0975559d7..8276fad64 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -4,9 +4,8 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::gpio::{self, Pin}; use embassy_rp::pio::{ - FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection, + FifoJoin, Pio, PioCommon, PioInstance, PioPin, PioStateMachine, PioStateMachineInstance, ShiftDirection, }; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; @@ -18,7 +17,7 @@ pub struct Ws2812<'d, P: PioInstance, const S: usize> { } impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { - pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self { + pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: impl PioPin) -> Self { // Setup sm0 // prepare the PIO program @@ -124,7 +123,7 @@ async fn main(_spawner: Spawner) { // For the thing plus, use pin 8 // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade()); + let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8); // Loop forever making RGB values and pushing them out to the WS2812. loop { -- cgit From 906d2b2db78d287ad818ab2a7abb1fec572ac6f6 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 3 May 2023 09:42:42 +0200 Subject: rp/pio: PioStateMachine{Instance, => ,Instance} next step: get rid of the insance trait entirely --- examples/rp/src/bin/pio_async.rs | 12 ++++++------ examples/rp/src/bin/pio_dma.rs | 2 +- examples/rp/src/bin/pio_hd44780.rs | 2 +- examples/rp/src/bin/ws2812-pio.rs | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 154cc6b65..8c02f9f16 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -9,7 +9,7 @@ use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstance, pin: impl PioPin) { +fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachine, pin: impl PioPin) { // Setup sm0 // Send data serially to pin @@ -37,7 +37,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachineInstanc } #[embassy_executor::task] -async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) { +async fn pio_task_sm0(mut sm: PioStateMachine<'static, PIO0, 0>) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -48,7 +48,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) { } } -fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachine) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full @@ -67,7 +67,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachineInstanc } #[embassy_executor::task] -async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) { +async fn pio_task_sm1(mut sm: PioStateMachine<'static, PIO0, 1>) { sm.set_enable(true); loop { let rx = sm.wait_pull().await; @@ -75,7 +75,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) { } } -fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachineInstance) { +fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachine) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -99,7 +99,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachineInstanc } #[embassy_executor::task] -async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, 2>) { +async fn pio_task_sm2(mut sm: PioStateMachine<'static, PIO0, 2>) { sm.set_enable(true); loop { sm.wait_irq(3).await; diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 0f1f6df12..a351e2c7c 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{Pio, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Pio, PioStateMachineInstance, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 6d56bc233..249711a32 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -64,7 +64,7 @@ async fn main(_spawner: Spawner) { pub struct HD44780<'l> { dma: PeripheralRef<'l, AnyChannel>, - sm: PioStateMachineInstance<'l, PIO0, 0>, + sm: PioStateMachine<'l, PIO0, 0>, buf: [u8; 40], } diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 8276fad64..c141560e5 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -13,11 +13,11 @@ use embassy_time::{Duration, Timer}; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; pub struct Ws2812<'d, P: PioInstance, const S: usize> { - sm: PioStateMachineInstance<'d, P, S>, + sm: PioStateMachine<'d, P, S>, } impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { - pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: impl PioPin) -> Self { + pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachine<'d, P, S>, pin: impl PioPin) -> Self { // Setup sm0 // prepare the PIO program -- cgit From 486fe9e59da7474c5162f56d89d5b6c279d02753 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 3 May 2023 10:18:24 +0200 Subject: rp/pio: remove PioStateMachineInstance move all methods into PioStateMachine instead. the huge trait wasn't object-safe and thus didn't have any benefits whatsoever except for making it *slightly* easier to write bounds for passing around state machines. that would be much better solved with generics-less instances. --- examples/rp/src/bin/pio_async.rs | 2 +- examples/rp/src/bin/pio_dma.rs | 2 +- examples/rp/src/bin/pio_hd44780.rs | 2 +- examples/rp/src/bin/ws2812-pio.rs | 4 +--- 4 files changed, 4 insertions(+), 6 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 8c02f9f16..11b290869 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Pio, PioCommon, PioPin, PioStateMachine, PioStateMachineInstance, ShiftDirection}; +use embassy_rp::pio::{Pio, PioCommon, PioPin, PioStateMachine, ShiftDirection}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index a351e2c7c..a2a2ee39a 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{Pio, PioStateMachineInstance, ShiftDirection}; +use embassy_rp::pio::{Pio, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 249711a32..bc51d43c4 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -7,7 +7,7 @@ use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{FifoJoin, Pio, PioPin, PioStateMachine, PioStateMachineInstance, ShiftDirection}; +use embassy_rp::pio::{FifoJoin, Pio, PioPin, PioStateMachine, ShiftDirection}; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index c141560e5..713e01b44 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -4,9 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::pio::{ - FifoJoin, Pio, PioCommon, PioInstance, PioPin, PioStateMachine, PioStateMachineInstance, ShiftDirection, -}; +use embassy_rp::pio::{FifoJoin, Pio, PioCommon, PioInstance, PioPin, PioStateMachine, ShiftDirection}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; -- cgit From 909a5fe2e513ef91129a29ccdd8772824879383c Mon Sep 17 00:00:00 2001 From: pennae Date: Thu, 27 Apr 2023 02:12:49 +0200 Subject: rp/pio: split irqs from state machines we can only have one active waiter for any given irq at any given time. allowing waits for irqs on state machines bypasses this limitation and causes lost events for all but the latest waiter for a given irq. splitting this out also allows us to signal from state machines to other parts of the application without monopolizing state machine access for the irq wait, as would be necessary to make irq waiting sound. --- examples/rp/src/bin/pio_async.rs | 9 +++++---- examples/rp/src/bin/pio_hd44780.rs | 7 +++++-- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 11b290869..3d76a7d7b 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -4,7 +4,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Pio, PioCommon, PioPin, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Pio, PioCommon, PioIrq, PioPin, PioStateMachine, ShiftDirection}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; @@ -99,10 +99,10 @@ fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachine) { +async fn pio_task_sm2(mut irq: PioIrq<'static, PIO0, 3>, mut sm: PioStateMachine<'static, PIO0, 2>) { sm.set_enable(true); loop { - sm.wait_irq(3).await; + irq.wait().await; info!("IRQ trigged"); } } @@ -114,6 +114,7 @@ async fn main(spawner: Spawner) { let Pio { mut common, + irq3, mut sm0, mut sm1, mut sm2, @@ -125,5 +126,5 @@ async fn main(spawner: Spawner) { setup_pio_task_sm2(&mut common, &mut sm2); spawner.spawn(pio_task_sm0(sm0)).unwrap(); spawner.spawn(pio_task_sm1(sm1)).unwrap(); - spawner.spawn(pio_task_sm2(sm2)).unwrap(); + spawner.spawn(pio_task_sm2(irq3, sm2)).unwrap(); } diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index bc51d43c4..7c1d7acfe 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -85,7 +85,10 @@ impl<'l> HD44780<'l> { let db7pin = db7.pin(); let Pio { - mut common, mut sm0, .. + mut common, + mut irq0, + mut sm0, + .. } = Pio::new(pio); // takes command words ( <0:4>) @@ -145,7 +148,7 @@ impl<'l> HD44780<'l> { sm0.push_tx((50 << 8) | 0x20); sm0.push_tx(0b1100_0000); - sm0.wait_irq(0).await; + irq0.wait().await; sm0.set_enable(false); // takes command sequences ( , data...) -- cgit From c44c108db57cbe34e21411054840f61c61efa8a8 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 3 May 2023 12:49:55 +0200 Subject: rp/pio: wrap sm rx, tx in structs and allow splitting this *finally* allows sound implementions of bidirectional transfers without blocking. the futures previously allowed only a single direction to be active at any given time, and the dma transfers didn't take a mutable reference and were thus unsound. --- examples/rp/src/bin/pio_async.rs | 4 ++-- examples/rp/src/bin/pio_dma.rs | 5 +++-- examples/rp/src/bin/pio_hd44780.rs | 16 ++++++++-------- examples/rp/src/bin/ws2812-pio.rs | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 3d76a7d7b..4e0ab5e3c 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -42,7 +42,7 @@ async fn pio_task_sm0(mut sm: PioStateMachine<'static, PIO0, 0>) { let mut v = 0x0f0caffa; loop { - sm.wait_push(v).await; + sm.tx().wait_push(v).await; v ^= 0xffff; info!("Pushed {:032b} to FIFO", v); } @@ -70,7 +70,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachine) { sm.set_enable(true); loop { - let rx = sm.wait_pull().await; + let rx = sm.rx().wait_pull().await; info!("Pulled {:032b} from FIFO", rx); } } diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index a2a2ee39a..c664482e5 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -60,9 +60,10 @@ async fn main(_spawner: Spawner) { } let mut din = [0u32; 29]; loop { + let (rx, tx) = sm.rx_tx(); join( - sm.dma_push(dma_out_ref.reborrow(), &dout), - sm.dma_pull(dma_in_ref.reborrow(), &mut din), + tx.dma_push(dma_out_ref.reborrow(), &dout), + rx.dma_pull(dma_in_ref.reborrow(), &mut din), ) .await; for i in 0..din.len() { diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 7c1d7acfe..f76d334e7 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -139,14 +139,14 @@ impl<'l> HD44780<'l> { sm0.set_enable(true); // init to 8 bit thrice - sm0.push_tx((50000 << 8) | 0x30); - sm0.push_tx((5000 << 8) | 0x30); - sm0.push_tx((200 << 8) | 0x30); + sm0.tx().push((50000 << 8) | 0x30); + sm0.tx().push((5000 << 8) | 0x30); + sm0.tx().push((200 << 8) | 0x30); // init 4 bit - sm0.push_tx((200 << 8) | 0x20); + sm0.tx().push((200 << 8) | 0x20); // set font and lines - sm0.push_tx((50 << 8) | 0x20); - sm0.push_tx(0b1100_0000); + sm0.tx().push((50 << 8) | 0x20); + sm0.tx().push(0b1100_0000); irq0.wait().await; sm0.set_enable(false); @@ -216,7 +216,7 @@ impl<'l> HD44780<'l> { sm0.set_enable(true); // display on and cursor on and blinking, reset display - sm0.dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await; + sm0.tx().dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await; Self { dma: dma.map_into(), @@ -240,6 +240,6 @@ impl<'l> HD44780<'l> { // set cursor to 1:15 self.buf[38..].copy_from_slice(&[0x80, 0xcf]); - self.sm.dma_push(self.dma.reborrow(), &self.buf).await; + self.sm.tx().dma_push(self.dma.reborrow(), &self.buf).await; } } diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 713e01b44..c9c701a70 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -87,7 +87,7 @@ impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { pub async fn write(&mut self, colors: &[RGB8]) { for color in colors { let word = (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); - self.sm.wait_push(word).await; + self.sm.tx().wait_push(word).await; } } } -- cgit From 8ebe6e5f2029026594c703820c11d703da2c0334 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 3 May 2023 17:16:35 +0200 Subject: rp/pio: drop Pio prefix from almost all names it's only any good for PioPin because there it follows a pattern of gpio pin alternate functions being named like that, everything else can just as well be referred to as `pio::Thing` --- examples/rp/src/bin/pio_async.rs | 14 +++++++------- examples/rp/src/bin/pio_hd44780.rs | 4 ++-- examples/rp/src/bin/ws2812-pio.rs | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 4e0ab5e3c..461ea3ff9 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -4,12 +4,12 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Pio, PioCommon, PioIrq, PioPin, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Common, Irq, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachine, pin: impl PioPin) { +fn setup_pio_task_sm0(pio: &mut Common, sm: &mut StateMachine, pin: impl PioPin) { // Setup sm0 // Send data serially to pin @@ -37,7 +37,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommon, sm: &mut PioStateMachine) { +async fn pio_task_sm0(mut sm: StateMachine<'static, PIO0, 0>) { sm.set_enable(true); let mut v = 0x0f0caffa; @@ -48,7 +48,7 @@ async fn pio_task_sm0(mut sm: PioStateMachine<'static, PIO0, 0>) { } } -fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachine) { +fn setup_pio_task_sm1(pio: &mut Common, sm: &mut StateMachine) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full @@ -67,7 +67,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommon, sm: &mut PioStateMachine) { +async fn pio_task_sm1(mut sm: StateMachine<'static, PIO0, 1>) { sm.set_enable(true); loop { let rx = sm.rx().wait_pull().await; @@ -75,7 +75,7 @@ async fn pio_task_sm1(mut sm: PioStateMachine<'static, PIO0, 1>) { } } -fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachine) { +fn setup_pio_task_sm2(pio: &mut Common, sm: &mut StateMachine) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -99,7 +99,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommon, sm: &mut PioStateMachine, mut sm: PioStateMachine<'static, PIO0, 2>) { +async fn pio_task_sm2(mut irq: Irq<'static, PIO0, 3>, mut sm: StateMachine<'static, PIO0, 2>) { sm.set_enable(true); loop { irq.wait().await; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index f76d334e7..17b2440cf 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -7,7 +7,7 @@ use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{FifoJoin, Pio, PioPin, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{FifoJoin, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; @@ -64,7 +64,7 @@ async fn main(_spawner: Spawner) { pub struct HD44780<'l> { dma: PeripheralRef<'l, AnyChannel>, - sm: PioStateMachine<'l, PIO0, 0>, + sm: StateMachine<'l, PIO0, 0>, buf: [u8; 40], } diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index c9c701a70..2e6860d8b 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -4,18 +4,18 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::pio::{FifoJoin, Pio, PioCommon, PioInstance, PioPin, PioStateMachine, ShiftDirection}; +use embassy_rp::pio::{Common, FifoJoin, Instance, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; -pub struct Ws2812<'d, P: PioInstance, const S: usize> { - sm: PioStateMachine<'d, P, S>, +pub struct Ws2812<'d, P: Instance, const S: usize> { + sm: StateMachine<'d, P, S>, } -impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { - pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachine<'d, P, S>, pin: impl PioPin) -> Self { +impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { + pub fn new(mut pio: Common<'d, P>, mut sm: StateMachine<'d, P, S>, pin: impl PioPin) -> Self { // Setup sm0 // prepare the PIO program -- cgit From 41ec4170a5ae9920fe31327252ba1bba754b6d9f Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 5 May 2023 19:49:34 +0200 Subject: rp/pio: add load_program, use_program programs contain information we could pull from them directly and use to validate other configuration of the state machine instead of asking the user to pull them out and hand them to us bit by bit. unfortunately programs do not specify how many in or out bits they use, so we can only handle side-set and wrapping jumps like this. it's still something though. --- examples/rp/src/bin/pio_async.rs | 25 ++++++------------------- examples/rp/src/bin/pio_dma.rs | 7 ++----- examples/rp/src/bin/pio_hd44780.rs | 16 ++-------------- examples/rp/src/bin/ws2812-pio.rs | 13 +++---------- 4 files changed, 13 insertions(+), 48 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 461ea3ff9..9f47c2316 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -5,11 +5,10 @@ use defmt::info; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{Common, Irq, Pio, PioPin, ShiftDirection, StateMachine}; -use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; -fn setup_pio_task_sm0(pio: &mut Common, sm: &mut StateMachine, pin: impl PioPin) { +fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { // Setup sm0 // Send data serially to pin @@ -22,15 +21,12 @@ fn setup_pio_task_sm0(pio: &mut Common, sm: &mut StateMachine, pi ); let relocated = RelocatedProgram::new(&prg.program); + sm.use_program(&pio.load_program(&relocated), &[]); let out_pin = pio.make_pio_pin(pin); let pio_pins = [&out_pin]; sm.set_out_pins(&pio_pins); - pio.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(sm, relocated.origin()); sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); sm.set_set_range(0, 1); - let pio::Wrap { source, target } = relocated.wrap(); - sm.set_wrap(source, target); sm.set_autopull(true); sm.set_out_shift_dir(ShiftDirection::Left); @@ -48,20 +44,16 @@ async fn pio_task_sm0(mut sm: StateMachine<'static, PIO0, 0>) { } } -fn setup_pio_task_sm1(pio: &mut Common, sm: &mut StateMachine) { +fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 1>) { // Setupm sm1 // Read 0b10101 repeatedly until ISR is full let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); let relocated = RelocatedProgram::new(&prg.program); - pio.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(sm, relocated.origin()); + sm.use_program(&pio.load_program(&relocated), &[]); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); sm.set_set_range(0, 0); - let pio::Wrap { source, target } = relocated.wrap(); - sm.set_wrap(source, target); - sm.set_autopush(true); sm.set_in_shift_dir(ShiftDirection::Right); } @@ -75,7 +67,7 @@ async fn pio_task_sm1(mut sm: StateMachine<'static, PIO0, 1>) { } } -fn setup_pio_task_sm2(pio: &mut Common, sm: &mut StateMachine) { +fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 2>) { // Setup sm2 // Repeatedly trigger IRQ 3 @@ -89,12 +81,7 @@ fn setup_pio_task_sm2(pio: &mut Common, sm: &mut StateMachine) { ".wrap", ); let relocated = RelocatedProgram::new(&prg.program); - pio.write_instr(relocated.origin() as usize, relocated.code()); - - let pio::Wrap { source, target } = relocated.wrap(); - sm.set_wrap(source, target); - - pio_instr_util::exec_jmp(sm, relocated.origin()); + sm.use_program(&pio.load_program(&relocated), &[]); sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); } diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index c664482e5..1c4e127c7 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -6,7 +6,7 @@ use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_rp::pio::{Pio, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::{pio_instr_util, Peripheral}; +use embassy_rp::Peripheral; use {defmt_rtt as _, panic_probe as _}; fn swap_nibbles(v: u32) -> u32 { @@ -38,11 +38,8 @@ async fn main(_spawner: Spawner) { ); let relocated = RelocatedProgram::new(&prg.program); - common.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); + sm.use_program(&common.load_program(&relocated), &[]); sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); - let pio::Wrap { source, target } = relocated.wrap(); - sm.set_wrap(source, target); sm.set_autopull(true); sm.set_autopush(true); sm.set_pull_threshold(32); diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 17b2440cf..c3466b554 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -123,15 +123,9 @@ impl<'l> HD44780<'l> { embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111); let relocated = RelocatedProgram::new(&prg.program); - common.write_instr(relocated.origin() as usize, relocated.code()); - embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin()); + sm0.use_program(&common.load_program(&relocated), &[&e]); sm0.set_clkdiv(125 * 256); - let pio::Wrap { source, target } = relocated.wrap(); - sm0.set_wrap(source, target); - sm0.set_side_enable(true); sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); - sm0.set_sideset_base_pin(&e); - sm0.set_sideset_count(2); sm0.set_out_shift_dir(ShiftDirection::Left); sm0.set_fifo_join(FifoJoin::TxOnly); sm0.set_autopull(true); @@ -199,17 +193,11 @@ impl<'l> HD44780<'l> { ); let relocated = RelocatedProgram::new(&prg.program); - common.write_instr(relocated.origin() as usize, relocated.code()); - embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin()); - let pio::Wrap { source, target } = relocated.wrap(); + sm0.use_program(&common.load_program(&relocated), &[&e]); sm0.set_clkdiv(8 * 256); // ~64ns/insn - sm0.set_side_enable(false); sm0.set_jmp_pin(db7pin); - sm0.set_wrap(source, target); sm0.set_set_pins(&[&rs, &rw]); sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); - sm0.set_sideset_base_pin(&e); - sm0.set_sideset_count(1); sm0.set_out_shift_dir(ShiftDirection::Left); sm0.set_fifo_join(FifoJoin::TxOnly); diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 2e6860d8b..889970541 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -5,7 +5,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::pio::{Common, FifoJoin, Instance, Pio, PioPin, ShiftDirection, StateMachine}; -use embassy_rp::pio_instr_util; use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; use smart_leds::RGB8; @@ -45,15 +44,11 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { let prg = a.assemble_with_wrap(wrap_source, wrap_target); - let relocated = RelocatedProgram::new(&prg); - pio.write_instr(relocated.origin() as usize, relocated.code()); - pio_instr_util::exec_jmp(&mut sm, relocated.origin()); - // Pin config let out_pin = pio.make_pio_pin(pin); - sm.set_set_pins(&[&out_pin]); - sm.set_sideset_base_pin(&out_pin); - sm.set_sideset_count(1); + + let relocated = RelocatedProgram::new(&prg); + sm.use_program(&pio.load_program(&relocated), &[&out_pin]); // Clock config // TODO CLOCK_FREQ should come from embassy_rp @@ -70,8 +65,6 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { } sm.set_clkdiv((int << 8) | frac); - let pio::Wrap { source, target } = relocated.wrap(); - sm.set_wrap(source, target); // FIFO config sm.set_autopull(true); -- cgit From 37b460637df0a20885ba8a0fbb0699e2d44ee4ec Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 5 May 2023 20:45:02 +0200 Subject: rp/pio: add set-pin-{values,dirs} convenience functions these are needed a lot during state machine setup, it makes sense to provide convenience functions for them. --- examples/rp/src/bin/pio_hd44780.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index c3466b554..40dee1c4d 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -7,7 +7,7 @@ use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{FifoJoin, Pio, PioPin, ShiftDirection, StateMachine}; +use embassy_rp::pio::{Direction, FifoJoin, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::pwm::{Config, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; @@ -115,12 +115,7 @@ impl<'l> HD44780<'l> { let db6 = common.make_pio_pin(db6); let db7 = common.make_pio_pin(db7); - sm0.set_set_pins(&[&rs, &rw]); - embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11); - sm0.set_set_pins(&[&e]); - embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1); - sm0.set_set_pins(&[&db4, &db5, &db6, &db7]); - embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111); + sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); let relocated = RelocatedProgram::new(&prg.program); sm0.use_program(&common.load_program(&relocated), &[&e]); -- cgit From 8e4d65e163bd484efc4fb31d20b14e6ac4a88de7 Mon Sep 17 00:00:00 2001 From: pennae Date: Sat, 6 May 2023 11:36:07 +0200 Subject: rp/pio: configure state machines with Config struct the many individual sets aren't very efficient, and almost no checks were done to ensure that the configuration written to the hardware was actually valid. this adresses both of these. --- examples/rp/src/bin/pio_async.rs | 37 ++++++++++++++++++--------------- examples/rp/src/bin/pio_dma.rs | 27 ++++++++++++++++-------- examples/rp/src/bin/pio_hd44780.rs | 42 ++++++++++++++++++++++---------------- examples/rp/src/bin/ws2812-pio.rs | 39 ++++++++++++++++------------------- 4 files changed, 81 insertions(+), 64 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 9f47c2316..12484e882 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -2,10 +2,13 @@ #![no_main] #![feature(type_alias_impl_trait)] use defmt::info; +use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Common, Irq, Pio, PioPin, ShiftDirection, StateMachine}; +use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::relocate::RelocatedProgram; +use fixed::traits::ToFixed; +use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { @@ -21,15 +24,14 @@ fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, ); let relocated = RelocatedProgram::new(&prg.program); - sm.use_program(&pio.load_program(&relocated), &[]); + let mut cfg = Config::default(); + cfg.use_program(&pio.load_program(&relocated), &[]); let out_pin = pio.make_pio_pin(pin); - let pio_pins = [&out_pin]; - sm.set_out_pins(&pio_pins); - sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); - sm.set_set_range(0, 1); - - sm.set_autopull(true); - sm.set_out_shift_dir(ShiftDirection::Left); + cfg.set_out_pins(&[&out_pin]); + cfg.set_set_pins(&[&out_pin]); + cfg.clock_divider = (U56F8!(125_000_000) / 20 / 200).to_fixed(); + cfg.shift_out.auto_fill = true; + sm.set_config(&cfg); } #[embassy_executor::task] @@ -51,11 +53,12 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); let relocated = RelocatedProgram::new(&prg.program); - sm.use_program(&pio.load_program(&relocated), &[]); - sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); - sm.set_set_range(0, 0); - sm.set_autopush(true); - sm.set_in_shift_dir(ShiftDirection::Right); + let mut cfg = Config::default(); + cfg.use_program(&pio.load_program(&relocated), &[]); + cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); + cfg.shift_in.auto_fill = true; + cfg.shift_in.direction = ShiftDirection::Right; + sm.set_config(&cfg); } #[embassy_executor::task] @@ -81,8 +84,10 @@ fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, ".wrap", ); let relocated = RelocatedProgram::new(&prg.program); - sm.use_program(&pio.load_program(&relocated), &[]); - sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); + let mut cfg = Config::default(); + cfg.use_program(&pio.load_program(&relocated), &[]); + cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); + sm.set_config(&cfg); } #[embassy_executor::task] diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 1c4e127c7..7f85288bf 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -2,11 +2,14 @@ #![no_main] #![feature(type_alias_impl_trait)] use defmt::info; +use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{Pio, ShiftDirection}; +use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::Peripheral; +use fixed::traits::ToFixed; +use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; fn swap_nibbles(v: u32) -> u32 { @@ -38,15 +41,21 @@ async fn main(_spawner: Spawner) { ); let relocated = RelocatedProgram::new(&prg.program); - sm.use_program(&common.load_program(&relocated), &[]); - sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); - sm.set_autopull(true); - sm.set_autopush(true); - sm.set_pull_threshold(32); - sm.set_push_threshold(32); - sm.set_out_shift_dir(ShiftDirection::Right); - sm.set_in_shift_dir(ShiftDirection::Left); + let mut cfg = Config::default(); + cfg.use_program(&common.load_program(&relocated), &[]); + cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); + cfg.shift_in = ShiftConfig { + auto_fill: true, + threshold: 32, + direction: ShiftDirection::Left, + }; + cfg.shift_out = ShiftConfig { + auto_fill: true, + threshold: 32, + direction: ShiftDirection::Right, + }; + sm.set_config(&cfg); sm.set_enable(true); let mut dma_out_ref = p.DMA_CH0.into_ref(); diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 40dee1c4d..61c5565d3 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -4,11 +4,12 @@ use core::fmt::Write; +use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Direction, FifoJoin, Pio, PioPin, ShiftDirection, StateMachine}; -use embassy_rp::pwm::{Config, Pwm}; +use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; +use embassy_rp::pwm::{self, Pwm}; use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Instant, Timer}; @@ -29,7 +30,7 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, { - let mut c = Config::default(); + let mut c = pwm::Config::default(); c.divider = 125.into(); c.top = 100; c.compare_b = 50; @@ -83,7 +84,6 @@ impl<'l> HD44780<'l> { ) -> HD44780<'l> { into_ref!(dma); - let db7pin = db7.pin(); let Pio { mut common, mut irq0, @@ -118,13 +118,17 @@ impl<'l> HD44780<'l> { sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); let relocated = RelocatedProgram::new(&prg.program); - sm0.use_program(&common.load_program(&relocated), &[&e]); - sm0.set_clkdiv(125 * 256); - sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); - sm0.set_out_shift_dir(ShiftDirection::Left); - sm0.set_fifo_join(FifoJoin::TxOnly); - sm0.set_autopull(true); - sm0.set_pull_threshold(32); + let mut cfg = Config::default(); + cfg.use_program(&common.load_program(&relocated), &[&e]); + cfg.clock_divider = 125u8.into(); + cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); + cfg.shift_out = ShiftConfig { + auto_fill: true, + direction: ShiftDirection::Left, + threshold: 32, + }; + cfg.fifo_join = FifoJoin::TxOnly; + sm0.set_config(&cfg); sm0.set_enable(true); // init to 8 bit thrice @@ -188,13 +192,15 @@ impl<'l> HD44780<'l> { ); let relocated = RelocatedProgram::new(&prg.program); - sm0.use_program(&common.load_program(&relocated), &[&e]); - sm0.set_clkdiv(8 * 256); // ~64ns/insn - sm0.set_jmp_pin(db7pin); - sm0.set_set_pins(&[&rs, &rw]); - sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); - sm0.set_out_shift_dir(ShiftDirection::Left); - sm0.set_fifo_join(FifoJoin::TxOnly); + let mut cfg = Config::default(); + cfg.use_program(&common.load_program(&relocated), &[&e]); + cfg.clock_divider = 8u8.into(); // ~64ns/insn + cfg.set_jmp_pin(&db7); + cfg.set_set_pins(&[&rs, &rw]); + cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); + cfg.shift_out.direction = ShiftDirection::Left; + cfg.fifo_join = FifoJoin::TxOnly; + sm0.set_config(&cfg); sm0.set_enable(true); diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 889970541..d7c4742d8 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -3,10 +3,12 @@ #![feature(type_alias_impl_trait)] use defmt::*; +use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; -use embassy_rp::pio::{Common, FifoJoin, Instance, Pio, PioPin, ShiftDirection, StateMachine}; +use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; use embassy_rp::relocate::RelocatedProgram; use embassy_time::{Duration, Timer}; +use fixed_macro::fixed; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; pub struct Ws2812<'d, P: Instance, const S: usize> { @@ -43,35 +45,30 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { a.bind(&mut wrap_source); let prg = a.assemble_with_wrap(wrap_source, wrap_target); + let mut cfg = Config::default(); // Pin config let out_pin = pio.make_pio_pin(pin); let relocated = RelocatedProgram::new(&prg); - sm.use_program(&pio.load_program(&relocated), &[&out_pin]); + cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); - // Clock config + // Clock config, measured in kHz to avoid overflows // TODO CLOCK_FREQ should come from embassy_rp - const CLOCK_FREQ: u32 = 125_000_000; - const WS2812_FREQ: u32 = 800_000; - - let bit_freq = WS2812_FREQ * CYCLES_PER_BIT; - let mut int = CLOCK_FREQ / bit_freq; - let rem = CLOCK_FREQ - (int * bit_freq); - let frac = (rem * 256) / bit_freq; - // 65536.0 is represented as 0 in the pio's clock divider - if int == 65536 { - int = 0; - } - - sm.set_clkdiv((int << 8) | frac); + let clock_freq = fixed!(125_000: U24F8); + let ws2812_freq = fixed!(800: U24F8); + let bit_freq = ws2812_freq * CYCLES_PER_BIT; + cfg.clock_divider = clock_freq / bit_freq; // FIFO config - sm.set_autopull(true); - sm.set_fifo_join(FifoJoin::TxOnly); - sm.set_pull_threshold(24); - sm.set_out_shift_dir(ShiftDirection::Left); - + cfg.fifo_join = FifoJoin::TxOnly; + cfg.shift_out = ShiftConfig { + auto_fill: true, + threshold: 24, + direction: ShiftDirection::Left, + }; + + sm.set_config(&cfg); sm.set_enable(true); Self { sm } -- cgit From b38d496d519f87d7f455e6c6b32f5d6379af44a5 Mon Sep 17 00:00:00 2001 From: pennae Date: Sat, 6 May 2023 20:53:06 +0200 Subject: rp/pio: allow wrap-around program loading execution wraps around after the end of instruction memory and wrapping works with this, so we may as well allow program loading across this boundary. could be useful for reusing chunks of instruction memory. --- examples/rp/src/bin/pio_hd44780.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 61c5565d3..088fd5649 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -95,6 +95,7 @@ impl<'l> HD44780<'l> { let prg = pio_proc::pio_asm!( r#" .side_set 1 opt + .origin 20 loop: out x, 24 @@ -148,7 +149,7 @@ impl<'l> HD44780<'l> { // many side sets are only there to free up a delay bit! let prg = pio_proc::pio_asm!( r#" - .origin 7 + .origin 27 .side_set 1 .wrap_target -- cgit From 87795cbca84a67ce9c5bdb5c3043b41251d75bbc Mon Sep 17 00:00:00 2001 From: Fabian Kunze Date: Sun, 7 May 2023 01:00:13 +0200 Subject: added example multi priority executors rp2040 --- examples/rp/src/bin/multiprio.rs | 152 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 examples/rp/src/bin/multiprio.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs new file mode 100644 index 000000000..2f79ba49e --- /dev/null +++ b/examples/rp/src/bin/multiprio.rs @@ -0,0 +1,152 @@ +//! This example showcases how to create multiple Executor instances to run tasks at +//! different priority levels. +//! +//! Low priority executor runs in thread mode (not interrupt), and uses `sev` for signaling +//! there's work in the queue, and `wfe` for waiting for work. +//! +//! Medium and high priority executors run in two interrupts with different priorities. +//! Signaling work is done by pending the interrupt. No "waiting" needs to be done explicitly, since +//! when there's work the interrupt will trigger and run the executor. +//! +//! Sample output below. Note that high priority ticks can interrupt everything else, and +//! medium priority computations can interrupt low priority computations, making them to appear +//! to take significantly longer time. +//! +//! ```not_rust +//! [med] Starting long computation +//! [med] done in 992 ms +//! [high] tick! +//! [low] Starting long computation +//! [med] Starting long computation +//! [high] tick! +//! [high] tick! +//! [med] done in 993 ms +//! [med] Starting long computation +//! [high] tick! +//! [high] tick! +//! [med] done in 993 ms +//! [low] done in 3972 ms +//! [med] Starting long computation +//! [high] tick! +//! [high] tick! +//! [med] done in 993 ms +//! ``` +//! +//! For comparison, try changing the code so all 3 tasks get spawned on the low priority executor. +//! You will get an output like the following. Note that no computation is ever interrupted. +//! +//! ```not_rust +//! [high] tick! +//! [med] Starting long computation +//! [med] done in 496 ms +//! [low] Starting long computation +//! [low] done in 992 ms +//! [med] Starting long computation +//! [med] done in 496 ms +//! [high] tick! +//! [low] Starting long computation +//! [low] done in 992 ms +//! [high] tick! +//! [med] Starting long computation +//! [med] done in 496 ms +//! [high] tick! +//! ``` +//! + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::mem; + +use cortex_m::peripheral::NVIC; +use cortex_m_rt::entry; +use defmt::{info, unwrap}; +use embassy_rp::executor::{Executor, InterruptExecutor}; +use embassy_rp::interrupt; +use embassy_rp::pac::Interrupt; +use embassy_time::{Duration, Instant, Timer, TICK_HZ}; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn run_high() { + loop { + info!(" [high] tick!"); + Timer::after(Duration::from_ticks(673740)).await; + } +} + +#[embassy_executor::task] +async fn run_med() { + loop { + let start = Instant::now(); + info!(" [med] Starting long computation"); + + // Spin-wait to simulate a long CPU computation + cortex_m::asm::delay(125_000_000); // ~1 second + + let end = Instant::now(); + let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ; + info!(" [med] done in {} ms", ms); + + Timer::after(Duration::from_ticks(53421)).await; + } +} + +#[embassy_executor::task] +async fn run_low() { + loop { + let start = Instant::now(); + info!("[low] Starting long computation"); + + // Spin-wait to simulate a long CPU computation + cortex_m::asm::delay(250_000_000); // ~2 seconds + + let end = Instant::now(); + let ms = end.duration_since(start).as_ticks() * 1000 / TICK_HZ; + info!("[low] done in {} ms", ms); + + Timer::after(Duration::from_ticks(82983)).await; + } +} + +static EXECUTOR_HIGH: InterruptExecutor = InterruptExecutor::new(); +static EXECUTOR_MED: InterruptExecutor = InterruptExecutor::new(); +static EXECUTOR_LOW: StaticCell = StaticCell::new(); + +#[interrupt] +unsafe fn SWI_IRQ_1() { + EXECUTOR_HIGH.on_interrupt() +} + +#[interrupt] +unsafe fn SWI_IRQ_0() { + EXECUTOR_MED.on_interrupt() +} + +#[entry] +fn main() -> ! { + info!("Hello World!"); + + let _p = embassy_rp::init(Default::default()); + let mut nvic: NVIC = unsafe { mem::transmute(()) }; + + // High-priority executor: SWI_IRQ_1, priority level 2 + unsafe { nvic.set_priority(Interrupt::SWI_IRQ_1, 2 << 6) }; + info!("bla: {}", NVIC::get_priority(Interrupt::SWI_IRQ_1)); + let spawner = EXECUTOR_HIGH.start(Interrupt::SWI_IRQ_1); + unwrap!(spawner.spawn(run_high())); + + // Medium-priority executor: SWI_IRQ_0, priority level 3 + unsafe { nvic.set_priority(Interrupt::SWI_IRQ_0, 3 << 6) }; + info!("bla: {}", NVIC::get_priority(Interrupt::SWI_IRQ_0)); + let spawner = EXECUTOR_MED.start(Interrupt::SWI_IRQ_0); + unwrap!(spawner.spawn(run_med())); + + // Low priority executor: runs in thread mode, using WFE/SEV + let executor = EXECUTOR_LOW.init(Executor::new()); + executor.run(|spawner| { + unwrap!(spawner.spawn(run_low())); + }); +} -- cgit From 59132514cfd04709bffb119642baf9d0dcf4733a Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Mon, 8 May 2023 09:43:58 -0400 Subject: Add missing functions, Cleanup, Gpout example --- examples/rp/src/bin/gpout.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 examples/rp/src/bin/gpout.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs new file mode 100644 index 000000000..0503212e8 --- /dev/null +++ b/examples/rp/src/bin/gpout.rs @@ -0,0 +1,21 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::{clocks, pac}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + //let mut led = Output::new(p.PIN_25, Level::Low); + + let gpout0 = clocks::Gpout0::new(p.PIN_21); + gpout0.set_src(pac::clocks::vals::ClkGpout0ctrlAuxsrc::CLK_SYS); + gpout0.set_div(1000, 0); + gpout0.enable(); + + info!("Pin 21 should be toggling at {} hz", clocks::clk_gpout0_freq()); +} -- cgit From 0584312ef0324d2ac67dbb9517176fabf628eec9 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Mon, 8 May 2023 23:25:01 +0200 Subject: Fix some typos --- examples/rp/src/bin/usb_serial.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index a991082ee..8160a1875 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) { config.max_power = 100; config.max_packet_size_0 = 64; - // Required for windows compatiblity. + // Required for windows compatibility. // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help config.device_class = 0xEF; config.device_sub_class = 0x02; -- cgit From 5015c845c59e8769d404dce5ca618cdf6fd16aeb Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Tue, 9 May 2023 12:10:24 -0400 Subject: Improve gpout example, clk_gpout_freq --- examples/rp/src/bin/gpout.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs index 0503212e8..ea0efb859 100644 --- a/examples/rp/src/bin/gpout.rs +++ b/examples/rp/src/bin/gpout.rs @@ -5,17 +5,30 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::{clocks, pac}; +use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - //let mut led = Output::new(p.PIN_25, Level::Low); - let gpout0 = clocks::Gpout0::new(p.PIN_21); - gpout0.set_src(pac::clocks::vals::ClkGpout0ctrlAuxsrc::CLK_SYS); - gpout0.set_div(1000, 0); - gpout0.enable(); + let gpout3 = clocks::Gpout::new(p.PIN_25); + gpout3.set_div(1000, 0); + gpout3.enable(); - info!("Pin 21 should be toggling at {} hz", clocks::clk_gpout0_freq()); + loop { + gpout3.set_src(pac::clocks::vals::ClkGpoutCtrlAuxsrc::CLK_SYS); + info!( + "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}", + clocks::clk_gpout_freq(&gpout3) + ); + Timer::after(Duration::from_secs(2)).await; + + gpout3.set_src(pac::clocks::vals::ClkGpoutCtrlAuxsrc::CLK_REF); + info!( + "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}", + clocks::clk_gpout_freq(&gpout3) + ); + Timer::after(Duration::from_secs(2)).await; + } } -- cgit From 5cfe1a1fb40470dfaf256fc87989fd67884113f1 Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Tue, 9 May 2023 17:45:24 -0400 Subject: Dirbaio comments round 2 --- examples/rp/src/bin/gpout.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs index ea0efb859..236a653ac 100644 --- a/examples/rp/src/bin/gpout.rs +++ b/examples/rp/src/bin/gpout.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::{clocks, pac}; +use embassy_rp::clocks; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -17,17 +17,17 @@ async fn main(_spawner: Spawner) { gpout3.enable(); loop { - gpout3.set_src(pac::clocks::vals::ClkGpoutCtrlAuxsrc::CLK_SYS); + gpout3.set_src(clocks::GpoutSrc::CLK_SYS); info!( "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}", - clocks::clk_gpout_freq(&gpout3) + gpout3.get_freq() ); Timer::after(Duration::from_secs(2)).await; - gpout3.set_src(pac::clocks::vals::ClkGpoutCtrlAuxsrc::CLK_REF); + gpout3.set_src(clocks::GpoutSrc::CLK_REF); info!( "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}", - clocks::clk_gpout_freq(&gpout3) + gpout3.get_freq() ); Timer::after(Duration::from_secs(2)).await; } -- cgit From 2fcdfc48762849d4de4686f9a4098db49c4031e6 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 13 May 2023 02:11:01 +0200 Subject: rp: don't use SetConfig trait in PWM and PIO. It was intended to allow changing baudrate on shared spi/i2c. There's no advantage in using it for PWM or PIO, and makes it less usable because you have to have `embassy-embedded-hal` as a dep to use it. --- examples/rp/src/bin/pio_async.rs | 1 - examples/rp/src/bin/pio_dma.rs | 1 - examples/rp/src/bin/pio_hd44780.rs | 1 - examples/rp/src/bin/pwm.rs | 1 - examples/rp/src/bin/ws2812-pio.rs | 1 - 5 files changed, 5 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 12484e882..79eda1a09 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -2,7 +2,6 @@ #![no_main] #![feature(type_alias_impl_trait)] use defmt::info; -use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 7f85288bf..05c0ebb16 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -2,7 +2,6 @@ #![no_main] #![feature(type_alias_impl_trait)] use defmt::info; -use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 088fd5649..bfc6c9908 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -4,7 +4,6 @@ use core::fmt::Write; -use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 69d315553..2b3d5d97a 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs @@ -3,7 +3,6 @@ #![feature(type_alias_impl_trait)] use defmt::*; -use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_rp::pwm::{Config, Pwm}; use embassy_time::{Duration, Timer}; diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index d7c4742d8..f4c2d6313 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs @@ -3,7 +3,6 @@ #![feature(type_alias_impl_trait)] use defmt::*; -use embassy_embedded_hal::SetConfig; use embassy_executor::Spawner; use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; use embassy_rp::relocate::RelocatedProgram; -- cgit From 26d7610554f262c2c25f99fb441e6dbd6abec61f Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 15 May 2023 00:38:58 +0200 Subject: net: do not use smoltcp Instant/Duration in public API. --- examples/rp/src/bin/usb_ethernet.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 66a6ed4d0..431db63eb 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -114,7 +114,7 @@ async fn main(spawner: Spawner) { loop { let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + socket.set_timeout(Some(embassy_time::Duration::from_secs(10))); info!("Listening on TCP:1234..."); if let Err(e) = socket.accept(1234).await { -- cgit From 14a5d03af2a74eccaa9930bdf81eef43791a4b33 Mon Sep 17 00:00:00 2001 From: pennae Date: Mon, 15 May 2023 15:21:05 +0200 Subject: rp: remove take!, add bind_interrupts! --- examples/rp/src/bin/adc.rs | 11 +++++++---- examples/rp/src/bin/i2c_async.rs | 12 ++++++++---- examples/rp/src/bin/uart_buffered_split.rs | 11 +++++++---- examples/rp/src/bin/uart_unidir.rs | 16 +++++++--------- examples/rp/src/bin/usb_ethernet.rs | 12 ++++++++---- examples/rp/src/bin/usb_logger.rs | 11 +++++++---- examples/rp/src/bin/usb_serial.rs | 12 ++++++++---- 7 files changed, 52 insertions(+), 33 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 4202fd394..7c2ca19f7 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -4,16 +4,19 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::adc::{Adc, Config}; -use embassy_rp::interrupt; +use embassy_rp::adc::{Adc, Config, InterruptHandler}; +use embassy_rp::bind_interrupts; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + ADC_IRQ_FIFO => InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - let irq = interrupt::take!(ADC_IRQ_FIFO); - let mut adc = Adc::new(p.ADC, irq, Config::default()); + let mut adc = Adc::new(p.ADC, Irqs, Config::default()); let mut p26 = p.PIN_26; let mut p27 = p.PIN_27; diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs index d1a2e3cd7..cf3cf742c 100644 --- a/examples/rp/src/bin/i2c_async.rs +++ b/examples/rp/src/bin/i2c_async.rs @@ -4,12 +4,17 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::i2c::{self, Config}; -use embassy_rp::interrupt; +use embassy_rp::bind_interrupts; +use embassy_rp::i2c::{self, Config, InterruptHandler}; +use embassy_rp::peripherals::I2C1; use embassy_time::{Duration, Timer}; use embedded_hal_async::i2c::I2c; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + I2C1_IRQ => InterruptHandler; +}); + #[allow(dead_code)] mod mcp23017 { pub const ADDR: u8 = 0x20; // default addr @@ -64,10 +69,9 @@ async fn main(_spawner: Spawner) { let sda = p.PIN_14; let scl = p.PIN_15; - let irq = interrupt::take!(I2C1_IRQ); info!("set up i2c "); - let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, irq, Config::default()); + let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, Config::default()); use mcp23017::*; diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index a8a682274..d6f01b4de 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -5,13 +5,17 @@ use defmt::*; use embassy_executor::Spawner; use embassy_executor::_export::StaticCell; -use embassy_rp::interrupt; +use embassy_rp::bind_interrupts; use embassy_rp::peripherals::UART0; -use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config}; +use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::{Read, Write}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + UART0_IRQ => BufferedInterruptHandler; +}); + macro_rules! singleton { ($val:expr) => {{ type T = impl Sized; @@ -26,10 +30,9 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); - let irq = interrupt::take!(UART0_IRQ); let tx_buf = &mut singleton!([0u8; 16])[..]; let rx_buf = &mut singleton!([0u8; 16])[..]; - let uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); + let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); let (rx, mut tx) = uart.split(); unwrap!(spawner.spawn(reader(rx))); diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index 4119a309f..c0943a1b8 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs @@ -7,24 +7,22 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::interrupt; +use embassy_rp::bind_interrupts; use embassy_rp::peripherals::UART1; -use embassy_rp::uart::{Async, Config, UartRx, UartTx}; +use embassy_rp::uart::{Async, Config, InterruptHandler, UartRx, UartTx}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + UART1_IRQ => InterruptHandler; +}); + #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); - let uart_rx = UartRx::new( - p.UART1, - p.PIN_5, - interrupt::take!(UART1_IRQ), - p.DMA_CH1, - Config::default(), - ); + let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default()); unwrap!(spawner.spawn(reader(uart_rx))); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 66a6ed4d0..2ddfb6344 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -6,8 +6,9 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Stack, StackResources}; -use embassy_rp::usb::Driver; -use embassy_rp::{interrupt, peripherals}; +use embassy_rp::peripherals::USB; +use embassy_rp::usb::{Driver, InterruptHandler}; +use embassy_rp::{bind_interrupts, peripherals}; use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; @@ -15,6 +16,10 @@ use embedded_io::asynch::Write; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler; +}); + type MyDriver = Driver<'static, peripherals::USB>; macro_rules! singleton { @@ -48,8 +53,7 @@ async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); // Create the driver, from the HAL. - let irq = interrupt::take!(USBCTRL_IRQ); - let driver = Driver::new(p.USB, irq); + let driver = Driver::new(p.USB, Irqs); // Create embassy-usb Config let mut config = Config::new(0xc0de, 0xcafe); diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs index 52417a02e..7c90d0ca3 100644 --- a/examples/rp/src/bin/usb_logger.rs +++ b/examples/rp/src/bin/usb_logger.rs @@ -3,12 +3,16 @@ #![feature(type_alias_impl_trait)] use embassy_executor::Spawner; -use embassy_rp::interrupt; +use embassy_rp::bind_interrupts; use embassy_rp::peripherals::USB; -use embassy_rp::usb::Driver; +use embassy_rp::usb::{Driver, InterruptHandler}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler; +}); + #[embassy_executor::task] async fn logger_task(driver: Driver<'static, USB>) { embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); @@ -17,8 +21,7 @@ async fn logger_task(driver: Driver<'static, USB>) { #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); - let irq = interrupt::take!(USBCTRL_IRQ); - let driver = Driver::new(p.USB, irq); + let driver = Driver::new(p.USB, Irqs); spawner.spawn(logger_task(driver)).unwrap(); let mut counter = 0; diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 8160a1875..ca728536c 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -5,13 +5,18 @@ use defmt::{info, panic}; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::interrupt; -use embassy_rp::usb::{Driver, Instance}; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::USB; +use embassy_rp::usb::{Driver, Instance, InterruptHandler}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::{Builder, Config}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { info!("Hello there!"); @@ -19,8 +24,7 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); // Create the driver, from the HAL. - let irq = interrupt::take!(USBCTRL_IRQ); - let driver = Driver::new(p.USB, irq); + let driver = Driver::new(p.USB, Irqs); // Create embassy-usb Config let mut config = Config::new(0xc0de, 0xcafe); -- cgit From ab63f3832fdceeea994500042594e0b7c0acac95 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Tue, 16 May 2023 11:21:17 +0200 Subject: rp: Read flash unique id and jedec id --- examples/rp/src/bin/flash.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index 8d6b379f4..19076150c 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs @@ -24,6 +24,16 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(10)).await; let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH); + + // Get JEDEC id + let jedec = flash.jedec_id().unwrap(); + info!("jedec id: 0x{:x}", jedec); + + // Get unique id + let mut uid = [0; 8]; + flash.unique_id(&mut uid).unwrap(); + info!("unique id: {:?}", uid); + erase_write_sector(&mut flash, 0x00); multiwrite_bytes(&mut flash, ERASE_SIZE as u32); -- cgit From f97b591831cab5ec29cfdb7cb98bc93debfdb57e Mon Sep 17 00:00:00 2001 From: pennae Date: Tue, 16 May 2023 18:13:15 +0200 Subject: rp/clocks: don't expose unstable pac items exposing pac items kind of undermines the unstable-pac feature. directly exposing register structure is also pretty inconvenient since the clock switching code takes care of the src/aux difference in behavior, so a user needn't really be forced to write down decomposed register values. --- examples/rp/src/bin/gpout.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs index 236a653ac..64461fc5f 100644 --- a/examples/rp/src/bin/gpout.rs +++ b/examples/rp/src/bin/gpout.rs @@ -17,14 +17,14 @@ async fn main(_spawner: Spawner) { gpout3.enable(); loop { - gpout3.set_src(clocks::GpoutSrc::CLK_SYS); + gpout3.set_src(clocks::GpoutSrc::Sys); info!( "Pin 25 is now outputing CLK_SYS/1000, should be toggling at {}", gpout3.get_freq() ); Timer::after(Duration::from_secs(2)).await; - gpout3.set_src(clocks::GpoutSrc::CLK_REF); + gpout3.set_src(clocks::GpoutSrc::Ref); info!( "Pin 25 is now outputing CLK_REF/1000, should be toggling at {}", gpout3.get_freq() -- cgit From 1be6e533165cb773979739c203b745df24ff1ecf Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Tue, 9 May 2023 17:05:39 -0400 Subject: Pin fix, improve fifo handling --- examples/rp/src/bin/pio_ws2812.rs | 132 ++++++++++++++++++++++++++++++++++++++ examples/rp/src/bin/ws2812-pio.rs | 128 ------------------------------------ 2 files changed, 132 insertions(+), 128 deletions(-) create mode 100644 examples/rp/src/bin/pio_ws2812.rs delete mode 100644 examples/rp/src/bin/ws2812-pio.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs new file mode 100644 index 000000000..4915c7e92 --- /dev/null +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -0,0 +1,132 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; +use embassy_rp::relocate::RelocatedProgram; +use embassy_time::{Duration, Timer}; +use fixed_macro::fixed; +use smart_leds::RGB8; +use {defmt_rtt as _, panic_probe as _}; +pub struct Ws2812<'d, P: Instance, const S: usize> { + sm: StateMachine<'d, P, S>, +} + +impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { + pub fn new(mut pio: Common<'d, P>, mut sm: StateMachine<'d, P, S>, pin: impl PioPin) -> Self { + // Setup sm0 + + // prepare the PIO program + let side_set = pio::SideSet::new(false, 1, false); + let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set); + + const T1: u8 = 2; // start bit + const T2: u8 = 5; // data bit + const T3: u8 = 3; // stop bit + const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32; + + let mut wrap_target = a.label(); + let mut wrap_source = a.label(); + let mut do_zero = a.label(); + a.set_with_side_set(pio::SetDestination::PINDIRS, 1, 0); + a.bind(&mut wrap_target); + // Do stop bit + a.out_with_delay_and_side_set(pio::OutDestination::X, 1, T3 - 1, 0); + // Do start bit + a.jmp_with_delay_and_side_set(pio::JmpCondition::XIsZero, &mut do_zero, T1 - 1, 1); + // Do data bit = 1 + a.jmp_with_delay_and_side_set(pio::JmpCondition::Always, &mut wrap_target, T2 - 1, 1); + a.bind(&mut do_zero); + // Do data bit = 0 + a.nop_with_delay_and_side_set(T2 - 1, 0); + a.bind(&mut wrap_source); + + let prg = a.assemble_with_wrap(wrap_source, wrap_target); + let mut cfg = Config::default(); + + // Pin config + let out_pin = pio.make_pio_pin(pin); + cfg.set_out_pins(&[&out_pin]); + cfg.set_set_pins(&[&out_pin]); + + let relocated = RelocatedProgram::new(&prg); + cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); + + // Clock config, measured in kHz to avoid overflows + // TODO CLOCK_FREQ should come from embassy_rp + let clock_freq = fixed!(125_000: U24F8); + let ws2812_freq = fixed!(800: U24F8); + let bit_freq = ws2812_freq * CYCLES_PER_BIT; + cfg.clock_divider = clock_freq / bit_freq; + + // FIFO config + cfg.fifo_join = FifoJoin::TxOnly; + cfg.shift_out = ShiftConfig { + auto_fill: true, + threshold: 24, + direction: ShiftDirection::Left, + }; + + sm.set_config(&cfg); + sm.set_enable(true); + + Self { sm } + } + + pub async fn write(&mut self, colors: &[RGB8]) { + for color in colors { + let word = (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); + if !self.sm.tx().try_push(word) { + self.sm.tx().wait_push(word).await; + } + } + } +} + +/// Input a value 0 to 255 to get a color value +/// The colours are a transition r - g - b - back to r. +fn wheel(mut wheel_pos: u8) -> RGB8 { + wheel_pos = 255 - wheel_pos; + if wheel_pos < 85 { + return (255 - wheel_pos * 3, 0, wheel_pos * 3).into(); + } + if wheel_pos < 170 { + wheel_pos -= 85; + return (0, wheel_pos * 3, 255 - wheel_pos * 3).into(); + } + wheel_pos -= 170; + (wheel_pos * 3, 255 - wheel_pos * 3, 0).into() +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Start"); + let p = embassy_rp::init(Default::default()); + + let Pio { common, sm0, .. } = Pio::new(p.PIO0); + + // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit + // feather boards for the 2040 both have one built in. + const NUM_LEDS: usize = 1; + let mut data = [RGB8::default(); NUM_LEDS]; + + // For the thing plus, use pin 8 + // For the feather, use pin 16 + let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8); + + // Loop forever making RGB values and pushing them out to the WS2812. + loop { + for j in 0..(256 * 5) { + debug!("New Colors:"); + for i in 0..NUM_LEDS { + data[i] = wheel((((i * 256) as u16 / NUM_LEDS as u16 + j as u16) & 255) as u8); + debug!("R: {} G: {} B: {}", data[i].r, data[i].g, data[i].b); + } + ws2812.write(&data).await; + + Timer::after(Duration::from_micros(5)).await; + } + } +} diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs deleted file mode 100644 index f4c2d6313..000000000 --- a/examples/rp/src/bin/ws2812-pio.rs +++ /dev/null @@ -1,128 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use defmt::*; -use embassy_executor::Spawner; -use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; -use embassy_rp::relocate::RelocatedProgram; -use embassy_time::{Duration, Timer}; -use fixed_macro::fixed; -use smart_leds::RGB8; -use {defmt_rtt as _, panic_probe as _}; -pub struct Ws2812<'d, P: Instance, const S: usize> { - sm: StateMachine<'d, P, S>, -} - -impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { - pub fn new(mut pio: Common<'d, P>, mut sm: StateMachine<'d, P, S>, pin: impl PioPin) -> Self { - // Setup sm0 - - // prepare the PIO program - let side_set = pio::SideSet::new(false, 1, false); - let mut a: pio::Assembler<32> = pio::Assembler::new_with_side_set(side_set); - - const T1: u8 = 2; // start bit - const T2: u8 = 5; // data bit - const T3: u8 = 3; // stop bit - const CYCLES_PER_BIT: u32 = (T1 + T2 + T3) as u32; - - let mut wrap_target = a.label(); - let mut wrap_source = a.label(); - let mut do_zero = a.label(); - a.set_with_side_set(pio::SetDestination::PINDIRS, 1, 0); - a.bind(&mut wrap_target); - // Do stop bit - a.out_with_delay_and_side_set(pio::OutDestination::X, 1, T3 - 1, 0); - // Do start bit - a.jmp_with_delay_and_side_set(pio::JmpCondition::XIsZero, &mut do_zero, T1 - 1, 1); - // Do data bit = 1 - a.jmp_with_delay_and_side_set(pio::JmpCondition::Always, &mut wrap_target, T2 - 1, 1); - a.bind(&mut do_zero); - // Do data bit = 0 - a.nop_with_delay_and_side_set(T2 - 1, 0); - a.bind(&mut wrap_source); - - let prg = a.assemble_with_wrap(wrap_source, wrap_target); - let mut cfg = Config::default(); - - // Pin config - let out_pin = pio.make_pio_pin(pin); - - let relocated = RelocatedProgram::new(&prg); - cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); - - // Clock config, measured in kHz to avoid overflows - // TODO CLOCK_FREQ should come from embassy_rp - let clock_freq = fixed!(125_000: U24F8); - let ws2812_freq = fixed!(800: U24F8); - let bit_freq = ws2812_freq * CYCLES_PER_BIT; - cfg.clock_divider = clock_freq / bit_freq; - - // FIFO config - cfg.fifo_join = FifoJoin::TxOnly; - cfg.shift_out = ShiftConfig { - auto_fill: true, - threshold: 24, - direction: ShiftDirection::Left, - }; - - sm.set_config(&cfg); - sm.set_enable(true); - - Self { sm } - } - - pub async fn write(&mut self, colors: &[RGB8]) { - for color in colors { - let word = (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); - self.sm.tx().wait_push(word).await; - } - } -} - -/// Input a value 0 to 255 to get a color value -/// The colours are a transition r - g - b - back to r. -fn wheel(mut wheel_pos: u8) -> RGB8 { - wheel_pos = 255 - wheel_pos; - if wheel_pos < 85 { - return (255 - wheel_pos * 3, 0, wheel_pos * 3).into(); - } - if wheel_pos < 170 { - wheel_pos -= 85; - return (0, wheel_pos * 3, 255 - wheel_pos * 3).into(); - } - wheel_pos -= 170; - (wheel_pos * 3, 255 - wheel_pos * 3, 0).into() -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - info!("Start"); - let p = embassy_rp::init(Default::default()); - - let Pio { common, sm0, .. } = Pio::new(p.PIO0); - - // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit - // feather boards for the 2040 both have one built in. - const NUM_LEDS: usize = 1; - let mut data = [RGB8::default(); NUM_LEDS]; - - // For the thing plus, use pin 8 - // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8); - - // Loop forever making RGB values and pushing them out to the WS2812. - loop { - for j in 0..(256 * 5) { - debug!("New Colors:"); - for i in 0..NUM_LEDS { - data[i] = wheel((((i * 256) as u16 / NUM_LEDS as u16 + j as u16) & 255) as u8); - debug!("R: {} G: {} B: {}", data[i].r, data[i].g, data[i].b); - } - ws2812.write(&data).await; - - Timer::after(Duration::from_micros(5)).await; - } - } -} -- cgit From 1ebb742fbf9839ab393c038f320003a9346d37ff Mon Sep 17 00:00:00 2001 From: Caleb Jamison Date: Fri, 19 May 2023 16:48:47 -0400 Subject: Switch to DMA, use new clocks, don't take ownership of pio common --- examples/rp/src/bin/pio_ws2812.rs | 44 +++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 4915c7e92..26422421f 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -4,18 +4,30 @@ use defmt::*; use embassy_executor::Spawner; +use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; use embassy_rp::relocate::RelocatedProgram; +use embassy_rp::{clocks, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Timer}; +use fixed::types::U24F8; use fixed_macro::fixed; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; -pub struct Ws2812<'d, P: Instance, const S: usize> { + +pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { + dma: PeripheralRef<'d, AnyChannel>, sm: StateMachine<'d, P, S>, } -impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { - pub fn new(mut pio: Common<'d, P>, mut sm: StateMachine<'d, P, S>, pin: impl PioPin) -> Self { +impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> { + pub fn new( + pio: &mut Common<'d, P>, + mut sm: StateMachine<'d, P, S>, + dma: impl Peripheral

+ 'd, + pin: impl PioPin, + ) -> Self { + into_ref!(dma); + // Setup sm0 // prepare the PIO program @@ -56,7 +68,7 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { // Clock config, measured in kHz to avoid overflows // TODO CLOCK_FREQ should come from embassy_rp - let clock_freq = fixed!(125_000: U24F8); + let clock_freq = U24F8::from_num(clocks::clk_sys_freq() / 1000); let ws2812_freq = fixed!(800: U24F8); let bit_freq = ws2812_freq * CYCLES_PER_BIT; cfg.clock_divider = clock_freq / bit_freq; @@ -72,16 +84,22 @@ impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { sm.set_config(&cfg); sm.set_enable(true); - Self { sm } + Self { + dma: dma.map_into(), + sm, + } } - pub async fn write(&mut self, colors: &[RGB8]) { - for color in colors { - let word = (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); - if !self.sm.tx().try_push(word) { - self.sm.tx().wait_push(word).await; - } + pub async fn write(&mut self, colors: &[RGB8; N]) { + // Precompute the word bytes from the colors + let mut words = [0u32; N]; + for i in 0..N { + let word = (u32::from(colors[i].g) << 24) | (u32::from(colors[i].r) << 16) | (u32::from(colors[i].b) << 8); + words[i] = word; } + + // DMA transfer + self.sm.tx().dma_push(self.dma.reborrow(), &words).await; } } @@ -105,7 +123,7 @@ async fn main(_spawner: Spawner) { info!("Start"); let p = embassy_rp::init(Default::default()); - let Pio { common, sm0, .. } = Pio::new(p.PIO0); + let Pio { mut common, sm0, .. } = Pio::new(p.PIO0); // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit // feather boards for the 2040 both have one built in. @@ -114,7 +132,7 @@ async fn main(_spawner: Spawner) { // For the thing plus, use pin 8 // For the feather, use pin 16 - let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8); + let mut ws2812 = Ws2812::new(&mut common, sm0, p.DMA_CH0, p.PIN_16); // Loop forever making RGB values and pushing them out to the WS2812. loop { -- cgit From 3f35a8876ee65d030e32ab2444bc0abb29d88382 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 30 May 2023 23:22:34 +0200 Subject: cyw43: adapt build to main embassy repo. --- examples/rp/src/bin/wifi_ap_tcp_server.rs | 139 ++++++++++++++++++++++++++++ examples/rp/src/bin/wifi_scan.rs | 75 +++++++++++++++ examples/rp/src/bin/wifi_tcp_server.rs | 146 ++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+) create mode 100644 examples/rp/src/bin/wifi_ap_tcp_server.rs create mode 100644 examples/rp/src/bin/wifi_scan.rs create mode 100644 examples/rp/src/bin/wifi_tcp_server.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs new file mode 100644 index 000000000..15264524e --- /dev/null +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -0,0 +1,139 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use core::str::from_utf8; + +use cyw43_pio::PioSpi; +use defmt::*; +use embassy_executor::Spawner; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config, Stack, StackResources}; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; +use embassy_rp::pio::Pio; +use embassy_time::Duration; +use embedded_io::asynch::Write; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + STATIC_CELL.init_with(move || $val) + }}; +} + +#[embassy_executor::task] +async fn wifi_task( + runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + info!("Hello World!"); + + let p = embassy_rp::init(Default::default()); + + let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); + let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); + + // To make flashing faster for development, you may want to flash the firmwares independently + // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: + // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; + //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; + + let pwr = Output::new(p.PIN_23, Level::Low); + let cs = Output::new(p.PIN_25, Level::High); + let mut pio = Pio::new(p.PIO0); + let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); + + let state = singleton!(cyw43::State::new()); + let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; + unwrap!(spawner.spawn(wifi_task(runner))); + + control.init(clm).await; + control + .set_power_management(cyw43::PowerManagementMode::PowerSave) + .await; + + // Use a link-local address for communication without DHCP server + let config = Config::Static(embassy_net::StaticConfig { + address: embassy_net::Ipv4Cidr::new(embassy_net::Ipv4Address::new(169, 254, 1, 1), 16), + dns_servers: heapless::Vec::new(), + gateway: None, + }); + + // Generate random seed + let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. + + // Init network stack + let stack = &*singleton!(Stack::new( + net_device, + config, + singleton!(StackResources::<2>::new()), + seed + )); + + unwrap!(spawner.spawn(net_task(stack))); + + //control.start_ap_open("cyw43", 5).await; + control.start_ap_wpa2("cyw43", "password", 5).await; + + // And now we can use it! + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + + loop { + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + control.gpio_set(0, false).await; + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + + info!("Received connection from {:?}", socket.remote_endpoint()); + control.gpio_set(0, true).await; + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("read error: {:?}", e); + break; + } + }; + + info!("rxd {}", from_utf8(&buf[..n]).unwrap()); + + match socket.write_all(&buf[..n]).await { + Ok(()) => {} + Err(e) => { + warn!("write error: {:?}", e); + break; + } + }; + } + } +} diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs new file mode 100644 index 000000000..aa5e5a399 --- /dev/null +++ b/examples/rp/src/bin/wifi_scan.rs @@ -0,0 +1,75 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use core::str; + +use cyw43_pio::PioSpi; +use defmt::*; +use embassy_executor::Spawner; +use embassy_net::Stack; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; +use embassy_rp::pio::Pio; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + STATIC_CELL.init_with(move || $val) + }}; +} + +#[embassy_executor::task] +async fn wifi_task( + runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + info!("Hello World!"); + + let p = embassy_rp::init(Default::default()); + + let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); + let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); + + // To make flashing faster for development, you may want to flash the firmwares independently + // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: + // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; + //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; + + let pwr = Output::new(p.PIN_23, Level::Low); + let cs = Output::new(p.PIN_25, Level::High); + let mut pio = Pio::new(p.PIO0); + let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); + + let state = singleton!(cyw43::State::new()); + let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; + unwrap!(spawner.spawn(wifi_task(runner))); + + control.init(clm).await; + control + .set_power_management(cyw43::PowerManagementMode::PowerSave) + .await; + + let mut scanner = control.scan().await; + while let Some(bss) = scanner.next().await { + if let Ok(ssid_str) = str::from_utf8(&bss.ssid) { + 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 new file mode 100644 index 000000000..eafa25f68 --- /dev/null +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -0,0 +1,146 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use core::str::from_utf8; + +use cyw43_pio::PioSpi; +use defmt::*; +use embassy_executor::Spawner; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Config, Stack, StackResources}; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; +use embassy_rp::pio::Pio; +use embassy_time::Duration; +use embedded_io::asynch::Write; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + STATIC_CELL.init_with(move || $val) + }}; +} + +#[embassy_executor::task] +async fn wifi_task( + runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + info!("Hello World!"); + + let p = embassy_rp::init(Default::default()); + + let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); + let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); + + // To make flashing faster for development, you may want to flash the firmwares independently + // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: + // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; + //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; + + let pwr = Output::new(p.PIN_23, Level::Low); + let cs = Output::new(p.PIN_25, Level::High); + let mut pio = Pio::new(p.PIO0); + let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); + + let state = singleton!(cyw43::State::new()); + let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; + unwrap!(spawner.spawn(wifi_task(runner))); + + control.init(clm).await; + control + .set_power_management(cyw43::PowerManagementMode::PowerSave) + .await; + + let config = Config::Dhcp(Default::default()); + //let config = embassy_net::Config::Static(embassy_net::Config { + // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), + // dns_servers: Vec::new(), + // gateway: Some(Ipv4Address::new(192, 168, 69, 1)), + //}); + + // Generate random seed + let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. + + // Init network stack + let stack = &*singleton!(Stack::new( + net_device, + config, + singleton!(StackResources::<2>::new()), + seed + )); + + unwrap!(spawner.spawn(net_task(stack))); + + loop { + //control.join_open(env!("WIFI_NETWORK")).await; + match control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await { + Ok(_) => break, + Err(err) => { + info!("join failed with status={}", err.status); + } + } + } + + // And now we can use it! + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + + loop { + let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(Duration::from_secs(10))); + + control.gpio_set(0, false).await; + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + + info!("Received connection from {:?}", socket.remote_endpoint()); + control.gpio_set(0, true).await; + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("read error: {:?}", e); + break; + } + }; + + info!("rxd {}", from_utf8(&buf[..n]).unwrap()); + + match socket.write_all(&buf[..n]).await { + Ok(()) => {} + Err(e) => { + warn!("write error: {:?}", e); + break; + } + }; + } + } +} -- cgit From 7f0e778145e7a0f7281d9b37e59473fddf232097 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 31 May 2023 00:54:20 +0200 Subject: move embassy-net-w5500 to subdir. --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 152 ++++++++++++++++++++++ examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 132 +++++++++++++++++++ examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 141 ++++++++++++++++++++ examples/rp/src/bin/ethernet_w5500_udp.rs | 127 ++++++++++++++++++ 4 files changed, 552 insertions(+) create mode 100644 examples/rp/src/bin/ethernet_w5500_multisocket.rs create mode 100644 examples/rp/src/bin/ethernet_w5500_tcp_client.rs create mode 100644 examples/rp/src/bin/ethernet_w5500_tcp_server.rs create mode 100644 examples/rp/src/bin/ethernet_w5500_udp.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs new file mode 100644 index 000000000..eb3b8de81 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -0,0 +1,152 @@ +//! This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<3>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Create two sockets listening to the same port, to handle simultaneous connections + unwrap!(spawner.spawn(listen_task(&stack, 0, 1234))); + unwrap!(spawner.spawn(listen_task(&stack, 1, 1234))); +} + +#[embassy_executor::task(pool_size = 2)] +async fn listen_task(stack: &'static Stack>, id: u8, port: u16) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + info!("SOCKET {}: Listening on TCP:{}...", id, port); + if let Err(e) = socket.accept(port).await { + warn!("accept error: {:?}", e); + continue; + } + info!( + "SOCKET {}: Received connection from {:?}", + id, + socket.remote_endpoint() + ); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("SOCKET {}: {:?}", id, e); + break; + } + }; + info!( + "SOCKET {}: rxd {}", + id, + core::str::from_utf8(&buf[..n]).unwrap() + ); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs new file mode 100644 index 000000000..e166e0f35 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -0,0 +1,132 @@ +//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::str::FromStr; +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Duration, Timer}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + led.set_low(); + info!("Connecting..."); + let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap(); + if let Err(e) = socket.connect((host_addr, 1234)).await { + warn!("connect error: {:?}", e); + continue; + } + info!("Connected to {:?}", socket.remote_endpoint()); + led.set_high(); + + let msg = b"Hello world!\n"; + loop { + if let Err(e) = socket.write_all(msg).await { + warn!("write error: {:?}", e); + break; + } + info!("txd: {}", core::str::from_utf8(msg).unwrap()); + Timer::after(Duration::from_secs(1)).await; + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs new file mode 100644 index 000000000..ffd664d15 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -0,0 +1,141 @@ +//! This example implements a TCP echo server on port 1234 and using DHCP. +//! Send it some data, you should see it echoed back and printed in the console. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + led.set_low(); + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + info!("Received connection from {:?}", socket.remote_endpoint()); + led.set_high(); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("{:?}", e); + break; + } + }; + info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs new file mode 100644 index 000000000..08ffeb244 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -0,0 +1,127 @@ +//! This example implements a UDP server listening on port 1234 and echoing back the data. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::udp::UdpSocket; +use embassy_net::{PacketMetadata, Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut buf = [0; 4096]; + loop { + let mut socket = UdpSocket::new( + stack, + &mut rx_meta, + &mut rx_buffer, + &mut tx_meta, + &mut tx_buffer, + ); + socket.bind(1234).unwrap(); + + loop { + let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); + if let Ok(s) = core::str::from_utf8(&buf[..n]) { + info!("rxd from {}: {}", ep, s); + } + socket.send_to(&buf[..n], ep).await.unwrap(); + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} -- cgit From d70994e4a8ea695f07b777fa99d7db4e5d4a7122 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 31 May 2023 01:01:30 +0200 Subject: net-w5500: integrate into main repo. --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 25 ++++++----------------- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 13 ++++-------- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 13 ++++-------- examples/rp/src/bin/ethernet_w5500_udp.rs | 22 +++++--------------- 4 files changed, 19 insertions(+), 54 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index eb3b8de81..c8e6d46a6 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -15,6 +15,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::Duration; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -62,14 +63,8 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; + let (device, runner) = + embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed @@ -103,18 +98,14 @@ async fn listen_task(stack: &'static Stack>, id: u8, port: u16) let mut buf = [0; 4096]; loop { let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + socket.set_timeout(Some(Duration::from_secs(10))); info!("SOCKET {}: Listening on TCP:{}...", id, port); if let Err(e) = socket.accept(port).await { warn!("accept error: {:?}", e); continue; } - info!( - "SOCKET {}: Received connection from {:?}", - id, - socket.remote_endpoint() - ); + info!("SOCKET {}: Received connection from {:?}", id, socket.remote_endpoint()); loop { let n = match socket.read(&mut buf).await { @@ -128,11 +119,7 @@ async fn listen_task(stack: &'static Stack>, id: u8, port: u16) break; } }; - info!( - "SOCKET {}: rxd {}", - id, - core::str::from_utf8(&buf[..n]).unwrap() - ); + info!("SOCKET {}: rxd {}", id, core::str::from_utf8(&buf[..n]).unwrap()); if let Err(e) = socket.write_all(&buf[..n]).await { warn!("write error: {:?}", e); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index e166e0f35..9a7c3ad19 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -7,6 +7,7 @@ #![feature(type_alias_impl_trait)] use core::str::FromStr; + use defmt::*; use embassy_executor::Spawner; use embassy_futures::yield_now; @@ -65,14 +66,8 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; + let (device, runner) = + embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed @@ -98,7 +93,7 @@ async fn main(spawner: Spawner) { let mut tx_buffer = [0; 4096]; loop { let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + socket.set_timeout(Some(Duration::from_secs(10))); led.set_low(); info!("Connecting..."); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index ffd664d15..f02543246 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -16,6 +16,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::Duration; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -64,14 +65,8 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; + let (device, runner) = + embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed @@ -98,7 +93,7 @@ async fn main(spawner: Spawner) { let mut buf = [0; 4096]; loop { let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + socket.set_timeout(Some(Duration::from_secs(10))); led.set_low(); info!("Listening on TCP:1234..."); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 08ffeb244..2c54f711e 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -9,8 +9,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_futures::yield_now; -use embassy_net::udp::UdpSocket; -use embassy_net::{PacketMetadata, Stack, StackResources}; +use embassy_net::udp::{PacketMetadata, UdpSocket}; +use embassy_net::{Stack, StackResources}; use embassy_net_w5500::*; use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; @@ -62,14 +62,8 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; + let (device, runner) = + embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed @@ -98,13 +92,7 @@ async fn main(spawner: Spawner) { let mut tx_meta = [PacketMetadata::EMPTY; 16]; let mut buf = [0; 4096]; loop { - let mut socket = UdpSocket::new( - stack, - &mut rx_meta, - &mut rx_buffer, - &mut tx_meta, - &mut tx_buffer, - ); + let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); socket.bind(1234).unwrap(); loop { -- cgit From 1d8321b821d114b369d5a087a1a7a6600228b032 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 1 Jun 2023 01:32:11 +0200 Subject: Use make_static! from static-cell v1.1 --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 17 +++---------- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 17 +++---------- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 18 +++----------- examples/rp/src/bin/ethernet_w5500_udp.rs | 18 +++----------- examples/rp/src/bin/lora_p2p_send_multicore.rs | 2 +- examples/rp/src/bin/multicore.rs | 2 +- examples/rp/src/bin/uart_buffered_split.rs | 15 +++--------- examples/rp/src/bin/usb_ethernet.rs | 30 ++++++++++------------- examples/rp/src/bin/wifi_ap_tcp_server.rs | 16 +++--------- examples/rp/src/bin/wifi_scan.rs | 12 ++------- examples/rp/src/bin/wifi_tcp_server.rs | 16 +++--------- 11 files changed, 44 insertions(+), 119 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index c8e6d46a6..63e142e7d 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -19,18 +19,9 @@ use embassy_time::Duration; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -62,7 +53,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -71,10 +62,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<3>::new()), + make_static!(StackResources::<3>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 9a7c3ad19..a532de00d 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -21,18 +21,9 @@ use embassy_time::{Duration, Timer}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -65,7 +56,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -74,10 +65,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index f02543246..599f6b1e9 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -20,18 +20,8 @@ use embassy_time::Duration; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -64,7 +54,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -73,10 +63,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 2c54f711e..ac5a65bb6 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -18,18 +18,8 @@ use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; use embedded_hal_async::spi::ExclusiveDevice; use rand::RngCore; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::task] async fn ethernet_task( runner: Runner< @@ -61,7 +51,7 @@ async fn main(spawner: Spawner) { let w5500_reset = Output::new(p.PIN_20, Level::High); let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); + let state = make_static!(State::<8, 8>::new()); let (device, runner) = embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; unwrap!(spawner.spawn(ethernet_task(runner))); @@ -70,10 +60,10 @@ async fn main(spawner: Spawner) { let seed = rng.next_u64(); // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( device, embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs index 5585606d8..eef2f7a53 100644 --- a/examples/rp/src/bin/lora_p2p_send_multicore.rs +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs @@ -7,7 +7,6 @@ use defmt::*; use embassy_executor::Executor; -use embassy_executor::_export::StaticCell; use embassy_lora::iv::GenericSx126xInterfaceVariant; use embassy_rp::gpio::{AnyPin, Input, Level, Output, Pin, Pull}; use embassy_rp::multicore::{spawn_core1, Stack}; @@ -19,6 +18,7 @@ use embassy_time::{Delay, Duration, Timer}; use lora_phy::mod_params::*; use lora_phy::sx1261_2::SX1261_2; use lora_phy::LoRa; +use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; static mut CORE1_STACK: Stack<4096> = Stack::new(); diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 376b2b61e..57278dd6c 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -4,13 +4,13 @@ use defmt::*; use embassy_executor::Executor; -use embassy_executor::_export::StaticCell; use embassy_rp::gpio::{Level, Output}; use embassy_rp::multicore::{spawn_core1, Stack}; use embassy_rp::peripherals::PIN_25; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_time::{Duration, Timer}; +use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; static mut CORE1_STACK: Stack<4096> = Stack::new(); diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index d6f01b4de..9df99bd58 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -4,34 +4,25 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_executor::_export::StaticCell; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::UART0; use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::{Read, Write}; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { UART0_IRQ => BufferedInterruptHandler; }); -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); - let tx_buf = &mut singleton!([0u8; 16])[..]; - let rx_buf = &mut singleton!([0u8; 16])[..]; + let tx_buf = &mut make_static!([0u8; 16])[..]; + let rx_buf = &mut make_static!([0u8; 16])[..]; let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); let (rx, mut tx) = uart.split(); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 38ff1620d..16fbf5e91 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -13,7 +13,7 @@ use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, Config, UsbDevice}; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -22,15 +22,6 @@ bind_interrupts!(struct Irqs { type MyDriver = Driver<'static, peripherals::USB>; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - const MTU: usize = 1514; #[embassy_executor::task] @@ -73,10 +64,10 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 256])[..], - &mut singleton!([0; 128])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 256])[..], + &mut make_static!([0; 128])[..], ); // Our MAC addr. @@ -85,14 +76,14 @@ async fn main(spawner: Spawner) { let host_mac_addr = [0x88, 0x88, 0x88, 0x88, 0x88, 0x88]; // Create classes on the builder. - let class = CdcNcmClass::new(&mut builder, singleton!(State::new()), host_mac_addr, 64); + let class = CdcNcmClass::new(&mut builder, make_static!(State::new()), host_mac_addr, 64); // Build the builder. let usb = builder.build(); unwrap!(spawner.spawn(usb_task(usb))); - let (runner, device) = class.into_embassy_net_device::(singleton!(NetState::new()), our_mac_addr); + let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); @@ -106,7 +97,12 @@ async fn main(spawner: Spawner) { let seed = 1234; // guaranteed random, chosen by a fair dice roll // Init network stack - let stack = &*singleton!(Stack::new(device, config, singleton!(StackResources::<2>::new()), seed)); + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); unwrap!(spawner.spawn(net_task(stack))); diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 15264524e..b27d3c9f8 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -16,17 +16,9 @@ use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; use embassy_rp::pio::Pio; use embassy_time::Duration; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -60,7 +52,7 @@ async fn main(spawner: Spawner) { let mut pio = Pio::new(p.PIO0); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); - let state = singleton!(cyw43::State::new()); + let state = make_static!(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); @@ -80,10 +72,10 @@ async fn main(spawner: Spawner) { let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( net_device, config, - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index aa5e5a399..79534f229 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -13,17 +13,9 @@ use embassy_net::Stack; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; use embassy_rp::pio::Pio; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -57,7 +49,7 @@ async fn main(spawner: Spawner) { let mut pio = Pio::new(p.PIO0); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); - let state = singleton!(cyw43::State::new()); + let state = make_static!(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index eafa25f68..1a00bca96 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -16,17 +16,9 @@ use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; use embassy_rp::pio::Pio; use embassy_time::Duration; use embedded_io::asynch::Write; -use static_cell::StaticCell; +use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - STATIC_CELL.init_with(move || $val) - }}; -} - #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -60,7 +52,7 @@ async fn main(spawner: Spawner) { let mut pio = Pio::new(p.PIO0); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); - let state = singleton!(cyw43::State::new()); + let state = make_static!(cyw43::State::new()); let (net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); @@ -80,10 +72,10 @@ async fn main(spawner: Spawner) { let seed = 0x0123_4567_89ab_cdef; // chosen by fair dice roll. guarenteed to be random. // Init network stack - let stack = &*singleton!(Stack::new( + let stack = &*make_static!(Stack::new( net_device, config, - singleton!(StackResources::<2>::new()), + make_static!(StackResources::<2>::new()), seed )); -- cgit From 54bab33c7342510be538bc6d8545fe50146557cf Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 14:57:17 +0200 Subject: Rename StaticConfig to StaticConfigV4 --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 2 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 2 +- examples/rp/src/bin/usb_ethernet.rs | 2 +- examples/rp/src/bin/wifi_ap_tcp_server.rs | 2 +- examples/rp/src/bin/wifi_tcp_server.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 63e142e7d..7e9e20b28 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -120,7 +120,7 @@ async fn listen_task(stack: &'static Stack>, id: u8, port: u16) } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index a532de00d..c0275be1b 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -108,7 +108,7 @@ async fn main(spawner: Spawner) { } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 599f6b1e9..da73e41ff 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -116,7 +116,7 @@ async fn main(spawner: Spawner) { } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index ac5a65bb6..4c861cbd2 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -95,7 +95,7 @@ async fn main(spawner: Spawner) { } } -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { if let Some(config) = stack.config() { return config.clone(); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 16fbf5e91..d33d9c72e 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -87,7 +87,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(usb_ncm_task(runner))); let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::StaticConfig { + //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index b27d3c9f8..970cf4b32 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { .await; // Use a link-local address for communication without DHCP server - let config = Config::Static(embassy_net::StaticConfig { + let config = Config::StaticV4(embassy_net::StaticConfigV4 { address: embassy_net::Ipv4Cidr::new(embassy_net::Ipv4Address::new(169, 254, 1, 1), 16), dns_servers: heapless::Vec::new(), gateway: None, diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 1a00bca96..9f95f8b03 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { .await; let config = Config::Dhcp(Default::default()); - //let config = embassy_net::Config::Static(embassy_net::Config { + //let config = embassy_net::Config::StaticV4(embassy_net::Config { // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(192, 168, 69, 1)), -- cgit From e871324bde25bd61241aed83416caf6e49376d5a Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Mon, 5 Jun 2023 16:00:53 +0200 Subject: net: StaticV4 config behind proto-ipv4 --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 2 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 7e9e20b28..066ecf2bc 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -122,7 +122,7 @@ async fn listen_task(stack: &'static Stack>, id: u8, port: u16) async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index c0275be1b..3e0f5d136 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -110,7 +110,7 @@ async fn main(spawner: Spawner) { async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index da73e41ff..db178d49d 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -118,7 +118,7 @@ async fn main(spawner: Spawner) { async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 4c861cbd2..21943c3c6 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -97,7 +97,7 @@ async fn main(spawner: Spawner) { async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfigV4 { loop { - if let Some(config) = stack.config() { + if let Some(config) = stack.config_v4() { return config.clone(); } yield_now().await; -- cgit From 352f0b6c3823797576c36f417d6be40189bca5d5 Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Wed, 7 Jun 2023 12:04:15 +0200 Subject: net: Support dual stack IP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 2 +- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 2 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 2 +- examples/rp/src/bin/usb_ethernet.rs | 4 ++-- examples/rp/src/bin/wifi_ap_tcp_server.rs | 2 +- examples/rp/src/bin/wifi_tcp_server.rs | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 066ecf2bc..82568254a 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<3>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index 3e0f5d136..d562defad 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -67,7 +67,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index db178d49d..7f521cdb4 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -65,7 +65,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index 21943c3c6..ada86ae55 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { // Init network stack let stack = &*make_static!(Stack::new( device, - embassy_net::Config::Dhcp(Default::default()), + embassy_net::Config::dhcpv4(Default::default()), make_static!(StackResources::<2>::new()), seed )); diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index d33d9c72e..91d1ec8e7 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -86,8 +86,8 @@ async fn main(spawner: Spawner) { let (runner, device) = class.into_embassy_net_device::(make_static!(NetState::new()), our_mac_addr); unwrap!(spawner.spawn(usb_ncm_task(runner))); - let config = embassy_net::Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::StaticConfigV4 { + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 970cf4b32..e8197390c 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -62,7 +62,7 @@ async fn main(spawner: Spawner) { .await; // Use a link-local address for communication without DHCP server - let config = Config::StaticV4(embassy_net::StaticConfigV4 { + let config = Config::ipv4_static(embassy_net::StaticConfigV4 { address: embassy_net::Ipv4Cidr::new(embassy_net::Ipv4Address::new(169, 254, 1, 1), 16), dns_servers: heapless::Vec::new(), gateway: None, diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 9f95f8b03..026e056fa 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -61,8 +61,8 @@ async fn main(spawner: Spawner) { .set_power_management(cyw43::PowerManagementMode::PowerSave) .await; - let config = Config::Dhcp(Default::default()); - //let config = embassy_net::Config::StaticV4(embassy_net::Config { + let config = Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { // address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), // dns_servers: Vec::new(), // gateway: Some(Ipv4Address::new(192, 168, 69, 1)), -- cgit From dc8e34420f434505829cafe0cb844af9c1c0b500 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 16:02:12 +0200 Subject: Remove executor dep+reexports from HALs. Closes #1547 --- examples/rp/src/bin/multiprio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index 2f79ba49e..fea1d5b03 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs @@ -62,7 +62,7 @@ use core::mem; use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::{info, unwrap}; -use embassy_rp::executor::{Executor, InterruptExecutor}; +use embassy_executor::{Executor, InterruptExecutor}; use embassy_rp::interrupt; use embassy_rp::pac::Interrupt; use embassy_time::{Duration, Instant, Timer, TICK_HZ}; -- cgit From 6653f262d7c2ec17e6aba91b89d3835504320a5a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 9 Jun 2023 16:44:58 +0200 Subject: examples: use nicer InterrupExt to set irq priority in multprio. --- examples/rp/src/bin/multiprio.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/multiprio.rs b/examples/rp/src/bin/multiprio.rs index fea1d5b03..9ace4cd68 100644 --- a/examples/rp/src/bin/multiprio.rs +++ b/examples/rp/src/bin/multiprio.rs @@ -57,14 +57,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::mem; - -use cortex_m::peripheral::NVIC; use cortex_m_rt::entry; use defmt::{info, unwrap}; use embassy_executor::{Executor, InterruptExecutor}; use embassy_rp::interrupt; -use embassy_rp::pac::Interrupt; +use embassy_rp::interrupt::{InterruptExt, Priority}; use embassy_time::{Duration, Instant, Timer, TICK_HZ}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -130,18 +127,15 @@ fn main() -> ! { info!("Hello World!"); let _p = embassy_rp::init(Default::default()); - let mut nvic: NVIC = unsafe { mem::transmute(()) }; // High-priority executor: SWI_IRQ_1, priority level 2 - unsafe { nvic.set_priority(Interrupt::SWI_IRQ_1, 2 << 6) }; - info!("bla: {}", NVIC::get_priority(Interrupt::SWI_IRQ_1)); - let spawner = EXECUTOR_HIGH.start(Interrupt::SWI_IRQ_1); + interrupt::SWI_IRQ_1.set_priority(Priority::P2); + let spawner = EXECUTOR_HIGH.start(interrupt::SWI_IRQ_1); unwrap!(spawner.spawn(run_high())); // Medium-priority executor: SWI_IRQ_0, priority level 3 - unsafe { nvic.set_priority(Interrupt::SWI_IRQ_0, 3 << 6) }; - info!("bla: {}", NVIC::get_priority(Interrupt::SWI_IRQ_0)); - let spawner = EXECUTOR_MED.start(Interrupt::SWI_IRQ_0); + interrupt::SWI_IRQ_0.set_priority(Priority::P3); + let spawner = EXECUTOR_MED.start(interrupt::SWI_IRQ_0); unwrap!(spawner.spawn(run_med())); // Low priority executor: runs in thread mode, using WFE/SEV -- cgit From 6863786243e0f7cb28661d49165eeffacbfd8152 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Sat, 10 Jun 2023 18:14:45 +0200 Subject: Document external button. Add wifi_blinky.rs for easy beginners start. --- examples/rp/src/bin/button.rs | 5 +++- examples/rp/src/bin/wifi_blinky.rs | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 examples/rp/src/bin/wifi_blinky.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index c5422c616..edfb09cdb 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs @@ -9,9 +9,12 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - let button = Input::new(p.PIN_28, Pull::Up); let mut led = Output::new(p.PIN_25, Level::Low); + // Use PIN_28, Pin34 on J0 for RP Pico, as a input. + // You need to ad your own button. + let button = Input::new(p.PIN_28, Pull::Up); + loop { if button.is_high() { led.set_high(); diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs new file mode 100644 index 000000000..f567e7c5d --- /dev/null +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -0,0 +1,59 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use cyw43_pio::PioSpi; +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::gpio::{Level, Output}; +use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; +use embassy_rp::pio::Pio; +use embassy_time::{Duration, Timer}; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn wifi_task( + runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, +) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let fw = include_bytes!("../../../../cyw43-firmware/43439A0.bin"); + let clm = include_bytes!("../../../../cyw43-firmware/43439A0_clm.bin"); + + // To make flashing faster for development, you may want to flash the firmwares independently + // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: + // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; + //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; + + let pwr = Output::new(p.PIN_23, Level::Low); + let cs = Output::new(p.PIN_25, Level::High); + let mut pio = Pio::new(p.PIO0); + let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); + + let state = make_static!(cyw43::State::new()); + let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; + unwrap!(spawner.spawn(wifi_task(runner))); + + control.init(clm).await; + control + .set_power_management(cyw43::PowerManagementMode::PowerSave) + .await; + + let delay = Duration::from_secs(1); + loop { + info!("led on!"); + control.gpio_set(0, true).await; + Timer::after(delay).await; + + info!("led off!"); + control.gpio_set(0, false).await; + Timer::after(delay).await; + } +} -- cgit From 23724b6bf6ce6492d40a3ff3af77c8b4d15a36d8 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Mon, 12 Jun 2023 18:12:35 +0200 Subject: Code cleanup. --- examples/rp/src/bin/wifi_blinky.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index f567e7c5d..be965807b 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -40,7 +40,7 @@ async fn main(spawner: Spawner) { let state = make_static!(cyw43::State::new()); let (_net_device, mut control, runner) = cyw43::new(state, pwr, spi, fw).await; unwrap!(spawner.spawn(wifi_task(runner))); - + control.init(clm).await; control .set_power_management(cyw43::PowerManagementMode::PowerSave) -- cgit From 35db5cf41653bdb995f5cad2d04788118a746921 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Mon, 12 Jun 2023 18:56:20 +0200 Subject: Spelling. --- examples/rp/src/bin/button.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index edfb09cdb..0d246c093 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs @@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) { let mut led = Output::new(p.PIN_25, Level::Low); // Use PIN_28, Pin34 on J0 for RP Pico, as a input. - // You need to ad your own button. + // You need to add your own button. let button = Input::new(p.PIN_28, Pull::Up); loop { -- cgit From f7ec579c18b2ec925afcd4ab9a840719f4ce08cc Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 29 Jun 2023 02:39:28 +0200 Subject: Update probe-rs-cli -> probe-rs --- examples/rp/src/bin/wifi_ap_tcp_server.rs | 4 ++-- examples/rp/src/bin/wifi_blinky.rs | 4 ++-- examples/rp/src/bin/wifi_scan.rs | 4 ++-- examples/rp/src/bin/wifi_tcp_server.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index e8197390c..310e84d92 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -42,8 +42,8 @@ async fn main(spawner: Spawner) { // To make flashing faster for development, you may want to flash the firmwares independently // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: - // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 - // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index be965807b..bbcb1b5ec 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -27,8 +27,8 @@ async fn main(spawner: Spawner) { // To make flashing faster for development, you may want to flash the firmwares independently // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: - // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 - // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 79534f229..391e12282 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -39,8 +39,8 @@ async fn main(spawner: Spawner) { // To make flashing faster for development, you may want to flash the firmwares independently // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: - // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 - // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 026e056fa..e9d1079a6 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -42,8 +42,8 @@ async fn main(spawner: Spawner) { // To make flashing faster for development, you may want to flash the firmwares independently // at hardcoded addresses, instead of baking them into the program with `include_bytes!`: - // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 - // probe-rs-cli download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 + // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000 + // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x10140000 //let fw = unsafe { core::slice::from_raw_parts(0x10100000 as *const u8, 224190) }; //let clm = unsafe { core::slice::from_raw_parts(0x10140000 as *const u8, 4752) }; -- cgit From a101d9078deb3ad576a40b6d5f4d6e81dcfd528e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 4 Jul 2023 19:53:06 +0200 Subject: update embedded-hal crates. --- examples/rp/src/bin/ethernet_w5500_multisocket.rs | 14 ++++++++++---- examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 14 ++++++++++---- examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 14 ++++++++++---- examples/rp/src/bin/ethernet_w5500_udp.rs | 13 ++++++++++--- examples/rp/src/bin/spi_display.rs | 8 ++++---- 5 files changed, 44 insertions(+), 19 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 82568254a..e81da177b 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -15,7 +15,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::Duration; +use embassy_time::{Delay, Duration}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -26,7 +26,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -54,8 +54,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index d562defad..9dd7ae973 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -17,7 +17,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::{Duration, Timer}; +use embassy_time::{Delay, Duration, Timer}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -28,7 +28,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -57,8 +57,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 7f521cdb4..db21c2b6f 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -16,7 +16,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::Duration; +use embassy_time::{Delay, Duration}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -26,7 +26,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -55,8 +55,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index ada86ae55..038432b17 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -16,6 +16,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::Delay; use embedded_hal_async::spi::ExclusiveDevice; use rand::RngCore; use static_cell::make_static; @@ -24,7 +25,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -52,8 +53,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 85a19ce07..2fd201595 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -175,7 +175,7 @@ mod touch { mod my_display_interface { use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; use embedded_hal_1::digital::OutputPin; - use embedded_hal_1::spi::SpiDeviceWrite; + use embedded_hal_1::spi::SpiDevice; /// SPI display interface. /// @@ -187,7 +187,7 @@ mod my_display_interface { impl SPIDeviceInterface where - SPI: SpiDeviceWrite, + SPI: SpiDevice, DC: OutputPin, { /// Create new SPI interface for communciation with a display driver @@ -198,7 +198,7 @@ mod my_display_interface { impl WriteOnlyDataCommand for SPIDeviceInterface where - SPI: SpiDeviceWrite, + SPI: SpiDevice, DC: OutputPin, { fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> { @@ -218,7 +218,7 @@ mod my_display_interface { } } - fn send_u8(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { + fn send_u8(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { match words { DataFormat::U8(slice) => spi.write(slice), DataFormat::U16(slice) => { -- cgit From a42ac86f1b71700632b77196ad506587774ae976 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Jul 2023 19:16:45 +0200 Subject: Remove wifi envvars. They're annoying, they cause rust-analyzer errors when opening the examples. --- examples/rp/src/bin/wifi_tcp_server.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index e9d1079a6..197535f45 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -19,6 +19,9 @@ use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +const WIFI_NETWORK: &str = "EmbassyTest"; +const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -82,8 +85,8 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(net_task(stack))); loop { - //control.join_open(env!("WIFI_NETWORK")).await; - match control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await { + //control.join_open(WIFI_NETWORK).await; + match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await { Ok(_) => break, Err(err) => { info!("join failed with status={}", err.status); -- cgit From 4b63829110b8ef314d22d78c160f54e6ae98634c Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 7 Jul 2023 04:30:46 +0200 Subject: rp/pio: use bind_interrupts for irqs closes #1338 --- examples/rp/src/bin/pio_async.rs | 9 +++++++-- examples/rp/src/bin/pio_dma.rs | 11 ++++++++--- examples/rp/src/bin/pio_hd44780.rs | 15 +++++++++++---- examples/rp/src/bin/pio_ws2812.rs | 13 ++++++++++--- examples/rp/src/bin/wifi_ap_tcp_server.rs | 9 +++++++-- examples/rp/src/bin/wifi_blinky.rs | 9 +++++++-- examples/rp/src/bin/wifi_scan.rs | 9 +++++++-- examples/rp/src/bin/wifi_tcp_server.rs | 9 +++++++-- 8 files changed, 64 insertions(+), 20 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 79eda1a09..69034c92a 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -3,13 +3,18 @@ #![feature(type_alias_impl_trait)] use defmt::info; use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; +use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::relocate::RelocatedProgram; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { // Setup sm0 @@ -110,7 +115,7 @@ async fn main(spawner: Spawner) { mut sm1, mut sm2, .. - } = Pio::new(pio); + } = Pio::new(pio, Irqs); setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); setup_pio_task_sm1(&mut common, &mut sm1); diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 05c0ebb16..80c963556 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,13 +4,18 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::Peripheral; +use embassy_rp::{bind_interrupts, Peripheral}; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + fn swap_nibbles(v: u32) -> u32 { let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; @@ -25,7 +30,7 @@ async fn main(_spawner: Spawner) { mut common, sm0: mut sm, .. - } = Pio::new(pio); + } = Pio::new(pio, Irqs); let prg = pio_proc::pio_asm!( ".origin 0", diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index bfc6c9908..0a4514a66 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -7,13 +7,19 @@ use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; +use embassy_rp::pio::{ + Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, +}; use embassy_rp::pwm::{self, Pwm}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::{into_ref, Peripheral, PeripheralRef}; +use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Instant, Timer}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(pub struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { // this test assumes a 2x16 HD44780 display attached as follow: @@ -37,7 +43,7 @@ async fn main(_spawner: Spawner) { }); let mut hd = HD44780::new( - p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, + p.PIO0, Irqs, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, ) .await; @@ -72,6 +78,7 @@ pub struct HD44780<'l> { impl<'l> HD44780<'l> { pub async fn new( pio: impl Peripheral

+ 'l, + irq: Irqs, dma: impl Peripheral

+ 'l, rs: impl PioPin, rw: impl PioPin, @@ -88,7 +95,7 @@ impl<'l> HD44780<'l> { mut irq0, mut sm0, .. - } = Pio::new(pio); + } = Pio::new(pio, irq); // takes command words ( <0:4>) let prg = pio_proc::pio_asm!( diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 26422421f..4a111e7aa 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -5,15 +5,22 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; -use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{ + Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, +}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::{clocks, into_ref, Peripheral, PeripheralRef}; +use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Timer}; use fixed::types::U24F8; use fixed_macro::fixed; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { dma: PeripheralRef<'d, AnyChannel>, sm: StateMachine<'d, P, S>, @@ -123,7 +130,7 @@ async fn main(_spawner: Spawner) { info!("Start"); let p = embassy_rp::init(Default::default()); - let Pio { mut common, sm0, .. } = Pio::new(p.PIO0); + let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit // feather boards for the 2040 both have one built in. diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 310e84d92..3e41f83be 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -11,14 +11,19 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Stack, StackResources}; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::Duration; use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -49,7 +54,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index bbcb1b5ec..6eb207af6 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -5,13 +5,18 @@ use cyw43_pio::PioSpi; use defmt::*; use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::{Duration, Timer}; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -34,7 +39,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 391e12282..aef18aa24 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -10,12 +10,17 @@ use cyw43_pio::PioSpi; use defmt::*; use embassy_executor::Spawner; use embassy_net::Stack; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -46,7 +51,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 197535f45..4fce74a66 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -11,14 +11,19 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Stack, StackResources}; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::Duration; use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + const WIFI_NETWORK: &str = "EmbassyTest"; const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; @@ -52,7 +57,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); -- cgit From 972cdd4265b24efb101c6b9df373466fcbccac5d Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 5 Jul 2023 20:05:34 +0200 Subject: rp/adc: rewrite the module - don't require an irq binding for blocking-only adc - abstract adc pins into an AnyPin like interface, erasing the actual peripheral type at runtime. - add pull-up/pull-down functions for adc pins - add a test (mostly a copy of the example, to be honest) - configure adc pads according to datasheet - report conversion errors (although they seem exceedingly rare?) - drop embedded-hal interfaces. embedded-hal channels can do neither AnyPin nor pullup/pulldown without encoding both into the type --- examples/rp/src/bin/adc.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 7c2ca19f7..65069cde1 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -4,8 +4,9 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::adc::{Adc, Config, InterruptHandler}; +use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; use embassy_rp::bind_interrupts; +use embassy_rp::gpio::Pull; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -18,18 +19,18 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut adc = Adc::new(p.ADC, Irqs, Config::default()); - let mut p26 = p.PIN_26; - let mut p27 = p.PIN_27; - let mut p28 = p.PIN_28; + let mut p26 = Pin::new(p.PIN_26, Pull::None); + let mut p27 = Pin::new(p.PIN_27, Pull::None); + let mut p28 = Pin::new(p.PIN_28, Pull::None); loop { - let level = adc.read(&mut p26).await; + let level = adc.read(&mut p26).await.unwrap(); info!("Pin 26 ADC: {}", level); - let level = adc.read(&mut p27).await; + let level = adc.read(&mut p27).await.unwrap(); info!("Pin 27 ADC: {}", level); - let level = adc.read(&mut p28).await; + let level = adc.read(&mut p28).await.unwrap(); info!("Pin 28 ADC: {}", level); - let temp = adc.read_temperature().await; + let temp = adc.read_temperature().await.unwrap(); info!("Temp: {} degrees", convert_to_celsius(temp)); Timer::after(Duration::from_secs(1)).await; } -- cgit From 55a5e9b3a51b537b7de80221d501be423af43303 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 22 Jun 2023 22:37:24 +0200 Subject: RP: Add RTC example to rp2040. --- examples/rp/src/bin/rtc.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 examples/rp/src/bin/rtc.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs new file mode 100644 index 000000000..a49c8f627 --- /dev/null +++ b/examples/rp/src/bin/rtc.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::rtc::{DateTime, DayOfWeek, RealTimeClock}; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let now = DateTime { + year: 2020, + month: 5, + day: 15, + day_of_week: DayOfWeek::Monday, + hour: 10, + minute: 30, + second: 50, + }; + + let rtc_result = RealTimeClock::new(p.RTC, now); + if let Ok(rtc) = rtc_result { + // In reality the delay would be much longer + Timer::after(Duration::from_millis(20000)).await; + + let _then: DateTime = rtc.now().unwrap(); + } +} -- cgit From a93714327eb85b02c7c4a419f2a76df579258975 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Tue, 11 Jul 2023 18:41:45 +0200 Subject: RP: Rename Rtc to match STM32 impl. Remove setting RTC in new(). --- examples/rp/src/bin/rtc.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index a49c8f627..6300950d4 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::rtc::{DateTime, DayOfWeek, RealTimeClock}; +use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -23,11 +23,17 @@ async fn main(_spawner: Spawner) { second: 50, }; - let rtc_result = RealTimeClock::new(p.RTC, now); - if let Ok(rtc) = rtc_result { + let mut rtc = Rtc::new(p.RTC); + if rtc.set_datetime(now).is_ok() { // In reality the delay would be much longer Timer::after(Duration::from_millis(20000)).await; - let _then: DateTime = rtc.now().unwrap(); + if let Ok(dt) = rtc.now() { + info!( + "Now: {}-{}-{} {}:{}:{}", + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, + ); + } } + info!("Done."); } -- cgit From 466a391b52836f79fafad5780ad2eb0a07d82513 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 14:13:19 +0200 Subject: RP: Add save/restore to Rtc. Example use. --- examples/rp/src/bin/rtc.rs | 55 ++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index 6300950d4..2ddde3257 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,6 +4,7 @@ use defmt::*; use embassy_executor::Spawner; +use embassy_rp::pac::rtc::regs::{Rtc0, Rtc1}; use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -11,29 +12,41 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - info!("Hello World!"); - - let now = DateTime { - year: 2020, - month: 5, - day: 15, - day_of_week: DayOfWeek::Monday, - hour: 10, - minute: 30, - second: 50, - }; + info!("Wait for 20s"); + let mut watchdog = embassy_rp::watchdog::Watchdog::new(p.WATCHDOG); let mut rtc = Rtc::new(p.RTC); - if rtc.set_datetime(now).is_ok() { - // In reality the delay would be much longer - Timer::after(Duration::from_millis(20000)).await; - if let Ok(dt) = rtc.now() { - info!( - "Now: {}-{}-{} {}:{}:{}", - dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, - ); - } + let rtc0 = Rtc0(watchdog.get_scratch0()); + let rtc1 = Rtc1(watchdog.get_scratch1()); + if rtc1.year() >= 2020 { + rtc.restore(rtc1, rtc0); + } else { + let now = DateTime { + year: 2020, + month: 5, + day: 15, + day_of_week: DayOfWeek::Monday, + hour: 10, + minute: 30, + second: 50, + }; + rtc.set_datetime(now).unwrap(); } - info!("Done."); + + Timer::after(Duration::from_millis(20000)).await; + + if let Ok(dt) = rtc.now() { + info!( + "Now: {}-{:02}-{:02} {}:{:02}:{:02}", + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, + ); + let (rtc1, rtc0) = rtc.save(); + watchdog.set_scratch0(rtc0.0); + watchdog.set_scratch1(rtc1.0); + } + + info!("Reboot."); + Timer::after(Duration::from_millis(200)).await; + cortex_m::peripheral::SCB::sys_reset(); } -- cgit From 6d402fe3932ac04ff939379e6520322476f683dc Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 15:16:56 +0200 Subject: RP: Don't reset RTC in Clock::init. Updated example. --- examples/rp/src/bin/rtc.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index 2ddde3257..d569f598f 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::pac::rtc::regs::{Rtc0, Rtc1}; use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -14,22 +13,18 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); info!("Wait for 20s"); - let mut watchdog = embassy_rp::watchdog::Watchdog::new(p.WATCHDOG); let mut rtc = Rtc::new(p.RTC); - let rtc0 = Rtc0(watchdog.get_scratch0()); - let rtc1 = Rtc1(watchdog.get_scratch1()); - if rtc1.year() >= 2020 { - rtc.restore(rtc1, rtc0); - } else { + if !rtc.is_running() { + info!("Start RTC"); let now = DateTime { - year: 2020, - month: 5, - day: 15, - day_of_week: DayOfWeek::Monday, - hour: 10, - minute: 30, - second: 50, + year: 2000, + month: 1, + day: 1, + day_of_week: DayOfWeek::Saturday, + hour: 0, + minute: 0, + second: 0, }; rtc.set_datetime(now).unwrap(); } @@ -41,9 +36,6 @@ async fn main(_spawner: Spawner) { "Now: {}-{:02}-{:02} {}:{:02}:{:02}", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ); - let (rtc1, rtc0) = rtc.save(); - watchdog.set_scratch0(rtc0.0); - watchdog.set_scratch1(rtc1.0); } info!("Reboot."); -- cgit From 588c0479f5dacd21e8654463eb3ca3d847d5dcd9 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 13 Jul 2023 11:16:11 +0200 Subject: Add descriptions to all RP2040 examples. Some need hardware that was not specified. --- examples/rp/src/bin/adc.rs | 5 ++++- examples/rp/src/bin/blinky.rs | 4 ++++ examples/rp/src/bin/button.rs | 4 ++++ examples/rp/src/bin/flash.rs | 2 ++ examples/rp/src/bin/gpio_async.rs | 6 ++++-- examples/rp/src/bin/gpout.rs | 4 ++++ examples/rp/src/bin/i2c_async.rs | 5 +++++ examples/rp/src/bin/i2c_blocking.rs | 5 +++++ examples/rp/src/bin/lora_lorawan.rs | 1 + examples/rp/src/bin/lora_p2p_receive.rs | 1 + examples/rp/src/bin/lora_p2p_send.rs | 1 + examples/rp/src/bin/lora_p2p_send_multicore.rs | 1 + examples/rp/src/bin/multicore.rs | 4 ++++ examples/rp/src/bin/pio_async.rs | 11 ++++++++++- examples/rp/src/bin/pio_dma.rs | 2 ++ examples/rp/src/bin/pio_hd44780.rs | 3 +++ examples/rp/src/bin/pio_ws2812.rs | 3 +++ examples/rp/src/bin/pwm.rs | 4 ++++ examples/rp/src/bin/rtc.rs | 2 ++ examples/rp/src/bin/spi.rs | 4 ++++ examples/rp/src/bin/spi_async.rs | 3 +++ examples/rp/src/bin/spi_display.rs | 5 +++++ examples/rp/src/bin/uart.rs | 6 ++++++ examples/rp/src/bin/uart_buffered_split.rs | 6 ++++++ examples/rp/src/bin/uart_unidir.rs | 6 +++++- examples/rp/src/bin/usb_ethernet.rs | 4 ++++ examples/rp/src/bin/usb_logger.rs | 4 ++++ examples/rp/src/bin/usb_serial.rs | 4 ++++ examples/rp/src/bin/watchdog.rs | 4 ++++ examples/rp/src/bin/wifi_ap_tcp_server.rs | 3 +++ examples/rp/src/bin/wifi_blinky.rs | 4 ++++ examples/rp/src/bin/wifi_scan.rs | 3 +++ examples/rp/src/bin/wifi_tcp_server.rs | 3 +++ 33 files changed, 122 insertions(+), 5 deletions(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 65069cde1..c0cbe0172 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -1,3 +1,6 @@ +//! This example test the ADC (Analog to Digital Conversion) of the RS2040 pin 26, 27 and 28. +//! It also reads the temperature sensor in the chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] @@ -38,5 +41,5 @@ async fn main(_spawner: Spawner) { fn convert_to_celsius(raw_temp: u16) -> f32 { // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet - 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32 + 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 } diff --git a/examples/rp/src/bin/blinky.rs b/examples/rp/src/bin/blinky.rs index 7aa36a19f..295b000f3 100644 --- a/examples/rp/src/bin/blinky.rs +++ b/examples/rp/src/bin/blinky.rs @@ -1,3 +1,7 @@ +//! This example test the RP Pico on board LED. +//! +//! It does not work with the RP Pico W board. See wifi_blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index 0d246c093..d7aa89410 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs @@ -1,3 +1,7 @@ +//! This example uses the RP Pico on board LED to test input pin 28. This is not the button on the board. +//! +//! It does not work with the RP Pico W board. Use wifi_blinky.rs and add input pin. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index 19076150c..4c4982acc 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs @@ -1,3 +1,5 @@ +//! This example test the flash connected to the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/gpio_async.rs b/examples/rp/src/bin/gpio_async.rs index 52d13a9d5..bf58044d5 100644 --- a/examples/rp/src/bin/gpio_async.rs +++ b/examples/rp/src/bin/gpio_async.rs @@ -1,3 +1,7 @@ +//! This example shows how async gpio can be used with a RP2040. +//! +//! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] @@ -9,8 +13,6 @@ use embassy_time::{Duration, Timer}; use gpio::{Input, Level, Output, Pull}; use {defmt_rtt as _, panic_probe as _}; -/// This example shows how async gpio can be used with a RP2040. -/// /// It requires an external signal to be manually triggered on PIN 16. For /// example, this could be accomplished using an external power source with a /// button so that it is possible to toggle the signal from low to high. diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs index 64461fc5f..0a3b5fa98 100644 --- a/examples/rp/src/bin/gpout.rs +++ b/examples/rp/src/bin/gpout.rs @@ -1,3 +1,7 @@ +//! This example shows how GPOUT (General purpose clock outputs) can toggle a output pin. +//! +//! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs index cf3cf742c..93224bc43 100644 --- a/examples/rp/src/bin/i2c_async.rs +++ b/examples/rp/src/bin/i2c_async.rs @@ -1,3 +1,8 @@ +//! This example shows how to communicate asynchronous using i2c with external chips. +//! +//! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. +//! (https://www.microchip.com/en-us/product/mcp23017) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index 7623e33c8..1c8c2039d 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -1,3 +1,8 @@ +//! This example shows how to communicate using i2c with external chips. +//! +//! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. +//! (https://www.microchip.com/en-us/product/mcp23017) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/lora_lorawan.rs b/examples/rp/src/bin/lora_lorawan.rs index a9c84bf95..d631fafa1 100644 --- a/examples/rp/src/bin/lora_lorawan.rs +++ b/examples/rp/src/bin/lora_lorawan.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LoRaWAN join functionality. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/lora_p2p_receive.rs b/examples/rp/src/bin/lora_p2p_receive.rs index 250419202..396d669de 100644 --- a/examples/rp/src/bin/lora_p2p_receive.rs +++ b/examples/rp/src/bin/lora_p2p_receive.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/lora_p2p_send.rs b/examples/rp/src/bin/lora_p2p_send.rs index 3a0544b17..a0f70fa5c 100644 --- a/examples/rp/src/bin/lora_p2p_send.rs +++ b/examples/rp/src/bin/lora_p2p_send.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LORA P2P send functionality. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs index eef2f7a53..89a62818d 100644 --- a/examples/rp/src/bin/lora_p2p_send_multicore.rs +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LORA P2P send functionality using the second core, with data provided by the first core. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 57278dd6c..893b724bf 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -1,3 +1,7 @@ +//! This example shows how to send messages between the two cores in the RP2040 chip. +//! +//! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 69034c92a..c001d6440 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -1,3 +1,5 @@ +//! This example shows powerful PIO module in the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] @@ -54,7 +56,14 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, // Setupm sm1 // Read 0b10101 repeatedly until ISR is full - let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); + let prg = pio_proc::pio_asm!( + // + ".origin 8", + "set x, 0x15", + ".wrap_target", + "in x, 5 [31]", + ".wrap", + ); let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 80c963556..9ab72e1f3 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -1,3 +1,5 @@ +//! This example shows powerful PIO module in the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 0a4514a66..8aedd24b6 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -1,3 +1,6 @@ +//! This example shows powerful PIO module in the RP2040 chip to communicate with a HD44780 display. +//! See (https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 4a111e7aa..3de2bd48d 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -1,3 +1,6 @@ +//! This example shows powerful PIO module in the RP2040 chip to communicate with WS2812 LED modules. +//! See (https://www.sparkfun.com/categories/tags/ws2812) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 2b3d5d97a..9d919287c 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs @@ -1,3 +1,7 @@ +//! This example shows how to use PWM (Pulse Width Modulation) in the RP2040 chip. +//! +//! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index d569f598f..15aa8243f 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -1,3 +1,5 @@ +//! This example shows how to use RTC (Real Time Clock) in the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index a830a17a2..602348f7a 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs @@ -1,3 +1,7 @@ +//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. +//! +//! Example for resistive touch sensor in Waveshare Pico-ResTouch + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index 671a9caaf..328074e8b 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -1,3 +1,6 @@ +//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. +//! No specific hardware is specified in this example. If you connect pin 11 and 12 you should get the same data back. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 2fd201595..26c258e1c 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -1,3 +1,8 @@ +//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. +//! +//! Example written for a display using the ST7789 chip. Possibly the Waveshare Pico-ResTouch +//! (https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs index 05177a6b4..451c3c396 100644 --- a/examples/rp/src/bin/uart.rs +++ b/examples/rp/src/bin/uart.rs @@ -1,3 +1,9 @@ +//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. +//! +//! No specific hardware is specified in this example. Only output on pin 0 is tested. +//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used +//! with its UART port. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index 9df99bd58..735201718 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -1,3 +1,9 @@ +//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. +//! +//! No specific hardware is specified in this example. If you connect pin 0 and 1 you should get the same data back. +//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used +//! with its UART port. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index c0943a1b8..c1515a911 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs @@ -1,5 +1,9 @@ -//! test TX-only and RX-only UARTs. You need to connect GPIO0 to GPIO5 for +//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. +//! +//! Test TX-only and RX-only on two different UARTs. You need to connect GPIO0 to GPIO5 for //! this to work +//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used +//! with its UART port. #![no_std] #![no_main] diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 91d1ec8e7..0a08f667e 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -1,3 +1,7 @@ +//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. +//! +//! This is a CDC-NCM class implementation, aka Ethernet over USB. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs index 7c90d0ca3..9c5e6897d 100644 --- a/examples/rp/src/bin/usb_logger.rs +++ b/examples/rp/src/bin/usb_logger.rs @@ -1,3 +1,7 @@ +//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. +//! +//! This creates the possibility to send log::info/warn/error/debug! to USB serial port. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index ca728536c..164e2052d 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -1,3 +1,7 @@ +//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. +//! +//! This creates a USB serial port that echos. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs index ece5cfe38..fe5eaf926 100644 --- a/examples/rp/src/bin/watchdog.rs +++ b/examples/rp/src/bin/watchdog.rs @@ -1,3 +1,7 @@ +//! This example shows how to use Watchdog in the RP2040 chip. +//! +//! It does not work with the RP Pico W board. See wifi_blinky.rs or connect external LED and resistor. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 3e41f83be..e3e393445 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -1,3 +1,6 @@ +//! This example uses the RP Pico W board Wifi chip (cyw43). +//! Creates an Access point Wifi network and creates a TCP endpoint on port 1234. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index 6eb207af6..33d43788c 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -1,3 +1,7 @@ +//! This example test the RP Pico W on board LED. +//! +//! It does not work with the RP Pico board. See blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index aef18aa24..743fab617 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -1,3 +1,6 @@ +//! This example uses the RP Pico W board Wifi chip (cyw43). +//! Scans Wifi for ssid names. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 4fce74a66..0223a3636 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -1,3 +1,6 @@ +//! This example uses the RP Pico W board Wifi chip (cyw43). +//! Connects to specified Wifi network and creates a TCP endpoint on port 1234. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] -- cgit From 56ca1794759a21d9d5397e5bd4aa8226f6ef9385 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 13 Jul 2023 22:47:03 +0200 Subject: Round temp to make more sense. --- examples/rp/src/bin/adc.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index c0cbe0172..81a8b8340 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -41,5 +41,8 @@ async fn main(_spawner: Spawner) { fn convert_to_celsius(raw_temp: u16) -> f32 { // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet - 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 + let temp = 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721; + let sign = if temp < 0.0 { -1.0 } else { 1.0 }; + let rounded_temp_x10: i16 = ((temp * 10.0) + 0.5 * sign) as i16; + (rounded_temp_x10 as f32) / 10.0 } -- cgit From 88d1976e812af995028025407872bf64264c4f94 Mon Sep 17 00:00:00 2001 From: maximedeboeck <119764381+maximedeboeck@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:31:56 +0200 Subject: Added usb-hid keyboard example for rp pico. --- examples/rp/src/bin/usb_hid_keyboard.rs | 188 ++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 examples/rp/src/bin/usb_hid_keyboard.rs (limited to 'examples/rp/src') diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs new file mode 100644 index 000000000..99af1f02f --- /dev/null +++ b/examples/rp/src/bin/usb_hid_keyboard.rs @@ -0,0 +1,188 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::sync::atomic::{AtomicBool, Ordering}; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_rp::bind_interrupts; +use embassy_rp::gpio::{Input, Pull}; +use embassy_rp::peripherals::USB; +use embassy_rp::usb::{Driver, InterruptHandler}; +use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; +use embassy_usb::control::OutResponse; +use embassy_usb::{Builder, Config, Handler}; +use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + // Create the driver, from the HAL. + let driver = Driver::new(p.USB, Irqs); + + // Create embassy-usb Config + let mut config = Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("HID keyboard example"); + config.serial_number = Some("12345678"); + config.max_power = 100; + config.max_packet_size_0 = 64; + + // 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]; + // You can also add a Microsoft OS descriptor. + // let mut msos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + let request_handler = MyRequestHandler {}; + let mut device_handler = MyDeviceHandler::new(); + + 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.handler(&mut device_handler); + + // Create classes on the builder. + let config = embassy_usb::class::hid::Config { + report_descriptor: KeyboardReport::desc(), + request_handler: Some(&request_handler), + poll_ms: 60, + max_packet_size: 64, + }; + let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Set up the signal pin that will be used to trigger the keyboard. + let mut signal_pin = Input::new(p.PIN_16, Pull::None); + + let (reader, mut writer) = hid.split(); + + // Do stuff with the class! + let in_fut = async { + loop { + info!("Waiting for HIGH on pin 16"); + signal_pin.wait_for_high().await; + info!("HIGH DETECTED"); + // Create a report with the A key pressed. (no shift modifier) + let report = KeyboardReport { + keycodes: [4, 0, 0, 0, 0, 0], + leds: 0, + modifier: 0, + reserved: 0, + }; + // Send the report. + match writer.write_serialize(&report).await { + Ok(()) => {} + Err(e) => warn!("Failed to send report: {:?}", e), + }; + signal_pin.wait_for_low().await; + info!("LOW DETECTED"); + let report = KeyboardReport { + keycodes: [0, 0, 0, 0, 0, 0], + leds: 0, + modifier: 0, + reserved: 0, + }; + match writer.write_serialize(&report).await { + Ok(()) => {} + Err(e) => warn!("Failed to send report: {:?}", e), + }; + } + }; + + let out_fut = async { + reader.run(false, &request_handler).await; + }; + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join(usb_fut, join(in_fut, out_fut)).await; +} + +struct MyRequestHandler {} + +impl RequestHandler for MyRequestHandler { + fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option { + info!("Get report for {:?}", id); + None + } + + fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse { + info!("Set report for {:?}: {=[u8]}", id, data); + OutResponse::Accepted + } + + fn set_idle_ms(&self, id: Option, dur: u32) { + info!("Set idle rate for {:?} to {:?}", id, dur); + } + + fn get_idle_ms(&self, id: Option) -> Option { + info!("Get idle rate for {:?}", id); + None + } +} + +struct MyDeviceHandler { + configured: AtomicBool, +} + +impl MyDeviceHandler { + fn new() -> Self { + MyDeviceHandler { + configured: AtomicBool::new(false), + } + } +} + +impl Handler for MyDeviceHandler { + fn enabled(&mut self, enabled: bool) { + self.configured.store(false, Ordering::Relaxed); + if enabled { + info!("Device enabled"); + } else { + info!("Device disabled"); + } + } + + fn reset(&mut self) { + self.configured.store(false, Ordering::Relaxed); + info!("Bus reset, the Vbus current limit is 100mA"); + } + + fn addressed(&mut self, addr: u8) { + self.configured.store(false, Ordering::Relaxed); + info!("USB address set to: {}", addr); + } + + 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.") + } else { + info!("Device is no longer configured, the Vbus current limit is 100mA."); + } + } +} -- cgit