From f565818b0310ba0ad7745b2e2cc092bc78c15d80 Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Wed, 31 May 2023 03:53:30 +0100 Subject: [PATCH] =?UTF-8?q?Use=20newer=20GPIO=C2=A0API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- examples/pico_spi_pio_sd_card.rs | 40 +---- src/lib.rs | 252 +++++++++++++++---------------- 3 files changed, 124 insertions(+), 170 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 489f62d..f117b8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ embedded-hal = "0.2.6" nb = "1.0.0" pio = "0.2.0" pio-proc = "0.2.0" -rp2040-hal = "0.8.0" +rp2040-hal = "0.9.0" fugit = "0.3.5" defmt = { version = "0.3.0", optional = true } diff --git a/examples/pico_spi_pio_sd_card.rs b/examples/pico_spi_pio_sd_card.rs index 7c613c2..a274994 100644 --- a/examples/pico_spi_pio_sd_card.rs +++ b/examples/pico_spi_pio_sd_card.rs @@ -39,37 +39,6 @@ //! //! $ mkfs.fat /dev/sdj1 //! -//! In the following ASCII art the SD card is also connected to 5 strong pull up -//! resistors. I've found varying values for these, from 50kOhm, 10kOhm -//! down to 5kOhm. -//! Stronger pull up resistors will eat more amperes, but also allow faster -//! data rates. -//! -//! ```text -//! +3.3V -//! Pull Ups ->|||| -//! 4x[5kOhm] -//! ||| \ -//! _______________ ||| \ -//! | DAT2/NC 9\---o|| \ _|USB|_ -//! | S DAT3/CS 1|---o+----+------SS--\ |1 R 40| -//! | D CMD/DI 2|----o----+-----MOSI-+-\ |2 P 39| -//! | VSS1 3|-- GND | | | GND-|3 38|- GND -//! | C VDD 4|-- +3.3V | /--SCK--+-+----SPI0 SCK-|4 P 37| -//! | A CLK/SCK 5|---------+-/ | \----SPI0 TX--|5 I 36|- +3.3V -//! | R VSS2 6|-- GND | /--MISO-+------SPI0 RX--|6 C | -//! | D DAT0/DO 7|---------o-/ \------SPI0 CSn-|7 O | -//! | DAT1/IRQ 8|-[5k]- +3.3V | | -//! """""""""""""""" | | -//! | | -//! ......... -//! |20 21| -//! """"""" -//! Symbols: -//! - (+) crossing lines, not connected -//! - (o) connected lines -//! ``` -//! //! The example can either be used with a probe to receive debug output //! and also the LED is used as status output. There are different blinking //! patterns. @@ -104,7 +73,7 @@ use defmt_rtt as _; use panic_halt as _; // Pull in any important traits -use rp_pico::hal::prelude::*; +use rp_pico::hal::{gpio::PullUp, prelude::*}; // Embed the `Hz` function/trait: use fugit::RateExtU32; @@ -191,8 +160,6 @@ fn blink_signals_loop( #[entry] fn main() -> ! { - info!("Program start"); - // Grab our singleton objects let mut pac = pac::Peripherals::take().unwrap(); let core = pac::CorePeripherals::take().unwrap(); @@ -232,11 +199,14 @@ fn main() -> ! { // Setup a delay for the LED blink signals: let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); + // Enable internal pull up on MISO + let gpio4 = pins.gpio4.into_pull_type::(); + // These are implicitly used by the spi driver if they are in the correct mode let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); let spi: spi_pio::Spi<'_, _, _, _, _, _, 8> = spi_pio::Spi::new( (&mut pio, sm0), - (pins.gpio4, pins.gpio3, pins.gpio2), + (gpio4, pins.gpio3, pins.gpio2), embedded_hal::spi::MODE_0, 16u32.MHz(), clocks.peripheral_clock.freq(), diff --git a/src/lib.rs b/src/lib.rs index df850b5..6d77cc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,6 @@ #![no_std] +use core::marker::PhantomData; + use embedded_hal::{ blocking::spi, spi::{Phase, Polarity}, @@ -6,20 +8,21 @@ use embedded_hal::{ use fugit::HertzU32; use pio::{Instruction, InstructionOperands}; use rp2040_hal::{ - gpio::{Disabled, DisabledConfig, Function, FunctionConfig, Pin, PinId, ValidPinMode}, + gpio::{ + AnyPin, FunctionNull, FunctionSioInput, FunctionSioOutput, Pin, SpecificPin, ValidFunction, + }, pio::{ PIOExt, PinDir, PinState, Rx, ShiftDirection, StateMachine, StateMachineIndex, Tx, UninitStateMachine, PIO, }, + typelevel::Is, }; #[cfg(not(feature = "defmt"))] mod defmt { #[macro_export] macro_rules! info { - ($($_:tt)*) => {{ - compile_error!("woops"); - }}; + ($($_:tt)*) => {{}}; } #[macro_export] macro_rules! error { @@ -32,68 +35,48 @@ mod defmt { pub struct Spi<'pio, P, SMI, MISO, MOSI, SCLK, const DS: u8> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, { _pio: &'pio mut PIO

