Skip to content

Commit

Permalink
Overhaul pin modules.
Browse files Browse the repository at this point in the history
- Added `AdcPin` wrapper to disable digital function for ADC operations
- Added `Sealed` supertrait to `PIOExt`
- Added pins to `Spi` to fix inconsistencies in gpio bounds in peripheral (i2c, uart, spi)
- Merge DynPin and Pin into Pin. The type class used in Pin now have a runtime variant allowing for
  the creation of uniform array of pins (eg: `[Pin<DynPinId, PinFnSio, PullDown>]`).
- Fix miss defined ValidPinMode bound allowing any Bank0 pin to be Xip and any Qspi pin to be any
  other function (except for clock).
- Use `let _ = ` to ignore result rather than `.ok();` as this gives a false sense the result is
  checked.

Addresses: #140, #446, #481, #485, #556
  • Loading branch information
ithinuel committed Apr 22, 2023
1 parent d6fad75 commit bca414c
Show file tree
Hide file tree
Showing 40 changed files with 2,396 additions and 2,802 deletions.
11 changes: 11 additions & 0 deletions rp2040-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Re-enabled implementations of traits from embedded-hal-nb 1.0.0-alpha.1 - @jannic
- Added `AdcPin` wrapper to disable digital function for ADC operations - @ithinuel
- Added `Sealed` supertrait to `PIOExt` - @ithinuel
- Added pins to `Spi` to fix inconsistencies in gpio bounds in peripheral (i2c, uart, spi) - @ithinuel
- Added `sio::Sio::read_bank0() -> u32` to provide single instruction multiple io read.

### Changed

- pwm::Slice::has_overflown() returns the raw interrupt flag, without masking/forcing. - @jannic
- Merge DynPin and Pin into Pin. The type class used in Pin now have a runtime variant allowing for
the creation of uniform array of pins (eg: `[Pin<DynPinId, PinFnSio, PullDown>]`). - @ithinuel
- Fix miss defined ValidPinMode bound allowing any Bank0 pin to be Xip and any Qspi pin to be any
other function (except for clock). - @ithinuel
- Use `let _ =` to ignore result rather than `.ok();` as this gives a false sense the result is
checked. - @ithinuel
- Use an enum for core identification. - @ithinuel
- Reduce code repetition in i2c modules. - @ithinuel

## [0.8.0] - 2023-02-16

