From d3cb29b113a90060fec9cf46d56a246c3affed42 Mon Sep 17 00:00:00 2001 From: Hmvp Date: Wed, 11 Aug 2021 02:53:42 +0200 Subject: [PATCH] Fix doc examples and add checking (#76) * Fix doc examples for peripheral drivers * Add no_run to doc examples so they can be built by CI * Enable building doc examples in CI check workflow --- .github/workflows/check.yml | 4 +++ rp2040-hal/src/clocks/mod.rs | 49 +++++++++++++++++++++-------------- rp2040-hal/src/gpio/dynpin.rs | 28 +++++++++++++++----- rp2040-hal/src/gpio/pin.rs | 27 +++++++++++-------- rp2040-hal/src/pwm.rs | 47 ++++++++++++++++++++------------- rp2040-hal/src/sio.rs | 11 +++++--- rp2040-hal/src/spi.rs | 17 +++++++----- rp2040-hal/src/uart.rs | 23 +++++++++++----- 8 files changed, 136 insertions(+), 70 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 0766dd7..29f3217 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -20,3 +20,7 @@ jobs: with: command: check args: --workspace --examples + - uses: actions-rs/cargo@v1 + with: + command: test + args: --doc --target x86_64-unknown-linux-gnu \ No newline at end of file diff --git a/rp2040-hal/src/clocks/mod.rs b/rp2040-hal/src/clocks/mod.rs index cf68005..cd502cd 100644 --- a/rp2040-hal/src/clocks/mod.rs +++ b/rp2040-hal/src/clocks/mod.rs @@ -3,49 +3,60 @@ //! //! //! ## Usage simple -//! ```rust -//! let mut p = rp2040_pac::Peripherals::take().unwrap(); -//! let mut watchdog = Watchdog::new(p.WATCHDOG); +//! ```no_run +//! use rp2040_hal::{clocks::init_clocks_and_plls, watchdog::Watchdog, pac}; +//! +//! let mut peripherals = pac::Peripherals::take().unwrap(); +//! let mut watchdog = Watchdog::new(peripherals.WATCHDOG); //! const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // Typically found in BSP crates -//! let mut clocks = init_clocks_and_plls(XOSC_CRYSTAL_FREQ, p.XOSC, p.CLOCKS, p.PLL_SYS, p.PLL_USB, &mut p.RESETS, &mut watchdog).ok().unwrap(); +//! let mut clocks = init_clocks_and_plls(XOSC_CRYSTAL_FREQ, peripherals.XOSC, peripherals.CLOCKS, peripherals.PLL_SYS, peripherals.PLL_USB, &mut peripherals.RESETS, &mut watchdog).ok().unwrap(); //! ``` //! //! ## Usage extended -//! ```rust -//! let mut p = rp2040_pac::Peripherals::take().unwrap(); -//! let mut watchdog = Watchdog::new(p.WATCHDOG); -//! let mut clocks = ClocksManager::new(p.CLOCKS, &mut watchdog); -//! // Enable the xosc +//! ```no_run +//! use embedded_time::rate::*; +//! use rp2040_hal::{clocks::{Clock, ClocksManager, ClockSource, InitError}, gpio::Pins, pac, pll::{common_configs::{PLL_SYS_125MHZ, PLL_USB_48MHZ}, setup_pll_blocking}, sio::Sio, watchdog::Watchdog, xosc::setup_xosc_blocking}; +//! +//! # fn func() -> Result<(), InitError> { +//! let mut peripherals = pac::Peripherals::take().unwrap(); +//! let mut watchdog = Watchdog::new(peripherals.WATCHDOG); //! const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // Typically found in BSP crates -//! let xosc = setup_xosc_blocking(p.XOSC, XOSC_CRYSTAL_FREQ.Hz()).map_err(InitError::XoscErr)?; +//! +//! // Start tick in watchdog +//! watchdog.enable_tick_generation(XOSC_CRYSTAL_FREQ as u8); +//! +//! let mut clocks = ClocksManager::new(peripherals.CLOCKS); +//! // Enable the xosc +//! let xosc = setup_xosc_blocking(peripherals.XOSC, XOSC_CRYSTAL_FREQ.Hz()).map_err(InitError::XoscErr)?; //! //! // Configure PLLs //! // REF FBDIV VCO POSTDIV //! // PLL SYS: 12 / 1 = 12MHz * 125 = 1500MHZ / 6 / 2 = 125MHz //! // PLL USB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz -//! let pll_sys = setup_pll_blocking(p.PLL_SYS, xosc.into(), PLL_SYS_125MHZ, &mut clocks, &mut p.RESETS).map_err(InitError::PllError)?; -//! let pll_usb = setup_pll_blocking(p.PLL_USB, xosc.into(), PLL_USB_48MHZ, &mut clocks, &mut p.RESETS).map_err(InitError::PllError)?; +//! let pll_sys = setup_pll_blocking(peripherals.PLL_SYS, xosc.operating_frequency().into(), PLL_SYS_125MHZ, &mut clocks, &mut peripherals.RESETS).map_err(InitError::PllError)?; +//! let pll_usb = setup_pll_blocking(peripherals.PLL_USB, xosc.operating_frequency().into(), PLL_USB_48MHZ, &mut clocks, &mut peripherals.RESETS).map_err(InitError::PllError)?; //! //! // Configure clocks //! // CLK_REF = XOSC (12MHz) / 1 = 12MHz -//! self.reference_clock.configure_clock(xosc, xosc.get_freq()).map_err(InitError::ClockError)?; +//! clocks.reference_clock.configure_clock(&xosc, xosc.get_freq()).map_err(InitError::ClockError)?; //! //! // CLK SYS = PLL SYS (125MHz) / 1 = 125MHz -//! self.system_clock.configure_clock(pll_sys, pll_sys.get_freq()).map_err(InitError::ClockError)?; +//! clocks.system_clock.configure_clock(&pll_sys, pll_sys.get_freq()).map_err(InitError::ClockError)?; //! //! // CLK USB = PLL USB (48MHz) / 1 = 48MHz -//! self.usb_clock.configure_clock(pll_usb, pll_usb.get_freq()).map_err(InitError::ClockError)?; +//! clocks.usb_clock.configure_clock(&pll_usb, pll_usb.get_freq()).map_err(InitError::ClockError)?; //! //! // CLK ADC = PLL USB (48MHZ) / 1 = 48MHz -//! self.adc_clock.configure_clock(pll_usb, pll_usb.get_freq()).map_err(InitError::ClockError)?; +//! clocks.adc_clock.configure_clock(&pll_usb, pll_usb.get_freq()).map_err(InitError::ClockError)?; //! //! // CLK RTC = PLL USB (48MHz) / 1024 = 46875Hz -//! self.rtc_clock.configure_clock(pll_usb, 46875u32.Hz()).map_err(InitError::ClockError)?; +//! clocks.rtc_clock.configure_clock(&pll_usb, 46875u32.Hz()).map_err(InitError::ClockError)?; //! //! // CLK PERI = clk_sys. Used as reference clock for Peripherals. No dividers so just select and enable //! // Normally choose clk_sys or clk_usb -//! self.peripheral_clock.configure_clock(&self.system_clock, self.system_clock.freq()).map_err(InitError::ClockError)?; -//! +//! clocks.peripheral_clock.configure_clock(&clocks.system_clock, clocks.system_clock.freq()).map_err(InitError::ClockError)?; +//! # Ok(()) +//! # } //! ``` //! //! See [Chapter 2 Section 15](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details diff --git a/rp2040-hal/src/gpio/dynpin.rs b/rp2040-hal/src/gpio/dynpin.rs index a5eb1f7..67b12f3 100644 --- a/rp2040-hal/src/gpio/dynpin.rs +++ b/rp2040-hal/src/gpio/dynpin.rs @@ -16,19 +16,30 @@ //! Instances of [`DynPin`] cannot be created directly. Rather, they must be //! created from their type-level equivalents using [`From`]/[`Into`]. //! -//! ``` +//! ```no_run //! // Move a pin out of the Pins struct and convert to a DynPin +//! # use rp2040_hal::{pac, gpio::{DynPin, bank0::Gpio12, Pins}, sio::Sio}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let sio = Sio::new(peripherals.SIO); +//! # let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS); +//! # use rp2040_hal::gpio::DYN_FLOATING_INPUT; //! let gpio12: DynPin = pins.gpio12.into(); //! ``` //! //! Conversions between pin modes use a value-level version of the type-level //! API. //! -//! ``` +//! ```no_run +//! # use rp2040_hal::{pac, gpio::{DynPin, Pins}, sio::Sio}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let sio = Sio::new(peripherals.SIO); +//! # let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS); +//! # use rp2040_hal::gpio::DYN_FLOATING_INPUT; +//! # let mut gpio12: DynPin = pins.gpio12.into(); //! // Use one of the literal function names //! gpio12.into_floating_input(); //! // Use a method and a DynPinMode variant -//! gpio12.into_mode(DYN_FLOATING_INPUT); +//! gpio12.try_into_mode(DYN_FLOATING_INPUT).unwrap(); //! ``` //! //! Because the pin state cannot be tracked at compile-time, many [`DynPin`] @@ -41,11 +52,16 @@ //! compile-time. Use [`TryFrom`](core::convert::TryFrom)/ //! [`TryInto`](core::convert::TryInto) for this conversion. //! -//! ``` +//! ```no_run +//! # use core::convert::TryInto; +//! # use rp2040_hal::{pac, gpio::{DynPin, bank0::Gpio12, Pin, Pins, FloatingInput}, sio::Sio}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let sio = Sio::new(peripherals.SIO); +//! # let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS); //! // Convert to a `DynPin` -//! let gpio12: DynPin = pins.gpio12.into(); +//! let mut gpio12: DynPin = pins.gpio12.into(); //! // Change pin mode -//! pa27.into_floating_input(); +//! gpio12.into_floating_input(); //! // Convert back to a `Pin` //! let gpio12: Pin = gpio12.try_into().unwrap(); //! ``` diff --git a/rp2040-hal/src/gpio/pin.rs b/rp2040-hal/src/gpio/pin.rs index a756bca..9b16caf 100644 --- a/rp2040-hal/src/gpio/pin.rs +++ b/rp2040-hal/src/gpio/pin.rs @@ -36,21 +36,26 @@ //! within the [`Pins`] struct can be moved out and used individually. //! //! -//! ``` -//! let mut peripherals = Peripherals::take().unwrap(); +//! ```no_run +//! # use rp2040_hal::{pac, gpio::Pins, sio::Sio}; +//! let mut peripherals = pac::Peripherals::take().unwrap(); //! let sio = Sio::new(peripherals.SIO); //! let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS); //! ``` //! //! Pins can be converted between modes using several different methods. //! -//! ``` +//! ```no_run +//! # use rp2040_hal::{pac, gpio::{bank0::Gpio12, Pin, Pins, FloatingInput}, sio::Sio}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let sio = Sio::new(peripherals.SIO); +//! # let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS); //! // Use one of the literal function names //! let gpio12 = pins.gpio12.into_floating_input(); //! // Use a generic method and one of the `PinMode` variant types -//! let gpio12 = pins.gpio12.into_mode::(); -//! // Specify the target type and use `From`/`Into` -//! let gpio12: Pin = pins.gpio12.into(); +//! let gpio12 = gpio12.into_mode::(); +//! // Specify the target type and use `.into_mode()` +//! let gpio12: Pin = gpio12.into_mode(); //! ``` //! //! # Embedded HAL traits @@ -61,16 +66,16 @@ //! //! For example, you can control the logic level of an `OutputPin` like so //! -//! ``` -//! use rp2040_hal::pac::Peripherals; -//! use rp2040_hak::gpio::v2::Pins; +//! ```no_run +//! use rp2040_hal::{pac, gpio::{bank0::Gpio12, Pin, Pins, PushPullOutput}, sio::Sio}; //! use embedded_hal::digital::v2::OutputPin; //! -//! let mut peripherals = Peripherals::take().unwrap(); +//! let mut peripherals = pac::Peripherals::take().unwrap(); //! let sio = Sio::new(peripherals.SIO); //! let pins = Pins::new(peripherals.IO_BANK0,peripherals.PADS_BANK0,sio.gpio_bank0, &mut peripherals.RESETS); //! -//! pins.gpio12.set_high(); +//! let mut pin12: Pin = pins.gpio12.into_mode(); +//! pin12.set_high(); //! ``` //! //! # Type-level features diff --git a/rp2040-hal/src/pwm.rs b/rp2040-hal/src/pwm.rs index 0b26fdd..8fdb94a 100644 --- a/rp2040-hal/src/pwm.rs +++ b/rp2040-hal/src/pwm.rs @@ -3,44 +3,55 @@ //! To access the PWM pins you must call the 'split' method on the PWM. This will return a //! `_____` struct with access to each PWM pin: //! -//! ```rust -//! use rp2040_hal::prelude::*; -//! let mut pac = rp2040_pac::Peripherals::take().unwrap(); +//! ```no_run +//! use embedded_hal::PwmPin; +//! use rp2040_hal::{pac, pwm::Pwm0}; +//! let mut peripherals = pac::Peripherals::take().unwrap(); //! let pin_num = 0; //! let mut pwm_pin = Pwm0::new(pin_num); //! ``` //! //! Once you have the PWM pins struct, you can take individual pins and configure them: //! -//! ```rust -//! pwm_pin.default_config(&mut pac.PWM, &mut pac.PAD_BANK0, &mut pac.IO_BANK0, &mut pac.RESETS); +//! ```no_run +//! # use embedded_hal::PwmPin; +//! # use rp2040_hal::{pac, pwm::Pwm0}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let pin_num = 0; +//! # let mut pwm_pin = Pwm0::new(pin_num); +//! pwm_pin.default_config(&mut peripherals.PWM, &mut peripherals.PADS_BANK0, &mut peripherals.IO_BANK0, &mut peripherals.RESETS); //! pwm_pin.set_duty(32767); //! pwm_pin.enable(); //! ``` //! //! The following configuration options are also available: //! -//! ```rust -//! pwm_pin.min_config(&pac.PWM, &pac.PAD_BANK0, &pac.IO_BANK0, &mut pac.RESETS); +//! ```no_run +//! # use embedded_hal::PwmPin; +//! # use rp2040_hal::{pac, pwm::Pwm0}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let pin_num = 0; +//! # let mut pwm_pin = Pwm0::new(pin_num); +//! pwm_pin.min_config(&mut peripherals.PWM, &mut peripherals.PADS_BANK0, &mut peripherals.IO_BANK0, &mut peripherals.RESETS); //! //! pwm_pin.get_duty(); //! pwm_pin.get_max_duty(); //! -//! pwm_pin.set_ph_correct().unwrap(); // Run in phase correct mode -//! pwm_pin.clr_ph_correct().unwrap(); // Don't run in phase correct mode +//! pwm_pin.set_ph_correct(); // Run in phase correct mode +//! pwm_pin.clr_ph_correct(); // Don't run in phase correct mode //! -//! pwm_pin.set_div_int(value: u8).unwrap(); // To set integer part of clock divider -//! pwm_pin.set_div_frac(value: u8).unwrap(); // To set fractional part of clock divider +//! pwm_pin.set_div_int(1u8); // To set integer part of clock divider +//! pwm_pin.set_div_frac(0u8); // To set fractional part of clock divider //! -//! pwm_pin.set_inv().unwrap(); // Invert the output -//! pwm_pin.clr_inv().unwrap(); // Don't invert the output +//! pwm_pin.set_inv(); // Invert the output +//! pwm_pin.clr_inv(); // Don't invert the output //! -//! pwm_pin.set_top(value: u16).unwrap(); // To set the TOP register +//! pwm_pin.set_top(u16::MAX); // To set the TOP register //! -//! pwm_pin.divmode_div().unwrap(); // Default divmode. Counts up at a rate dictated by div. -//! pwm_pin.divmode_level().unwrap(); // These 3 divmodes can be used with a PWM B pin to read PWM inputs. -//! pwm_pin.divmode_rise().unwrap(); -//! pwm_pin.divmode_fall().unwrap(); +//! pwm_pin.divmode_div(); // Default divmode. Counts up at a rate dictated by div. +//! pwm_pin.divmode_level(); // These 3 divmodes can be used with a PWM B pin to read PWM inputs. +//! pwm_pin.divmode_rise(); +//! pwm_pin.divmode_fall(); //! ``` //! //! default_config() sets ph_correct to false, the clock divider to 1, does not invert the output, sets top to 65535, and resets the counter. diff --git a/rp2040-hal/src/sio.rs b/rp2040-hal/src/sio.rs index 8685103..c70fef2 100644 --- a/rp2040-hal/src/sio.rs +++ b/rp2040-hal/src/sio.rs @@ -2,15 +2,20 @@ //! //! To be able to partition parts of the SIO block to other modules: //! -//! ```rust +//! ```no_run +//! use rp2040_hal::{gpio::Pins, pac, sio::Sio}; +//! //! let mut peripherals = pac::Peripherals::take().unwrap(); //! let sio = Sio::new(peripherals.SIO); //! ``` //! //! And then for example //! -//! ```rust -//! let pins = gpio:Pins::new(pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS); +//! ```no_run +//! # use rp2040_hal::{gpio::Pins, pac, sio::Sio}; +//! # let mut peripherals = pac::Peripherals::take().unwrap(); +//! # let sio = Sio::new(peripherals.SIO); +//! let pins = Pins::new(peripherals.IO_BANK0, peripherals.PADS_BANK0, sio.gpio_bank0, &mut peripherals.RESETS); //! ``` use super::*; diff --git a/rp2040-hal/src/spi.rs b/rp2040-hal/src/spi.rs index cc36f04..1895c4c 100644 --- a/rp2040-hal/src/spi.rs +++ b/rp2040-hal/src/spi.rs @@ -4,14 +4,19 @@ //! //! ## Usage //! -//! ```rust -//! let sio = Sio::new(p.SIO); -//! let gpio_pins = Pins::new(p.IO_BANK0, p.PADS_BANK0, sio.gpio_bank0, &mut p.RESETS); +//! ```no_run +//! use embedded_hal::spi::MODE_0; +//! use embedded_time::rate::*; +//! use rp2040_hal::{spi::Spi, gpio::{Pins, FunctionSpi}, pac, sio::Sio}; //! -//! let _ = gpio_pins.spi_sclk.into_mode::(); -//! let _ = gpio_pins.spi_mosi.into_mode::(); +//! let mut peripherals = pac::Peripherals::take().unwrap(); +//! let sio = Sio::new(peripherals.SIO); +//! let pins = Pins::new(peripherals.IO_BANK0, peripherals.PADS_BANK0, sio.gpio_bank0, &mut peripherals.RESETS); //! -//! let spi = Spi::<_, _, 8>::new(p.SPI0).init(&mut p.RESETS, 125_000_000.Hz(), 16_000_000.Hz(), &MODE_0); +//! let _ = pins.gpio2.into_mode::(); +//! let _ = pins.gpio3.into_mode::(); +//! +//! let spi = Spi::<_, _, 8>::new(peripherals.SPI0).init(&mut peripherals.RESETS, 125_000_000u32.Hz(), 16_000_000u32.Hz(), &MODE_0); //! ``` use crate::resets::SubsystemReset; diff --git a/rp2040-hal/src/uart.rs b/rp2040-hal/src/uart.rs index fbab75d..174c651 100644 --- a/rp2040-hal/src/uart.rs +++ b/rp2040-hal/src/uart.rs @@ -5,19 +5,28 @@ //! ## Usage //! //! See [examples/uart.rs](https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples/uart.rs) for a more complete example -//! ```rust +//! ```no_run +//! use rp2040_hal::{clocks::init_clocks_and_plls, gpio::{Pins, FunctionUart}, pac, sio::Sio, uart::{self, UartPeripheral}, watchdog::Watchdog}; +//! +//! const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // Typically found in BSP crates +//! +//! let mut peripherals = pac::Peripherals::take().unwrap(); +//! let sio = Sio::new(peripherals.SIO); +//! let pins = Pins::new(peripherals.IO_BANK0, peripherals.PADS_BANK0, sio.gpio_bank0, &mut peripherals.RESETS); +//! let mut watchdog = Watchdog::new(peripherals.WATCHDOG); +//! let mut clocks = init_clocks_and_plls(XOSC_CRYSTAL_FREQ, peripherals.XOSC, peripherals.CLOCKS, peripherals.PLL_SYS, peripherals.PLL_USB, &mut peripherals.RESETS, &mut watchdog).ok().unwrap(); +//! //! // Need to perform clock init before using UART or it will freeze. -//! // Skipping it here for brevity //! let uart = UartPeripheral::<_, _>::enable( -//! pac.UART0, -//! &mut pac.RESETS, -//! hal::uart::common_configs::_9600_8_N_1, +//! peripherals.UART0, +//! &mut peripherals.RESETS, +//! uart::common_configs::_9600_8_N_1, //! clocks.peripheral_clock.into(), //! ).unwrap(); //! //! // Set up UART on GP0 and GP1 (Pico pins 1 and 2) -//! let _tx_pin = pins.gpio0.into_mode::(); -//! let _rx_pin = pins.gpio1.into_mode::(); +//! let _tx_pin = pins.gpio0.into_mode::(); +//! let _rx_pin = pins.gpio1.into_mode::(); //! uart.write_full_blocking(b"Hello World!\r\n"); //! ```