, _sm: StateMachine<(P, SMI), rp2040_hal::pio::Running>, tx: Tx<(P, SMI)>, rx: Rx<(P, SMI)>, - #[allow(clippy::type_complexity)] _pins: ( - Pin>, - Pin>, - Pin>, + Pin, + Pin, + Pin, ), + _old_pins_states: PhantomData<(MISO, MOSI, SCLK)>, } -type NewErr = ( - UninitStateMachine<(P, SMI)>, - Pin>, - Pin>, - Pin>, -); +type NewErr = (UninitStateMachine<(P, SMI)>, (MISO, MOSI, SCLK)); impl<'pio, P, SMI, MISO, MOSI, SCLK, const DS: u8> Spi<'pio, P, SMI, MISO, MOSI, SCLK, DS> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, { #[allow(clippy::type_complexity)] - pub fn new( + pub fn new( (pio, sm): (&'pio mut PIO

, UninitStateMachine<(P, SMI)>), - (miso, mosi, mut sclk): ( - Pin>, - Pin>, - Pin>, - ), + (miso, mosi, sclk): (MISO, MOSI, SCLK), mode: embedded_hal::spi::Mode, bus_freq: HertzU32, clock_freq: HertzU32, - ) -> Result< - Self, - NewErr< - P, - SMI, - MISO, - MOSI, - SCLK, - MisoDisabledConfig, - MosiDisabledConfig, - SclkDisabledConfig, - >, - > + ) -> Result> where - MisoDisabledConfig: DisabledConfig, - MosiDisabledConfig: DisabledConfig, - SclkDisabledConfig: DisabledConfig, + MISO: AnyPin + Is>, + MOSI: AnyPin + Is>, + SCLK: AnyPin + Is>, + MISO::Id: ValidFunction + ValidFunction, + MOSI::Id: ValidFunction + ValidFunction, + SCLK::Id: ValidFunction + ValidFunction, { let program = pio_proc::pio_asm!( ".side_set 1 opt" @@ -121,13 +104,13 @@ where let installed = match pio.install(&program) { Ok(inst) => inst, - Err(_) => return Err((sm, miso, mosi, sclk)), + Err(_) => return Err((sm, (miso, mosi, sclk))), }; entry_point += i32::from(installed.offset()); if entry_point > 32 { // TODO: this should check against a value from the PIO, not a hardcoded value. defmt::error!("Entry point set beyond pio's memory."); - return Err((sm, miso, mosi, sclk)); + return Err((sm, ( miso, mosi, sclk ))); } let entry_point = entry_point as u8; @@ -141,7 +124,7 @@ where if !(1..=65536).contains(&int) || (int == 65536 && frac != 0) { defmt::error!("The ratio between the bus frequency and the system clock must be within [1.0, 65536.0]."); pio.uninstall(installed); - return Err((sm, miso, mosi, sclk)); + return Err((sm, (miso, mosi, sclk))); } // 65536.0 is represented as 0 in the pio's clock divider if int == 65536 { @@ -151,11 +134,17 @@ where let int: u16 = int as u16; let frac: u8 = frac as u8; + let mosi = mosi.into(); + let miso = miso.into(); + let mut sclk = sclk.into(); + let mosi_pin_id = mosi.id(); + let miso_pin_id = miso.id(); + let sclk_pin_id = sclk.id(); let (mut sm, rx, tx) = rp2040_hal::pio::PIOBuilder::from_program(installed) .buffers(rp2040_hal::pio::Buffers::RxTx) - .out_pins(MOSI::DYN.num, 1) - .in_pin_base(MISO::DYN.num) - .side_set_pin_base(SCLK::DYN.num) + .out_pins(mosi_pin_id.num, 1) + .in_pin_base(miso_pin_id.num) + .side_set_pin_base(sclk_pin_id.num) .autopull(true) .autopush(true) // msb/lsb first can be selected here @@ -172,21 +161,21 @@ where sclk.set_output_override(rp2040_hal::gpio::OutputOverride::DontInvert); } let sclk = sclk.into_push_pull_output_in_state(rp2040_hal::gpio::PinState::Low); - let miso = miso.into_floating_input(); + let miso = miso.into_function::(); let mosi = mosi.into_push_pull_output_in_state(rp2040_hal::gpio::PinState::Low); sm.set_pins([ - (MOSI::DYN.num, PinState::Low), - (SCLK::DYN.num, PinState::Low), + (mosi_pin_id.num, PinState::Low), + (sclk_pin_id.num, PinState::Low), ]); sm.set_pindirs([ - (MISO::DYN.num, PinDir::Input), - (MOSI::DYN.num, PinDir::Output), - (SCLK::DYN.num, PinDir::Output), + (miso_pin_id.num, PinDir::Input), + (mosi_pin_id.num, PinDir::Output), + (sclk_pin_id.num, PinDir::Output), ]); - let miso = miso.into_mode(); - let mosi = mosi.into_mode(); - let sclk = sclk.into_mode(); + let miso = miso.into_function(); + let mosi = mosi.into_function(); + let sclk = sclk.into_function(); sm.exec_instruction(Instruction { operands: InstructionOperands::JMP { @@ -204,77 +193,74 @@ where tx, rx, _pins: (miso, mosi, sclk), + _old_pins_states: PhantomData, }) } } macro_rules! impl_write { - ($type:ty, $fn:ident, [$($nr:expr),+]) => { - $( - impl<'pio, P, SMI, MISO, MOSI, SCLK> embedded_hal::spi::FullDuplex<$type> - for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> - where - P: PIOExt + FunctionConfig, - SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, - { - type Error = core::convert::Infallible; + ($type:ty, $fn:ident, [$($nr:expr),+]) => { + $( + impl<'pio, P, SMI, MISO, MOSI, SCLK> embedded_hal::spi::FullDuplex<$type> + for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> + where + P: PIOExt, + SMI: StateMachineIndex, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, + { + type Error = core::convert::Infallible; - fn read(&mut self) -> nb::Result<$type, Self::Error> { - if let Some(r) = self.rx.read() { - Ok(r as $type) - } else { - Err(nb::Error::WouldBlock) - } - } + fn read(&mut self) -> nb::Result<$type, Self::Error> { + if let Some(r) = self.rx.read() { + Ok(r as $type) + } else { + Err(nb::Error::WouldBlock) + } + } - fn send(&mut self, word: $type) -> nb::Result<(), Self::Error> { - if self.tx.$fn(word) { - Ok(()) - } else { - Err(nb::Error::WouldBlock) + fn send(&mut self, word: $type) -> nb::Result<(), Self::Error> { + if self.tx.$fn(word) { + Ok(()) + } else { + Err(nb::Error::WouldBlock) + } + } } - } - } - impl<'pio, P, SMI, MISO, MOSI, SCLK> spi::write::Default<$type> - for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> - where - P: PIOExt + FunctionConfig, - SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, - { - } - impl<'pio, P, SMI, MISO, MOSI, SCLK> spi::transfer::Default<$type> - for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> - where - P: PIOExt + FunctionConfig, - SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, - { - } - impl<'pio, P, SMI, MISO, MOSI, SCLK> spi::write_iter::Default<$type> - for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> - where - P: PIOExt + FunctionConfig, - SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, - { - } - )+ - }; -} + impl<'pio, P, SMI, MISO, MOSI, SCLK> spi::write::Default<$type> + for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> + where + P: PIOExt, + SMI: StateMachineIndex, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, + { + } + impl<'pio, P, SMI, MISO, MOSI, SCLK> spi::transfer::Default<$type> + for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> + where + P: PIOExt, + SMI: StateMachineIndex, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, + { + } + impl<'pio, P, SMI, MISO, MOSI, SCLK> spi::write_iter::Default<$type> + for Spi<'pio, P, SMI, MISO, MOSI, SCLK, $nr> + where + P: PIOExt, + SMI: StateMachineIndex, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, + { + } + )+ + }; + } impl_write!(u8, write_u8_replicated, [1, 2, 3, 4, 5, 6, 7, 8]); impl_write!(u16, write_u16_replicated, [9, 10, 11, 12, 13, 14, 15, 16]); impl_write!( @@ -286,12 +272,11 @@ impl_write!( impl<'pio, P, SMI, MISO, MOSI, SCLK, const DS: u8> rp2040_hal::dma::ReadTarget for Spi<'pio, P, SMI, MISO, MOSI, SCLK, DS> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, { type ReceivedWord = u32; @@ -310,12 +295,11 @@ where impl<'pio, P, SMI, MISO, MOSI, SCLK, const DS: u8> rp2040_hal::dma::WriteTarget for Spi<'pio, P, SMI, MISO, MOSI, SCLK, DS> where - P: PIOExt + FunctionConfig, + P: PIOExt, SMI: StateMachineIndex, - MISO: PinId, - MOSI: PinId, - SCLK: PinId, - Function

: ValidPinMode + ValidPinMode + ValidPinMode, + MISO: AnyPin, + MOSI: AnyPin, + SCLK: AnyPin, { type TransmittedWord = u32;