Skip to main content

BusAllocator

Struct BusAllocator 

Source
pub struct BusAllocator { /* private fields */ }

Implementations§

Source§

impl BusAllocator

Source

pub fn new( spi0: Option<Peri<'static, SPI0>>, spi1: Option<Peri<'static, SPI1>>, i2c0: Option<Peri<'static, I2C0>>, i2c1: Option<Peri<'static, I2C1>>, uart0: Option<Peri<'static, UART0>>, uart1: Option<Peri<'static, UART1>>, dma: DmaPool, pio0: Peri<'static, PIO0>, pio1: Peri<'static, PIO1>, pio2: Peri<'static, PIO2>, ) -> Self

Creates an allocator holding every provided peripheral.

Supply None for any hardware instance the board does not want to expose to drivers. Every PIO block is mandatory because PIO state machines back several fallback buses.

§Example
use xpanse_api::bus::allocator::{BusAllocator, DmaPool};

let p = embassy_rp::init(Default::default());
let buses = BusAllocator::new(
    Some(p.SPI0),
    Some(p.SPI1),
    Some(p.I2C0),
    Some(p.I2C1),
    Some(p.UART0),
    Some(p.UART1),
    DmaPool::none(),
    p.PIO0,
    p.PIO1,
    p.PIO2,
);
Source

pub fn request_spi_hardware<I: SpiHw>( &mut self, ) -> Result<Peri<'static, I>, AllocatorError>

Requests exclusive access to one hardware SPI peripheral.

Returns AllocatorError::Exhausted if the peripheral has already been handed out.

Source

pub fn release_spi_hardware<I: SpiHw>(&mut self, peri: Peri<'static, I>)

Returns a hardware SPI peripheral to the reusable pool.

Source

pub fn request_dma<C: DmaChannel>( &mut self, ) -> Result<Peri<'static, C>, AllocatorError>

Requests exclusive access to one DMA channel.

Returns AllocatorError::Exhausted if the channel has already been handed out.

Source

pub fn release_dma<C: DmaChannel>(&mut self, peri: Peri<'static, C>)

Returns a DMA channel to the reusable pool.

Source

pub fn create_spi_hardware<I, TxDma, RxDma, Irq>( &mut self, clk: Peri<'static, impl ClkPin<I>>, mosi: Peri<'static, impl MosiPin<I>>, miso: Peri<'static, impl MisoPin<I>>, irq: Irq, config: Config, ) -> Result<SpiBusHandle, AllocatorError>
where I: SpiHw, TxDma: DmaChannel, RxDma: DmaChannel, Irq: Binding<TxDma::Interrupt, InterruptHandler<TxDma>> + Binding<RxDma::Interrupt, InterruptHandler<RxDma>> + 'static,

Builds a hardware SPI bus backed by DMA (truly async). Pin roles and instance are checked at compile time: clk must be a ClkPin<I>, mosi a MosiPin<I>, miso a MisoPin<I>. The DMA channels are pulled from the allocator’s pool; the IRQ binding is the board’s zero-sized bind_interrupts! type.

§Errors

Returns AllocatorError::InvalidConfiguration for an unsupported SPI clock, or if TxDma and RxDma name the same DMA channel type. Returns AllocatorError::Exhausted if the SPI peripheral or either DMA channel is unavailable; in that case already-acquired resources are released.

§Example
use embassy_rp::spi;
use xpanse_api::bus::allocator::BusAllocator;
use xpanse_api::reexports::embassy_rp::{peripherals::*, interrupt::typelevel::Binding};

embassy_rp::bind_interrupts!(struct Irqs {
    DMA_CH0 => embassy_rp::dma::InterruptHandler<DMA_CH0>;
    DMA_CH1 => embassy_rp::dma::InterruptHandler<DMA_CH1>;
});

fn make_spi(buses: &mut BusAllocator, p: SplitParts) -> SpiBusHandle {
    buses.create_spi_hardware::<SPI0, DMA_CH0, DMA_CH1, _>(
        p.gpio2, p.gpio4, p.gpio3, Irqs, spi::Config::default(),
    )
    .expect("SPI configured in range")
}
Source

pub fn create_spi_pio<TxDma, RxDma, Irq>( &mut self, clk: Peri<'static, impl PioPin>, mosi: Peri<'static, impl PioPin>, miso: Peri<'static, impl PioPin>, irq: Irq, config: Config, ) -> Result<SpiBusHandle, AllocatorError>
where TxDma: DmaChannel, RxDma: DmaChannel, Irq: Binding<TxDma::Interrupt, InterruptHandler<TxDma>> + Binding<RxDma::Interrupt, InterruptHandler<RxDma>> + 'static,

Builds a PIO-backed SPI bus (async via DMA) on any free PIO state machine.

§Errors

Returns AllocatorError::InvalidConfiguration if the clock frequency is unsupported, the pins span different GPIO banks, or the requested TX and RX DMA channels are the same type. Returns AllocatorError::Exhausted if no matching PIO state machine or DMA channel is free; acquired DMA channels are released on failure.

Source

pub fn create_spi_bitbang( &mut self, clk: Peri<'static, impl Pin>, mosi: Peri<'static, impl Pin>, miso: Peri<'static, impl Pin>, config: Config, ) -> Result<SpiBusHandle, AllocatorError>

Builds a bit-banged SPI bus using only GPIO.

§Errors

Returns AllocatorError::InvalidConfiguration only for an SPI clock outside the bit-bang timing range.

Source

pub fn create_spi_no_hardware<TxDma, RxDma, Irq>( &mut self, clk: Peri<'static, impl PioPin>, mosi: Peri<'static, impl PioPin>, miso: Peri<'static, impl PioPin>, irq: Irq, config: Config, ) -> Result<SpiBusHandle, AllocatorError>
where TxDma: DmaChannel, RxDma: DmaChannel, Irq: Binding<TxDma::Interrupt, InterruptHandler<TxDma>> + Binding<RxDma::Interrupt, InterruptHandler<RxDma>> + 'static,

Builds a SPI bus that doesn’t use hardware, preferring PIO then bit-bang.

If PIO cannot be built, any PIO SM reservation is released before dropping to a bit-banged bus.

Returns AllocatorError::InvalidConfiguration if the frequency is unsupported anywhere, or if the requested TX and RX DMA channels are the same type.

Source

pub fn create_spi<I, TxDma, RxDma, Irq>( &mut self, clk: Peri<'static, impl ClkPin<I> + PioPin>, mosi: Peri<'static, impl MosiPin<I> + PioPin>, miso: Peri<'static, impl MisoPin<I> + PioPin>, irq: Irq, config: Config, ) -> Result<SpiBusHandle, AllocatorError>
where I: SpiHw, TxDma: DmaChannel, RxDma: DmaChannel, Irq: Binding<TxDma::Interrupt, InterruptHandler<TxDma>> + Binding<RxDma::Interrupt, InterruptHandler<RxDma>> + 'static,

Builds a SPI bus, preferring hardware then PIO then bit-bang.

Pins must implement both role-checked SPI traits and PioPin so a PIO fallback remains possible. If hardware SPI cannot be built, DMA channels are released before falling back. If PIO cannot be built, any PIO SM reservation is released before dropping to a bit-banged bus.

Returns AllocatorError::InvalidConfiguration if the frequency is unsupported anywhere, or if the requested TX and RX DMA channels are the same type.

Source

pub fn request_i2c_hardware<I: I2cHw>( &mut self, ) -> Result<Peri<'static, I>, AllocatorError>

Requests exclusive access to one hardware I2C peripheral.

Returns AllocatorError::Exhausted if the peripheral has already been handed out.

Source

pub fn release_i2c_hardware<I: I2cHw>(&mut self, peri: Peri<'static, I>)

Returns a hardware I2C peripheral to the reusable pool.

Source

pub fn create_i2c_hardware<I, Irq>( &mut self, scl: Peri<'static, impl SclPin<I>>, sda: Peri<'static, impl SdaPin<I>>, irq: Irq, config: Config, ) -> Result<I2cBusHandle, AllocatorError>
where I: I2cHw, Irq: Binding<I::Interrupt, InterruptHandler<I>> + 'static,

Builds a hardware I2C bus (async, interrupt-driven — no DMA needed).

scl and sda are role-checked against I at compile time, and irq is the board’s bind_interrupts! type for the I2C interrupt.

§Errors

Returns AllocatorError::InvalidConfiguration if the frequency or derived clock dividers are out of range, or AllocatorError::Exhausted if the I2C peripheral is unavailable.

§Example
use embassy_rp::i2c;
use xpanse_api::bus::allocator::BusAllocator;

embassy_rp::bind_interrupts!(struct Irqs {
    I2C0_IRQ => embassy_rp::i2c::InterruptHandler<embassy_rp::peripherals::I2C0>;
});

let bus = buses.create_i2c_hardware::<embassy_rp::peripherals::I2C0, _>(
    p.gpio0, p.gpio1, Irqs, i2c::Config::default(),
)
.expect("I2C configured in range");
Source

pub fn create_i2c_bitbang( &mut self, scl: Peri<'static, impl Pin>, sda: Peri<'static, impl Pin>, frequency_hz: u32, ) -> Result<I2cBusHandle, AllocatorError>

Builds a bit-banged I2C bus using two GPIO pins with open-drain capability. Frequencies outside the timer’s range are rejected. scl and sda may be any GPIO pins; they are not role-checked.

§Errors

Returns AllocatorError::InvalidConfiguration for a frequency above twice the timer tick rate or zero.

Source

pub fn request_uart_hardware<I: UartHw>( &mut self, ) -> Result<Peri<'static, I>, AllocatorError>

Requests exclusive access to one hardware UART peripheral.

Returns AllocatorError::Exhausted if the peripheral has already been handed out.

Source

pub fn release_uart_hardware<I: UartHw>(&mut self, peri: Peri<'static, I>)

Returns a hardware UART peripheral to the reusable pool.

Source

pub fn create_uart_hardware<I, TxDma, RxDma, Irq>( &mut self, tx: Peri<'static, impl TxPin<I>>, rx: Peri<'static, impl RxPin<I>>, irq: Irq, config: Config, ) -> Result<UartBusHandle, AllocatorError>
where I: UartHw, TxDma: DmaChannel, RxDma: DmaChannel, Irq: Binding<I::Interrupt, InterruptHandler<I>> + Binding<TxDma::Interrupt, InterruptHandler<TxDma>> + Binding<RxDma::Interrupt, InterruptHandler<RxDma>> + 'static,

Builds a hardware (DMA) UART bus.

tx and rx are role-checked against I at compile time. The DMA channels are pulled from the allocator’s pool.

§Errors

Returns AllocatorError::InvalidConfiguration for an unsupported baud rate or if TxDma and RxDma name the same channel type. Returns AllocatorError::Exhausted if the UART peripheral or a DMA channel is unavailable; already-acquired resources are released on failure.

Source

pub fn create_uart_pio( &mut self, tx: Peri<'static, impl PioPin>, rx: Peri<'static, impl PioPin>, baud_rate: u32, ) -> Result<UartBusHandle, AllocatorError>

Builds a PIO-backed UART bus on any two free state machines of one block.

PIO UART uses FIFO polling and needs no DMA.

§Errors

Returns AllocatorError::InvalidConfiguration if the baud rate is unsupported or tx and rx are not in the same GPIO bank. Returns AllocatorError::Exhausted if no PIO state machine pair is free.

Source

pub fn create_uart_bitbang( &mut self, tx: Peri<'static, impl Pin>, rx: Peri<'static, impl Pin>, baud_rate: u32, ) -> Result<UartBusHandle, AllocatorError>

Builds a bit-banged UART bus using only GPIO at a representable baud.

8-N-1 framing, idle-high TX line, one-byte reads.

§Errors

Returns AllocatorError::InvalidConfiguration for a baud rate of zero or above the timer’s maximum.

Source

pub fn create_uart_no_hardware( &mut self, tx: Peri<'static, impl PioPin>, rx: Peri<'static, impl PioPin>, baud_rate: u32, ) -> Result<UartBusHandle, AllocatorError>

Builds a UART bus, preferring PIO then bit-bang.

Hardware UART requires DMA — request it explicitly with create_uart_hardware or BusAllocator::create_uart(Self::create_uart).

§Errors

Returns AllocatorError::InvalidConfiguration if the baud rate is unsupported or tx and rx are not in the same GPIO bank. Returns AllocatorError::Exhausted if PIO state machines are free but all fallbacks ultimately fail.

Source

pub fn create_uart<I, TxDma, RxDma, Irq>( &mut self, tx: Peri<'static, impl TxPin<I> + PioPin>, rx: Peri<'static, impl RxPin<I> + PioPin>, irq: Irq, config: Config, ) -> Result<UartBusHandle, AllocatorError>
where I: UartHw, TxDma: DmaChannel, RxDma: DmaChannel, Irq: Binding<I::Interrupt, InterruptHandler<I>> + Binding<TxDma::Interrupt, InterruptHandler<TxDma>> + Binding<RxDma::Interrupt, InterruptHandler<RxDma>> + 'static,

Builds a UART bus, preferring hardware then PIO then bit-bang.

Pins must implement both role-checked UART traits and PioPin so a PIO fallback remains possible. On the hardware failure path, any acquired UART peripheral or DMA channel is released before the fallback is attempted.

§Errors

Returns AllocatorError::InvalidConfiguration if the baud rate is unsupported or TxDma and RxDma name the same channel type. Returns AllocatorError::Exhausted if all three backends are unavailable.

Source

pub fn request_pio<P: PioPin>( &mut self, pin: &Peri<'static, P>, ) -> Option<PioAccess<'_>>

Hands out one free PIO state machine on any block, together with the block’s Common handle. Drivers that load custom PIO programs use this, then call with_pio! to dispatch over the erased block/SM types.

The Common borrow is only valid while the returned crate::bus::pio::PioAccess is alive (i.e. while you hold &mut BusAllocator). Programs loaded via Common produce 'static handles, so a driver can load a program, configure the SM, and then keep the LoadedProgram + StateMachine after the borrow ends.

Returns None if every state machine on every block is in use, the pin is not a PIO-capable GPIO, or 32 instructions have already been reserved.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where Dst: LosslessTryFrom<Src>,

Source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
Source§

impl<Src, Dst> LossyInto<Dst> for Src
where Dst: LossyFrom<Src>,

Source§

fn lossy_into(self) -> Dst

Performs the conversion.
Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.