Skip to content

Instantly share code, notes, and snippets.

@9names
Created January 15, 2026 08:20
Show Gist options
  • Select an option

  • Save 9names/5c99db1037cc807103cbe1886863f275 to your computer and use it in GitHub Desktop.

Select an option

Save 9names/5c99db1037cc807103cbe1886863f275 to your computer and use it in GitHub Desktop.
2MHz PWM on rp2040
#![no_std]
#![no_main]
use defmt::*;
use defmt_rtt as _;
use embedded_hal::pwm::SetDutyCycle;
use panic_probe as _;
use rp2040_hal::{
clocks::{init_clocks_and_plls, Clock},
entry, pac,
sio::Sio,
watchdog::Watchdog,
};
use embedded_hal::delay::DelayNs;
use rp2040_hal as hal;
use pwm_freq::PwmFreq;
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H;
#[entry]
fn main() -> ! {
info!("Program start");
let mut pac = pac::Peripherals::take().unwrap();
let _core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);
// External high-speed crystal on the pico board is 12Mhz
let external_xtal_freq_hz = 12_000_000u32;
let clocks = init_clocks_and_plls(
external_xtal_freq_hz,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
let sysclkfreq = clocks.system_clock.freq().to_Hz();
let mut delay = rp2040_hal::timer::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
// Configure PWM4
let pwm: &mut rp2040_hal::pwm::Slice<rp2040_hal::pwm::Pwm4, rp2040_hal::pwm::FreeRunning> =
&mut pwm_slices.pwm4;
pwm.set_top(0);
pwm.set_ph_correct();
pwm.enable();
// Output channel B on PWM4 to GPIO 25
let channel = &mut pwm.channel_b;
channel.output_to(pins.gpio25);
channel.output_to(pins.gpio9);
// slight delay here before we keep going
delay.delay_ns(100_000_000);
// target 2MHz
let target_freq = 2_000_000;
let pwm_freq = PwmFreq::new(sysclkfreq, target_freq).unwrap();
let pwm_config = pwm_freq.get_config();
let calculated_freq = pwm_freq.get_actual_freq();
info!(
"user asked for {} but the best we can do is {}hz",
target_freq, calculated_freq
);
pwm.channel_b.set_duty_cycle(pwm_config.top / 2).unwrap();
pwm.set_top(pwm_config.top);
pwm.set_div_int(pwm_config.div.0);
pwm.set_div_frac(pwm_config.div.1);
info!("all important logic is done, now we just output a square wave all day");
loop {
delay.delay_ns(500_000_000);
}
}
// End of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment