Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PIO and SPI

Before the RP2040 can communicate with the CYW43439, it first needs a communication interface. As we learned in the previous chapters, the Pico W uses a PIO-based SPI interface instead of one of the RP2040’s hardware SPI peripherals.

The first two lines configure the control pins used by the wireless chip.

#![allow(unused)]
fn main() {
let pwr = Output::new(p.PIN_23, Level::Low);
let cs = Output::new(p.PIN_25, Level::High);
}

PIN_23 is connected to the power control pin of the CYW43439, while PIN_25 is connected to its chip select (CS) pin. The power control pin is initialized to Low so the wireless chip remains disabled until the driver is ready to initialize it. The chip select pin is initialized to High because SPI chip select is active low, ensuring the CYW43439 is not selected until an SPI transaction begins.

Before creating the PIO instance, we bind the interrupt used by the PIO program. This allows Embassy to handle interrupts generated by the PIO state machine.

#![allow(unused)]
fn main() {
bind_interrupts!(struct Irqs {
    PIO0_IRQ_0 => InterruptHandler<PIO0>;
});
}

Next, we create the PIO instance.

#![allow(unused)]
fn main() {
let mut pio = Pio::new(p.PIO0, Irqs);
}

This gives us access to one of the RP2040’s PIO blocks.

Finally, we create the PIO-based SPI interface.

The PioSpi type is provided by the cyw43-pio crate. It implements the SPI protocol using one of the RP2040’s PIO state machines. Although its constructor accepts several parameters, most of them should already be familiar. We provide the PIO state machine, the chip select pin, the data and clock pins, and a DMA channel to create a communication interface between the RP2040 and the CYW43439.

#![allow(unused)]
fn main() {
let spi = PioSpi::new(
    &mut pio.common,
    pio.sm0,
    DEFAULT_CLOCK_DIVIDER,
    pio.irq0,
    cs,
    p.PIN_24,
    p.PIN_29,
    p.DMA_CH0,
);
}

The resulting spi object represents the communication channel between the RP2040 and the CYW43439. The CYW43 driver uses this interface whenever it needs to transfer firmware, configure the wireless chip, or send commands such as turning the onboard LED on or off.