pub struct BusAllocator { /* private fields */ }Implementations§
Source§impl BusAllocator
impl BusAllocator
Sourcepub 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
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,
);Sourcepub fn request_spi_hardware<I: SpiHw>(
&mut self,
) -> Result<Peri<'static, I>, AllocatorError>
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.
Sourcepub fn release_spi_hardware<I: SpiHw>(&mut self, peri: Peri<'static, I>)
pub fn release_spi_hardware<I: SpiHw>(&mut self, peri: Peri<'static, I>)
Returns a hardware SPI peripheral to the reusable pool.
Sourcepub fn request_dma<C: DmaChannel>(
&mut self,
) -> Result<Peri<'static, C>, AllocatorError>
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.
Sourcepub fn release_dma<C: DmaChannel>(&mut self, peri: Peri<'static, C>)
pub fn release_dma<C: DmaChannel>(&mut self, peri: Peri<'static, C>)
Returns a DMA channel to the reusable pool.
Sourcepub 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,
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")
}Sourcepub 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,
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.
Sourcepub 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>
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.
Sourcepub 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,
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.
Sourcepub 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,
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.
Sourcepub fn request_i2c_hardware<I: I2cHw>(
&mut self,
) -> Result<Peri<'static, I>, AllocatorError>
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.
Sourcepub fn release_i2c_hardware<I: I2cHw>(&mut self, peri: Peri<'static, I>)
pub fn release_i2c_hardware<I: I2cHw>(&mut self, peri: Peri<'static, I>)
Returns a hardware I2C peripheral to the reusable pool.
Sourcepub 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>
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>
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");Sourcepub fn create_i2c_bitbang(
&mut self,
scl: Peri<'static, impl Pin>,
sda: Peri<'static, impl Pin>,
frequency_hz: u32,
) -> Result<I2cBusHandle, AllocatorError>
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.
Sourcepub fn request_uart_hardware<I: UartHw>(
&mut self,
) -> Result<Peri<'static, I>, AllocatorError>
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.
Sourcepub fn release_uart_hardware<I: UartHw>(&mut self, peri: Peri<'static, I>)
pub fn release_uart_hardware<I: UartHw>(&mut self, peri: Peri<'static, I>)
Returns a hardware UART peripheral to the reusable pool.
Sourcepub 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,
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.
Sourcepub fn create_uart_pio(
&mut self,
tx: Peri<'static, impl PioPin>,
rx: Peri<'static, impl PioPin>,
baud_rate: u32,
) -> Result<UartBusHandle, AllocatorError>
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.
Sourcepub fn create_uart_bitbang(
&mut self,
tx: Peri<'static, impl Pin>,
rx: Peri<'static, impl Pin>,
baud_rate: u32,
) -> Result<UartBusHandle, AllocatorError>
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.
Sourcepub fn create_uart_no_hardware(
&mut self,
tx: Peri<'static, impl PioPin>,
rx: Peri<'static, impl PioPin>,
baud_rate: u32,
) -> Result<UartBusHandle, AllocatorError>
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.
Sourcepub 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,
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.
Sourcepub fn request_pio<P: PioPin>(
&mut self,
pin: &Peri<'static, P>,
) -> Option<PioAccess<'_>>
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.