Skip to content

Commit

Permalink
Remove usage of dyn, instead use an enum for runtime dispatch (#33)
Browse files Browse the repository at this point in the history
* Remove usage of dyn, instead use an enum for runtime dispatch

* cfg rework, transport enum

Remove much of the cfg blocks from varios places. Where possible, new
concise cfgs have been introduced.

Adds a transport to replace dyn.
  • Loading branch information
MabezDev authored Sep 11, 2023
1 parent 4d97c62 commit a035f30
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 85 deletions.
15 changes: 15 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,19 @@ fn main() {
println!("cargo:rerun-if-changed=ld/ld/esp32s3_rom.x");
println!("cargo:rustc-link-arg=-Tld/esp32s3_rom.x");
}

emit_cfg();
}

fn emit_cfg() {
#[cfg(any(
feature = "esp32c3",
feature = "esp32s3",
feature = "esp32c6",
feature = "esp32h2"
))]
println!("cargo:rustc-cfg=usb_device");

#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
println!("cargo:rustc-cfg=usb0");
}
71 changes: 65 additions & 6 deletions src/io.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,73 @@
use core::marker::PhantomData;

use heapless::Deque;

use crate::protocol::InputIO;

pub mod uart;
#[cfg(any(
feature = "esp32c3",
feature = "esp32s3",
feature = "esp32c6",
feature = "esp32h2"
))]
#[cfg(usb_device)]
pub mod usb_serial_jtag;

const RX_QUEUE_SIZE: usize = crate::targets::MAX_WRITE_BLOCK + 0x400;

static mut RX_QUEUE: Deque<u8, RX_QUEUE_SIZE> = Deque::new();

trait UartMarker: InputIO {}
trait UsbSerialJtagMarker: InputIO {}
trait UsbOtgMarker: InputIO {}

#[non_exhaustive]
pub enum Transport<S, J, U> {
Uart(S),
#[cfg(usb_device)]
UsbSerialJtag(J),
#[cfg(usb0)]
UsbOtg(U),
#[doc(hidden)]
__Hidden(PhantomData<J>, PhantomData<U>),
}

impl<S, J, U> InputIO for Transport<S, J, U>
where
S: UartMarker,
J: UsbSerialJtagMarker,
U: UsbOtgMarker,
{
fn recv(&mut self) -> u8 {
match self {
Transport::Uart(s) => s.recv(),
#[cfg(usb_device)]
Transport::UsbSerialJtag(j) => j.recv(),
_ => todo!(),
}
}

fn send(&mut self, data: &[u8]) {
match self {
Transport::Uart(s) => s.send(data),
#[cfg(usb_device)]
Transport::UsbSerialJtag(j) => j.send(data),
_ => todo!(),
}
}
}

pub struct Noop;

impl InputIO for Noop {
fn recv(&mut self) -> u8 {
todo!()
}

fn send(&mut self, _data: &[u8]) {
todo!()
}
}

impl UartMarker for Noop {}
impl UsbSerialJtagMarker for Noop {}
impl UsbOtgMarker for Noop {}

impl<T: UartMarker> UartMarker for &mut T {}
impl<T: UsbSerialJtagMarker> UsbSerialJtagMarker for &mut T {}
impl<T: UsbOtgMarker> UsbOtgMarker for &mut T {}
6 changes: 4 additions & 2 deletions src/io/uart.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::RX_QUEUE;
use super::{UartMarker, RX_QUEUE};
use crate::{
hal::{peripherals::UART0, prelude::*, uart::Instance, Uart},
protocol::InputIO,
Expand All @@ -15,6 +15,8 @@ impl<T: Instance> InputIO for Uart<'_, T> {
}
}

impl<T: Instance> UartMarker for Uart<'_, T> {}

#[interrupt]
fn UART0() {
let uart = unsafe { &*UART0::ptr() };
Expand All @@ -30,7 +32,7 @@ fn UART0() {
// the read _must_ be a word read so the hardware correctly detects the read and
// pops the byte from the fifo cast the result to a u8, as only the
// first byte contains the data
let data = unsafe { (uart.fifo.as_ptr() as *mut u32).offset(offset).read() } as u8;
let data = unsafe { uart.fifo.as_ptr().offset(offset).read() } as u8;
unsafe { RX_QUEUE.push_back(data).unwrap() };
}

Expand Down
4 changes: 3 additions & 1 deletion src/io/usb_serial_jtag.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::RX_QUEUE;
use super::{UsbSerialJtagMarker, RX_QUEUE};
use crate::{
hal::{
prelude::*,
Expand All @@ -18,6 +18,8 @@ impl InputIO for UsbSerialJtag<'_> {
}
}

impl UsbSerialJtagMarker for UsbSerialJtag<'_> {}

#[interrupt]
unsafe fn USB_DEVICE() {
let usj = crate::hal::peripherals::USB_DEVICE::steal();
Expand Down
37 changes: 8 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ pub use esp32h2_hal as hal;
pub use esp32s2_hal as hal;
#[cfg(feature = "esp32s3")]
pub use esp32s3_hal as hal;
// Due to a bug in esp-hal this MUST be included in the root.
#[cfg(target_arch = "riscv32")]
pub use hal::interrupt;
// Re-export the correct target based on which feature is active
#[cfg(feature = "esp32")]
pub use targets::Esp32 as target;
Expand All @@ -44,18 +41,15 @@ pub mod targets;
#[derive(Debug)]
pub enum TransportMethod {
Uart,
#[cfg(any(
feature = "esp32c3",
feature = "esp32s3",
feature = "esp32c6",
feature = "esp32h2"
))]
#[cfg(usb_device)]
UsbSerialJtag,
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
#[cfg(usb0)]
UsbOtg,
}

