diff options
| -rw-r--r-- | .cargo/rp-pico-2040.toml | 2 | ||||
| -rw-r--r-- | Cargo.lock | 3 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | crates/rp-pico-2040/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/rp-pico-2040/src/lib.rs | 112 | ||||
| -rw-r--r-- | crates/rp-pico-2040/src/main.rs | 7 | ||||
| -rw-r--r-- | crates/stdio-imxrt-usbd/Cargo.toml | 4 |
7 files changed, 121 insertions, 14 deletions
diff --git a/.cargo/rp-pico-2040.toml b/.cargo/rp-pico-2040.toml index 7bb6886..dfff0e8 100644 --- a/.cargo/rp-pico-2040.toml +++ b/.cargo/rp-pico-2040.toml @@ -2,7 +2,7 @@ target = "thumbv6m-threadx-eabi" [target.thumbv6m-threadx-eabi] -runner = "elf2uf2-rs -d" +runner = "elf2uf2-rs -s -d" rustflags = [ "-Clink-arg=-Tweak-symbols.x", "-Clink-arg=-Tlink.x", @@ -775,8 +775,9 @@ dependencies = [ "embedded-hal 1.0.0", "rp-pico", "rust-threadx-cortex-m", - "rust-threadx-stdio-semihosting", "rust-threadx-sync-single-core", + "usb-device", + "usbd-serial", ] [[package]] @@ -25,6 +25,9 @@ imxrt1170 = { git = "https://git.mciantyre.dev/imxrt-drivers" } ral-registers = { version = "0.2" } +usb-device = "0.3" +usbd-serial = "0.2" + [patch.crates-io] cortex-m = { git = "https://github.com/rust-embedded/cortex-m", rev = "8c62cc47314445346851b0d0664f9cc34c50b24d" } imxrt-ral = { diff --git a/crates/rp-pico-2040/Cargo.toml b/crates/rp-pico-2040/Cargo.toml index 6603bf4..6921f2b 100644 --- a/crates/rp-pico-2040/Cargo.toml +++ b/crates/rp-pico-2040/Cargo.toml @@ -8,6 +8,8 @@ embedded-hal = "1.0" rp-pico = "0.9.0" rust-threadx-cortex-m.workspace = true -rust-threadx-stdio-semihosting.workspace = true rust-threadx-sync-single-core.workspace = true cortex-m.workspace = true + +usb-device.workspace = true +usbd-serial.workspace = true diff --git a/crates/rp-pico-2040/src/lib.rs b/crates/rp-pico-2040/src/lib.rs index 8f877aa..0fb049a 100644 --- a/crates/rp-pico-2040/src/lib.rs +++ b/crates/rp-pico-2040/src/lib.rs @@ -11,12 +11,16 @@ extern crate fusible; use core::pin::Pin; use rust_threadx_cortex_m as _; -use rust_threadx_stdio_semihosting as _; use rust_threadx_sync_single_core as _; use embedded_hal::digital::OutputPin; use rp_pico::hal; use rp_pico::hal::pac; +use usb_device::{class_prelude::*, prelude::*}; +use usbd_serial::SerialPort; + +extern crate alloc; +use alloc::vec::Vec; #[doc(hidden)] #[unsafe(no_mangle)] @@ -45,9 +49,19 @@ pub unsafe extern "C" fn _tx_initialize_low_level() { } } +use fusible::queue::{Queue, QueueContext, StaticQueueSlots}; +use fusible::semaphore::{Semaphore, SemaphoreContext}; use fusible::thread::{StaticStack, Thread, ThreadContext}; -static STACK: StaticStack<512> = StaticStack::new(); -static THREAD: ThreadContext = Thread::context(); + +static BLINK_STACK: StaticStack<512> = StaticStack::new(); +static BLINK_THREAD: ThreadContext = Thread::context(); + +static USB_STACK: StaticStack<8192> = StaticStack::new(); +static USB_THREAD: ThreadContext = Thread::context(); +static USB_EVENT: SemaphoreContext = Semaphore::context(); + +static STDOUT_MSGS: StaticQueueSlots<Vec<u8>, 4> = StaticQueueSlots::new(); +static STDOUT_QUEUE: QueueContext<Vec<u8>> = Queue::context(); #[unsafe(no_mangle)] #[doc(hidden)] @@ -56,7 +70,7 @@ pub extern "C" fn __rust_threadx_app_define() { let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); - hal::clocks::init_clocks_and_plls( + let clocks = hal::clocks::init_clocks_and_plls( rp_pico::XOSC_CRYSTAL_FREQ, pac.XOSC, pac.CLOCKS, @@ -80,8 +94,8 @@ pub extern "C" fn __rust_threadx_app_define() { let mut led_pin = pins.led.into_push_pull_output(); Thread::create( - Pin::static_ref(&THREAD), - STACK.take().unwrap(), + Pin::static_ref(&BLINK_THREAD), + BLINK_STACK.take().unwrap(), &Default::default(), move || loop { led_pin.set_high().unwrap(); @@ -91,4 +105,90 @@ pub extern "C" fn __rust_threadx_app_define() { }, ) .unwrap(); + + let usb_event = Semaphore::create(Pin::static_ref(&USB_EVENT), &Default::default()).unwrap(); + let stdout_queue = Queue::create( + Pin::static_ref(&STDOUT_QUEUE), + STDOUT_MSGS.take().unwrap(), + &Default::default(), + ) + .unwrap(); + + Thread::create( + Pin::static_ref(&USB_THREAD), + USB_STACK.take().unwrap(), + &Default::default(), + move || { + let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new( + pac.USBCTRL_REGS, + pac.USBCTRL_DPRAM, + clocks.usb_clock, + true, + &mut pac.RESETS, + )); + + let mut serial = SerialPort::new(&usb_bus); + let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .strings(&[StringDescriptors::default() + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST")]) + .unwrap() + .device_class(2) + .build(); + + loop { + unsafe { cortex_m::peripheral::NVIC::unmask(hal::pac::Interrupt::USBCTRL_IRQ) }; + usb_event.get().unwrap(); + usb_dev.poll(&mut [&mut serial]); + + serial.read(&mut []).ok(); + + if let Some(msg) = stdout_queue.try_receive() { + let _ = serial.write(&msg); + } + } + }, + ) + .unwrap(); +} + +use hal::pac::interrupt; + +#[interrupt] +fn USBCTRL_IRQ() { + cortex_m::peripheral::NVIC::mask(hal::pac::interrupt::USBCTRL_IRQ); + + // Safety: If the interrupt is unmasked, then we created + // the semaphore. + unsafe { Pin::static_ref(&USB_EVENT).assume_created().put() }; +} + +fn stdout_write(buf: &[u8]) -> usize { + let Some(queue) = Pin::static_ref(&STDOUT_QUEUE).try_created() else { + return 0; + }; + + let msg = Vec::from(buf); + queue.send(msg).unwrap(); + // Wake up the USB thread so it can see our message. + if let Some(usb_event) = Pin::static_ref(&USB_EVENT).try_created() { + usb_event.put(); + } + buf.len() +} + +#[unsafe(no_mangle)] +fn __rust_threadx_stdout_write(buf: &[u8]) -> usize { + stdout_write(buf) +} + +#[unsafe(no_mangle)] +fn __rust_threadx_stderr_write(buf: &[u8]) -> usize { + stdout_write(buf) +} + +#[unsafe(no_mangle)] +fn __rust_threadx_stdin_read(_: &mut [u8]) -> usize { + 0 // Haven't tried it. } diff --git a/crates/rp-pico-2040/src/main.rs b/crates/rp-pico-2040/src/main.rs index b155870..389257a 100644 --- a/crates/rp-pico-2040/src/main.rs +++ b/crates/rp-pico-2040/src/main.rs @@ -3,9 +3,10 @@ use rust_threadx_rp_pico_2040 as _; use std::{thread, time::Duration}; fn main() { - // Nothing interesting yet. Nevertheless, the LED should - // be blinking on a background thread. + let mut count = 0_usize; loop { - thread::sleep(Duration::from_millis(100)); + println!("Hello world! The count is {count}\r"); + thread::sleep(Duration::from_millis(1_000)); + count = count.wrapping_add(1); } } diff --git a/crates/stdio-imxrt-usbd/Cargo.toml b/crates/stdio-imxrt-usbd/Cargo.toml index ce3012e..87c5d0d 100644 --- a/crates/stdio-imxrt-usbd/Cargo.toml +++ b/crates/stdio-imxrt-usbd/Cargo.toml @@ -6,8 +6,8 @@ publish = false [dependencies] imxrt-usbd = "0.4" -usb-device = "0.3" -usbd-serial = "0.2" +usb-device = { workspace = true } +usbd-serial = { workspace = true } cortex-m = { workspace = true } imxrt-ral = { workspace = true } |