Expand Down
6 changes: 3 additions & 3 deletions rp2040-hal/examples/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ fn main() -> ! {

// UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1)
let uart_pins = (
pins.gpio0.into_mode::<hal::gpio::FunctionUart>(),
pins.gpio1.into_mode::<hal::gpio::FunctionUart>(),
pins.gpio0.into_function::<hal::gpio::FunctionUart>(),
pins.gpio1.into_function::<hal::gpio::FunctionUart>(),
);

// Create a UART driver
Expand All @@ -110,7 +110,7 @@ fn main() -> ! {
let mut temperature_sensor = adc.enable_temp_sensor();

// Configure GPIO26 as an ADC input
let mut adc_pin_0 = pins.gpio26.into_floating_input();
let mut adc_pin_0 = hal::adc::AdcPin::new(pins.gpio26);
loop {
// Read the raw ADC counts from the temperature sensor channel.
let temp_sens_adc_counts: u16 = adc.read(&mut temperature_sensor).unwrap();
Expand Down
48 changes: 2 additions & 46 deletions rp2040-hal/examples/dht11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ use rp2040_hal as hal;
use hal::pac;

// Some traits we need
use embedded_hal::digital::v2::InputPin;
use embedded_hal::digital::v2::OutputPin;
use hal::gpio::dynpin::DynPin;
use hal::Clock;

/// The linker will place this boot block at the start of our program image. We
Expand All @@ -43,48 +41,6 @@ const XTAL_FREQ_HZ: u32 = 12_000_000u32;

use dht_sensor::{dht11, DhtReading};

/// A wrapper for DynPin, implementing both InputPin and OutputPin, to simulate
/// an open-drain pin as needed by the wire protocol the DHT11 sensor speaks.
/// https://how2electronics.com/interfacing-dht11-temperature-humidity-sensor-with-raspberry-pi-pico/
struct InOutPin {
inner: DynPin,
}

impl InOutPin {
fn new(inner: DynPin) -> Self {
Self { inner }
}
}

impl InputPin for InOutPin {
type Error = rp2040_hal::gpio::Error;
fn is_high(&self) -> Result<bool, <Self as embedded_hal::digital::v2::InputPin>::Error> {
self.inner.is_high()
}
fn is_low(&self) -> Result<bool, <Self as embedded_hal::digital::v2::InputPin>::Error> {
self.inner.is_low()
}
}

impl OutputPin for InOutPin {
type Error = rp2040_hal::gpio::Error;
fn set_low(&mut self) -> Result<(), <Self as embedded_hal::digital::v2::OutputPin>::Error> {
// To actively pull the pin low, it must also be configured as a (readable) output pin
self.inner.into_readable_output();
// In theory, we should set the pin to low first, to make sure we never actively
// pull it up. But if we try it on the input pin, we get Err(Gpio(InvalidPinType)).
self.inner.set_low()?;
Ok(())
}
fn set_high(&mut self) -> Result<(), <Self as embedded_hal::digital::v2::OutputPin>::Error> {
// To set the open-drain pin to high, just disable the output driver by changing the
// pin to input mode with pull-up. That way, the DHT11 can still pull the data line down
// to send its response.
self.inner.into_pull_up_input();
Ok(())
}
}

/// Entry point to our bare-metal application.
///
/// The `#[rp2040_hal::entry]` macro ensures the Cortex-M start-up code calls this function
Expand Down Expand Up @@ -128,8 +84,8 @@ fn main() -> ! {
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

// Use GPIO 28 as an InOutPin
let mut pin = InOutPin::new(pins.gpio28.into());
pin.set_high().ok();
let mut pin = hal::gpio::InOutPin::new(pins.gpio28);
let _ = pin.set_high();

// Perform a sensor reading
let _measurement = dht11::Reading::read(&mut delay, &mut pin);
Expand Down
8 changes: 4 additions & 4 deletions rp2040-hal/examples/gpio_irq_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ const XTAL_FREQ_HZ: u32 = 12_000_000u32;
// We'll create some type aliases using `type` to help with that

/// This pin will be our output - it will drive an LED if you run this on a Pico
type LedPin = gpio::Pin<gpio::bank0::Gpio25, gpio::PushPullOutput>;
type LedPin = gpio::Pin<gpio::bank0::Gpio25, gpio::FunctionSioOutput, gpio::PullNone>;

/// This pin will be our interrupt source.
/// It will trigger an interrupt if pulled to ground (via a switch or jumper wire)
type ButtonPin = gpio::Pin<gpio::bank0::Gpio26, gpio::PullUpInput>;
type ButtonPin = gpio::Pin<gpio::bank0::Gpio26, gpio::FunctionSioInput, gpio::PullUp>;

/// Since we're always accessing these pins together we'll store them in a tuple.
/// Giving this tuple a type alias means we won't need to use () when putting them
Expand Down Expand Up @@ -121,10 +121,10 @@ fn main() -> ! {
// Configure GPIO 25 as an output to drive our LED.
// we can use into_mode() instead of into_pull_up_input()
// since the variable we're pushing it into has that type
let led = pins.gpio25.into_mode();
let led = pins.gpio25.into();

// Set up the GPIO pin that will be our input
let in_pin = pins.gpio26.into_mode();
let in_pin = pins.gpio26.into();

// Trigger on the 'falling edge' of the input pin.
// This will happen as the button is being pressed
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ fn main() -> ! {
);

// Configure two pins as being I²C, not GPIO
let sda_pin = pins.gpio18.into_mode::<hal::gpio::FunctionI2C>();
let scl_pin = pins.gpio19.into_mode::<hal::gpio::FunctionI2C>();
let sda_pin = pins.gpio18.into_function::<hal::gpio::FunctionI2C>();
let scl_pin = pins.gpio19.into_function::<hal::gpio::FunctionI2C>();
// let not_an_scl_pin = pins.gpio20.into_mode::<hal::gpio::FunctionI2C>();

// Create the I²C drive, using the two pre-configured pins. This will fail
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/pio_blink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ fn main() -> ! {
);

// configure LED pin for Pio0.
let _led: Pin<_, FunctionPio0> = pins.gpio25.into_mode();
let led: Pin<_, FunctionPio0, _> = pins.gpio25.into_function();
// PIN id for use inside of PIO
let led_pin_id = 25;
let led_pin_id = led.id().num;

// Define some simple PIO program.
const MAX_DELAY: u8 = 31;
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/pio_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ fn main() -> ! {
);

// configure LED pin for Pio0.
let _led: Pin<_, FunctionPio0> = pins.gpio25.into_mode();
let led: Pin<_, FunctionPio0, _> = pins.gpio25.into_function();
// PIN id for use inside of PIO
let led_pin_id = 25;
let led_pin_id = led.id().num;

// HELLO WORLD in morse code:
// .... . .-.. .-.. --- / .-- --- .-. .-.. -..
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/pio_proc_blink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ fn main() -> ! {
);

// configure LED pin for Pio0.
let _led: Pin<_, FunctionPio0> = pins.gpio25.into_mode();
let led: Pin<_, FunctionPio0, _> = pins.gpio25.into_function();
// PIN id for use inside of PIO
let led_pin_id = 25;
let led_pin_id = led.id().num;

// Define some simple PIO program.
let program = pio_proc::pio_asm!(
Expand Down
2 changes: 1 addition & 1 deletion rp2040-hal/examples/pio_side_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn main() -> ! {
);

// configure LED pin for Pio0.
let led: Pin<_, FunctionPio0> = pins.gpio25.into_mode();
let led: Pin<_, FunctionPio0, _> = pins.gpio25.into_function();
// PIN id for use inside of PIO
let led_pin_id = led.id().num;

Expand Down
8 changes: 4 additions & 4 deletions rp2040-hal/examples/pio_synchronized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ fn main() -> ! {
);

// configure pins for Pio0.
let _: Pin<_, FunctionPio0> = pins.gpio0.into_mode();
let _: Pin<_, FunctionPio0> = pins.gpio1.into_mode();
let gp0: Pin<_, FunctionPio0, _> = pins.gpio0.into_function();
let gp1: Pin<_, FunctionPio0, _> = pins.gpio1.into_function();

// PIN id for use inside of PIO
let pin0 = 0;
let pin1 = 1;
let pin0 = gp0.id().num;
let pin1 = gp1.id().num;

// Define some simple PIO program.
let program = pio_proc::pio_asm!(
Expand Down
16 changes: 8 additions & 8 deletions rp2040-hal/examples/pwm_irq_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ const XTAL_FREQ_HZ: u32 = 12_000_000u32;
/// We'll create some type aliases using `type` to help with that

/// This pin will be our output - it will drive an LED if you run this on a Pico
type LedPin = gpio::Pin<gpio::bank0::Gpio25, gpio::PushPullOutput>;
type LedPin = gpio::Pin<gpio::bank0::Gpio25, gpio::FunctionSio<gpio::SioOutput>, gpio::PullNone>;

/// This pin will be our input for a 50 Hz servo PWM signal
type InputPwmPin = gpio::Pin<gpio::bank0::Gpio1, gpio::FunctionPwm>;
type InputPwmPin = gpio::Pin<gpio::bank0::Gpio1, gpio::FunctionPwm, gpio::PullNone>;

/// This will be our PWM Slice - it will interpret the PWM signal from the pin
type PwmSlice = pwm::Slice<pwm::Pwm0, pwm::InputHighRunning>;
Expand Down Expand Up @@ -134,8 +134,8 @@ fn main() -> ! {
pwm.enable();

// Connect to GPI O1 as the input to channel B on PWM0
let input_pin = pins.gpio1.into();
let channel = &mut pwm.channel_b;
let input_pin = channel.input_from(pins.gpio1);
channel.enable();

// Enable an interrupt whenever GPI O1 goes from high to low (the end of a pulse)
Expand All @@ -144,7 +144,7 @@ fn main() -> ! {
// Configure GPIO 25 as an output to drive our LED.
// we can use into_mode() instead of into_pull_up_input()
// since the variable we're pushing it into has that type
let led = pins.gpio25.into_mode();
let led = pins.gpio25.into();

// Give away our pins by moving them into the `GLOBAL_PINS` variable.
// We won't need to access them in the main thread again
Expand Down Expand Up @@ -193,14 +193,14 @@ fn IO_IRQ_BANK0() {
// if the PWM signal indicates low, turn off the LED
if pulse_width_us < LOW_US {
// set_low can't fail, but the embedded-hal traits always allow for it
// we can discard the Result by transforming it to an Option
led.set_low().ok();
// we can discard the Result
let _ = led.set_low();
}
// if the PWM signal indicates low, turn on the LED
else if pulse_width_us > HIGH_US {
// set_high can't fail, but the embedded-hal traits always allow for it
// we can discard the Result by transforming it to an Option
led.set_high().ok();
// we can discard the Result
let _ = led.set_high();
}

// If the PWM signal was in the dead-zone between LOW and HIGH, don't change the LED's
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/rom_funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ fn main() -> ! {

let uart_pins = (
// UART TX (characters sent from RP2040) on pin 1 (GPIO0)
pins.gpio0.into_mode::<hal::gpio::FunctionUart>(),
pins.gpio0.into_function::<hal::gpio::FunctionUart>(),
// UART RX (characters received by RP2040) on pin 2 (GPIO1)
pins.gpio1.into_mode::<hal::gpio::FunctionUart>(),
pins.gpio1.into_function::<hal::gpio::FunctionUart>(),
);
let mut uart = hal::uart::UartPeripheral::new(pac.UART0, uart_pins, &mut pac.RESETS)
.enable(
Expand Down
8 changes: 4 additions & 4 deletions rp2040-hal/examples/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ fn main() -> ! {
);

// These are implicitly used by the spi driver if they are in the correct mode
let _spi_sclk = pins.gpio6.into_mode::<hal::gpio::FunctionSpi>();
let _spi_mosi = pins.gpio7.into_mode::<hal::gpio::FunctionSpi>();
let _spi_miso = pins.gpio4.into_mode::<hal::gpio::FunctionSpi>();
let spi = hal::Spi::<_, _, 8>::new(pac.SPI0);
let spi_mosi = pins.gpio7.into_function::<hal::gpio::FunctionSpi>();
let spi_miso = pins.gpio4.into_function::<hal::gpio::FunctionSpi>();
let spi_sclk = pins.gpio6.into_function::<hal::gpio::FunctionSpi>();
let spi = hal::spi::Spi::<_, _, _, 8>::new(pac.SPI0, (spi_mosi, spi_miso, spi_sclk));

// Exchange the uninitialised SPI driver for an initialised one
let mut spi = spi.init(
Expand Down
8 changes: 4 additions & 4 deletions rp2040-hal/examples/spi_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ fn main() -> ! {
);

// These are implicitly used by the spi driver if they are in the correct mode
let _spi_sclk = pins.gpio6.into_mode::<hal::gpio::FunctionSpi>();
let _spi_mosi = pins.gpio7.into_mode::<hal::gpio::FunctionSpi>();
let _spi_miso = pins.gpio4.into_mode::<hal::gpio::FunctionSpi>();
let spi = hal::spi::Spi::<_, _, 8>::new(pac.SPI0);
let spi_mosi = pins.gpio7.into_function::<hal::gpio::FunctionSpi>();
let spi_miso = pins.gpio4.into_function::<hal::gpio::FunctionSpi>();
let spi_sclk = pins.gpio6.into_function::<hal::gpio::FunctionSpi>();
let spi = hal::spi::Spi::<_, _, _, 8>::new(pac.SPI0, (spi_mosi, spi_miso, spi_sclk));

// Exchange the uninitialised SPI driver for an initialised one
let spi = spi.init(
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ fn main() -> ! {

let uart_pins = (
// UART TX (characters sent from RP2040) on pin 1 (GPIO0)
pins.gpio0.into_mode(),
pins.gpio0.into_function(),
// UART RX (characters received by RP2040) on pin 2 (GPIO1)
pins.gpio1.into_mode(),
pins.gpio1.into_function(),
);
let mut uart = hal::uart::UartPeripheral::new(pac.UART0, uart_pins, &mut pac.RESETS)
.enable(
Expand Down
4 changes: 2 additions & 2 deletions rp2040-hal/examples/uart_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ fn main() -> ! {

let uart_pins = (
// UART TX (characters sent from RP2040) on pin 1 (GPIO0)
pins.gpio0.into_mode(),
pins.gpio0.into_function(),
// UART RX (characters received by RP2040) on pin 2 (GPIO1)
pins.gpio1.into_mode(),
pins.gpio1.into_function(),
);
let uart = hal::uart::UartPeripheral::new(pac.UART0, uart_pins, &mut pac.RESETS)
.enable(
Expand Down
2 changes: 1 addition & 1 deletion rp2040-hal/examples/vector_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static mut RAM_VTABLE: VectorTable = VectorTable::new();

// Give our LED and Alarm a type alias to make it easier to refer to them
type LedAndAlarm = (
hal::gpio::Pin<hal::gpio::bank0::Gpio25, hal::gpio::PushPullOutput>,
hal::gpio::Pin<hal::gpio::bank0::Gpio25, hal::gpio::FunctionSioOutput, hal::gpio::PullDown>,
hal::timer::Alarm0,
);

Expand Down
Loading

0 comments on commit bca414c

Please sign in to comment.