diff --git a/rp2040-hal/examples/gpio_c_interop.rs b/rp2040-hal/examples/gpio_c_interop.rs new file mode 100644 index 000000000..533ab771e --- /dev/null +++ b/rp2040-hal/examples/gpio_c_interop.rs @@ -0,0 +1,103 @@ +#![no_std] +#![no_main] + +// 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; + +// A shorter alias for the Peripheral Access Crate, which provides low-level +// register access +use hal::pac; + +// Some traits we need +use embedded_hal::digital::v2::ToggleableOutputPin; + +use hal::gpio::*; +use hal::gpio::DynGroup::Bank0; +use hal::gpio::DynOutput::PushPull; +use hal::Clock; +// use crate::DynRegisters; + +/// 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. +/// Note: This boot block is not necessary when using a rp-hal based BSP +/// as the BSPs already perform this step. +#[link_section = ".boot2"] +#[used] +pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H; + +/// 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; + +/// This function will construct a DynPin (based on pin_id) and use it to toggle the GPIO +/// It assumes that the pin is already in the correct mode +extern "C" fn do_work(pin_id: u8) { + let pin = DynPinId { + group: Bank0, + num: pin_id, + }; + let mode = DynPinMode::Output(PushPull); + let mut dynpin1 = unsafe { DynPin::new(pin, mode) }; + // Panic if the pin wasn't in the right mode + dynpin1.toggle().unwrap(); +} + +/// Entry point to our bare-metal application. +/// +/// The `#[rp2040_hal::entry]` macro ensures the Cortex-M start-up code calls this function +/// as soon as all global variables and the spinlock are initialised. +/// +/// The function configures the RP2040 peripherals, then toggles a GPIO pin in +/// an infinite loop. If there is an LED connected to that pin, it will blink. +#[rp2040_hal::entry] +fn main() -> ! { + // Grab our singleton objects + let mut pac = pac::Peripherals::take().unwrap(); + let core = pac::CorePeripherals::take().unwrap(); + + + // Set up the watchdog driver - needed by the clock setup code + let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); + + // Configure the clocks + 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(); + + let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); + + // The single-cycle I/O block controls our GPIO pins + let sio = hal::Sio::new(pac.SIO); + + // Set the pins to their default state + let pins = hal::gpio::Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + + // The pin number to use as an output + let pin_number:u8 = 25; + // We'll put the pin in the correct mode first, though C code might do this too + pins.gpio25.into_push_pull_output(); + + loop { + do_work(pin_number); + delay.delay_ms(500); + } +} + +// End of file diff --git a/rp2040-hal/src/gpio/dynpin.rs b/rp2040-hal/src/gpio/dynpin.rs index 974d67ace..ba3b66c35 100644 --- a/rp2040-hal/src/gpio/dynpin.rs +++ b/rp2040-hal/src/gpio/dynpin.rs @@ -305,7 +305,7 @@ impl DynPin { /// must be at most one corresponding [`DynPin`] in existence at any given /// time. Violating this requirement is `unsafe`. #[inline] - unsafe fn new(id: DynPinId, mode: DynPinMode) -> Self { + pub unsafe fn new(id: DynPinId, mode: DynPinMode) -> Self { DynPin { regs: DynRegisters::new(id), mode,