diff --git a/rp2040-hal/examples/pwm_blink.rs b/rp2040-hal/examples/pwm_blink.rs index afd194a..149ded0 100644 --- a/rp2040-hal/examples/pwm_blink.rs +++ b/rp2040-hal/examples/pwm_blink.rs @@ -1,43 +1,124 @@ +//! # PWM Blink Example +//! +//! If you have an LED connected to pin 25, it will fade the LED using the PWM +//! peripheral. +//! +//! It may need to be adapted to your particular board layout and/or pin assignment. +//! +//! See the `Cargo.toml` file for Copyright and licence details. + #![no_std] #![no_main] +// The macro for our start-up function use cortex_m_rt::entry; -use embedded_hal::PwmPin; -use panic_halt as _; -use rp2040_hal::{gpio::Pins, pwm::*, sio::Sio}; +// Ensure we halt the program on panic (if we don't mention this crate it won't +// be linked) +use panic_halt as _; + +// Alias for our HAL crate +use rp2040_hal as hal; + +// Traits we need +use embedded_hal::PwmPin; +use embedded_time::rate::*; +use rp2040_hal::clocks::Clock; + +// A shorter alias for the Peripheral Access Crate, which provides low-level +// register access +use hal::pac; + +//// 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; +/// The minimum PWM value (i.e. LED brightness) we want +const LOW: u16 = 0; + +/// The maximum PWM value (i.e. LED brightness) we want +const HIGH: u16 = 25000; + +/// 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 initialised. +/// +/// The function configures the RP2040 peripherals, then fades the LED in an +/// infinite loop. #[entry] fn main() -> ! { - let mut pac = rp2040_pac::Peripherals::take().unwrap(); + // Grab our singleton objects + let mut pac = pac::Peripherals::take().unwrap(); + let core = pac::CorePeripherals::take().unwrap(); - let sio = Sio::new(pac.SIO); - let pins = Pins::new( + // Set up the watchdog driver - needed by the clock setup code + let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG); + + // Configure the clocks + // + // The default is to generate a 125 MHz system clock + 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(); + + // The single-cycle I/O block controls our GPIO pins + let sio = hal::sio::Sio::new(pac.SIO); + + // Set the pins up according to their function on this particular board + let pins = hal::gpio::Pins::new( pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS, ); + // The delay object lets us wait for specified amounts of time (in + // milliseconds) + let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer()); + // Init PWMs - let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS); + let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS); // Configure PWM4 - let mut pwm = pwm_slices.pwm4; + let pwm = &mut pwm_slices.pwm4; pwm.set_ph_correct(); pwm.enable(); - // Use B channel (which outputs to GPIO 25) - let mut channel = pwm.channel_b; + // Output channel B on PWM4 to GPIO 25 + let channel = &mut pwm.channel_b; channel.output_to(pins.gpio25); + + // Infinite loop, fading LED up and down loop { - channel.set_duty(15000); - // TODO: Replace with proper delays once we have clocks working - cortex_m::asm::delay(5_000_000); - channel.set_duty(30000); - cortex_m::asm::delay(5_000_000); + // Ramp brightness up + for i in (LOW..=HIGH).skip(100) { + delay.delay_us(8); + channel.set_duty(i); + } + + // Ramp brightness down + for i in (LOW..=HIGH).rev().skip(100) { + delay.delay_us(8); + channel.set_duty(i); + } + + delay.delay_ms(500); } } + +// End of file