pub fn detect_transport() -> TransportMethod {
#[allow(unused)]
use targets::{EspUsbOtgId, EspUsbSerialJtagId};
#[repr(C)]
struct Uart {
baud_rate: u32,
Expand All @@ -72,28 +66,13 @@ pub fn detect_transport() -> TransportMethod {
extern "C" {
fn esp_flasher_rom_get_uart() -> *const Uart;
}
#[cfg(any(feature = "esp32c3", feature = "esp32c6", feature = "esp32h2"))]
const USB_SERIAL_JTAG: u8 = 3;
#[cfg(any(feature = "esp32s3"))]
const USB_SERIAL_JTAG: u8 = 4;

#[cfg(feature = "esp32s3")]
const USB_OTG: u8 = 3;
#[cfg(feature = "esp32s2")]
const USB_OTG: u8 = 2;

let device = unsafe { esp_flasher_rom_get_uart() };
let num = unsafe { (*device).buff_uart_no };
match num {
#[cfg(any(
feature = "esp32c3",
feature = "esp32s3",
feature = "esp32c6",
feature = "esp32h2"
))]
USB_SERIAL_JTAG => TransportMethod::UsbSerialJtag,
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
USB_OTG => TransportMethod::UsbOtg,
#[cfg(usb_device)]
target::USB_SERIAL_JTAG_ID => TransportMethod::UsbSerialJtag,
#[cfg(usb0)]
target::USB_OTG_ID => TransportMethod::UsbOtg,
_ => TransportMethod::Uart,
}
}
39 changes: 28 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,35 @@ use flasher_stub::hal::uart::{
};
use flasher_stub::{
hal::{clock::ClockControl, interrupt, peripherals, prelude::*, Uart, IO},
protocol::{InputIO, Stub},
io::Noop,
protocol::Stub,
targets,
};
use static_cell::StaticCell;

const MSG_BUFFER_SIZE: usize = targets::MAX_WRITE_BLOCK + 0x400;

// TODO this sucks, but default generic parameters are not used when inference
// fails, meaning that we _have_ to specifiy the types here Seems like work on this has stalled: https://github.com/rust-lang/rust/issues/27336, note that I tried the feature and it didn't work.
#[cfg(not(any(usb_device, usb0)))]
type Transport =
flasher_stub::io::Transport<&'static mut Uart<'static, crate::peripherals::UART0>, Noop, Noop>;
#[cfg(all(usb_device, not(usb0)))]
type Transport = flasher_stub::io::Transport<
&'static mut Uart<'static, crate::peripherals::UART0>,
&'static mut flasher_stub::hal::UsbSerialJtag<'static>,
Noop,
>;
#[cfg(all(not(usb_device), usb0))]
type Transport =
flasher_stub::io::Transport<&'static mut Uart<'static, crate::peripherals::UART0>, Noop, Noop>; // TODO replace Noop with usb type later
#[cfg(all(usb_device, usb0))]
type Transport = flasher_stub::io::Transport<
&'static mut Uart<'static, crate::peripherals::UART0>,
&'static mut flasher_stub::hal::UsbSerialJtag<'static>,
Noop, // TODO replace Noop with usb type later
>;

#[flasher_stub::hal::entry]
fn main() -> ! {
let peripherals = peripherals::Peripherals::take();
Expand Down Expand Up @@ -62,7 +84,7 @@ fn main() -> ! {
let transport = flasher_stub::detect_transport();
flasher_stub::dprintln!("Stub init! Transport detected: {:?}", transport);

let transport: &'static mut dyn InputIO = match transport {
let transport = match transport {
flasher_stub::TransportMethod::Uart => {
let mut serial = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);

Expand All @@ -76,14 +98,9 @@ fn main() -> ! {

static mut TRANSPORT: StaticCell<Uart<'static, crate::peripherals::UART0>> =
StaticCell::new();
unsafe { TRANSPORT.init(serial) }
Transport::Uart(unsafe { TRANSPORT.init(serial) })
}
#[cfg(any(
feature = "esp32c3",
feature = "esp32s3",
feature = "esp32c6",
feature = "esp32h2"
))]
#[cfg(usb_device)]
flasher_stub::TransportMethod::UsbSerialJtag => {
let mut usb_serial = flasher_stub::hal::UsbSerialJtag::new(
peripherals.USB_DEVICE,
Expand All @@ -98,9 +115,9 @@ fn main() -> ! {

static mut TRANSPORT: StaticCell<flasher_stub::hal::UsbSerialJtag<'static>> =
StaticCell::new();
unsafe { TRANSPORT.init(usb_serial) }
Transport::UsbSerialJtag(unsafe { TRANSPORT.init(usb_serial) })
}
#[cfg(any(feature = "esp32s2", feature = "esp32s3"))]
#[cfg(usb0)]
flasher_stub::TransportMethod::UsbOtg => unimplemented!(),
};

Expand Down
Loading

0 comments on commit a035f30

Please sign in to comment.