Crate esp32_wroom_rp

source ·
Expand description

esp32-wroom-rp

This crate is an Espressif ESP32-WROOM WiFi module communications driver for RP2040 series microcontroller implemented in Rust. It currently supports the ESP32-WROOM-32E and ESP32-WROOM-32UE modules. Future implementations intend to add support for the ESP32-WROOM-DA module.

It’s intended to communicate with recent versions of most Arduino-derived WiFiNINA firmwares that run on an ESP32-WROOM-XX WiFi module. For example, Adafruit makes such WiFi hardware, referred to as the Airlift, and maintains its firmware.

This driver is implemented on top of embedded-hal, which makes it platform-independent, but is currently only intended to be used with rp2040-hal for your application.

Please see the README.md for details on where to obtain and how to connect your RP2040-based device (e.g. Pico) to your ESP32-WROOM-XX WiFi board.

Once connected, note that all communication with the WiFi board occurs via a SPI bus. As the example below (and all examples under the directory cross/) show, you first need to create an embedded_hal::spi::Spi instance. See the rp2040-hal documentation along with the datasheet for your device on what specific SPI ports are available to you.

You’ll also need to reserve 4 important GPIO pins (3 output, 1 input) that are used to mediate communication between the two boards. The examples also demonstrate how to do this through instantiating an instance of esp32_wroom_rp::gpio::EspControlPins.

NOTE: This crate is still under active development. This API will remain volatile until 1.0.0.

Usage

First add this to your Cargo.toml

[dependencies]
esp32_wroom_rp = 0.3.0
...

Next:

// The macro for our start-up function
use cortex_m_rt::entry;

// Needed for debug output symbols to be linked in binary image
use defmt_rtt as _;

use panic_probe as _;

// Alias for our HAL crate
use rp2040_hal as hal;

use embedded_hal::spi::MODE_0;
use fugit::RateExtU32;
use hal::clocks::Clock;
use hal::pac;

use esp32_wroom_rp::gpio::EspControlPins;
use esp32_wroom_rp::wifi::Wifi;

// The linker will place this boot block at the start of our program image. We
// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;

// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
// if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32;

// Entry point to our bare-metal application.
//
// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
// as soon as all global variables are initialized.
#[entry]
fn main() -> ! {
    // Grab our singleton objects
    let mut pac = pac::Peripherals::take().unwrap();
    let core = pac::CorePeripherals::take().unwrap();

    // Set up the watchdog driver - needed by the clock setup code
    let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);

    // Configure the clocks
    let clocks = hal::clocks::init_clocks_and_plls(
        XTAL_FREQ_HZ,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

    // The single-cycle I/O block controls our GPIO pins
    let sio = hal::Sio::new(pac.SIO);

    // Set the pins to their default state
    let pins = hal::gpio::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    defmt::info!("ESP32-WROOM-RP get NINA firmware version example");

    // These are implicitly used by the spi driver if they are in the correct mode
    let _spi_miso = pins.gpio16.into_mode::<hal::gpio::FunctionSpi>();
    let _spi_sclk = pins.gpio18.into_mode::<hal::gpio::FunctionSpi>();
    let _spi_mosi = pins.gpio19.into_mode::<hal::gpio::FunctionSpi>();

    let spi = hal::Spi::<_, _, 8>::new(pac.SPI0);

    // Exchange the uninitialized SPI driver for an initialized one
    let spi = spi.init(
        &mut pac.RESETS,
        clocks.peripheral_clock.freq(),
        8.MHz(),
        &MODE_0,
    );

    let esp_pins = EspControlPins {
        // CS on pin x (GPIO7)
        cs: pins.gpio7.into_mode::<hal::gpio::PushPullOutput>(),
        // GPIO0 on pin x (GPIO2)
        gpio0: pins.gpio2.into_mode::<hal::gpio::PushPullOutput>(),
        // RESETn on pin x (GPIO11)
        resetn: pins.gpio11.into_mode::<hal::gpio::PushPullOutput>(),
        // ACK on pin x (GPIO10)
        ack: pins.gpio10.into_mode::<hal::gpio::FloatingInput>(),
    };
    let mut wifi = Wifi::init(spi, esp_pins, &mut delay).unwrap();
    let firmware_version = wifi.firmware_version();
    defmt::info!("NINA firmware version: {:?}", firmware_version);

    // Infinitely sit in a main loop
    loop {}
}

More examples

Please refer to the cross/ directory in this crate’s source for examples that demonstrate how to use every part of its public API.

Modules

GPIO pin control interface of a connected ESP32-WROOM target WiFi board.
Defines common network functions, types and error definitions.
Defines functions, types and error definitions related to the WiFiNINA protocol communication specification.
Send/receive data to/from a TCP server and associated types.
Perform common core WiFi functions such as join a network, resolve a DNS hostname, etc.

Structs

A structured representation of a connected NINA firmware device’s version number (e.g. 1.7.4).

Enums

Highest level error types for this crate.