rp2040-project-template

repository·main·Indexed 20 days ago

https://github.com/rp-rs/rp2040-project-template

A project template for developing firmware on the RP2040 microcontroller using the rp2040-hal. It provides a pre-configured development environment with modern Rust tooling for debugging and logging, supporting the thumbv6m-none-eabi target, flip-link for stack protection, and probe-rs-tools for flashing.

Tokens
2.3K
Snippets
10
Records
12
Agent score
70%

What's inside rp2040-project-template

  1. Manually initialize rp2040_boot2

    main

    The second-stage bootloader must be placed in the .boot2 section. While most Board Support Packages (BSPs) like rp-pico handle this, you can manually initialize it in your main.rs if you are not using a BSP:

    use rp2040_boot2;
    
    #[link_section = ".boot2"]
    #[used]
    pub static BOOT_LOADER: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
  2. Quickstart for RP2040 development

    main

    This guide assumes you are using a Raspberry Pi Pico and a Raspberry Pi Debug Probe with probe-rs.

    1. Connect your Pico and Debug Probe to your host.
    2. Install cargo-generate: cargo install cargo-generate.
    3. Create project: cargo generate rp-rs/rp2040-project-template.
    4. Install target: rustup target install thumbv6m-none-eabi.
    5. Install stack protection: cargo install flip-link.
    6. Install flashing tools: cargo install --locked probe-rs-tools.
    7. Flash and run: cargo run.
    # Step-by-step setup
    cargo install cargo-generate
    cargo generate rp-rs/rp2040-project-template
    rustup target install thumbv6m-none-eabi
    cargo install flip-link
    cargo install --locked probe-rs-tools
    cargo run
  3. Create a new project from the template

    main

    You can initialize a new project using cargo-generate or by manual download.

    Run the following command and follow the interactive wizard:

    cargo generate --git https://github.com/rp-rs/rp2040-project-template

    Manual Download/GitHub Template

    If downloading as a ZIP or using GitHub's template feature, you must perform these cleanup steps:

    • Remove debug_probes.md and the cargo-generate directory.
    • Edit/remove README.md.
    • Update .vscode/launch.json (if using VSCode) or remove it.
    • Edit Cargo.toml to set your project name.
    • Edit .cargo/config.toml to select your preferred runner.
  4. Run and manage DEFMT logging levels

    main

    Use cargo run for debug builds and cargo run --release for release builds.

    By default, the DEFMT_LOG level is set to debug. You can override this to control logging verbosity (e.g., trace, info, off).

    Overriding DEFMT_LOG

    • Via .cargo/config.toml (Permanent):
      [env]
      DEFMT_LOG = "off"
    • Inline (Linux/MacOS): DEFMT_LOG=trace cargo run
    • Environment Variable (Linux/MacOS): export DEFMT_LOG=trace
    • Environment Variable (Windows CMD): set DEFMT_LOG=trace
    • Environment Variable (Windows PowerShell): $Env:DEFMT_LOG = trace
    # Example: running with trace logging on Linux/MacOS
    DEFMT_LOG=trace cargo run
  5. Use a Raspberry Pi Pico as a CMSIS-DAP debug probe

    main

    You can repurpose a second Raspberry Pi Pico to act as a CMSIS-DAP debugger for your target RP2040 board.

    1. Prepare the Probe Firmware

    Download the appropriate firmware from the official raspberrypi/debugprobe releases:

    • Raspberry Pi Pico 1: Use debugprobe_on_pico.uf2
    • Raspberry Pi Pico 2: Use debugprobe_on_pico2.uf2

    2. Flash the Firmware

    1. Hold the BOOTSEL button on the Pico while connecting it to your computer via USB to enter USB Mass Storage Mode.
    2. Open the RPI-RP2 drive.
    3. Copy the downloaded .uf2 file into the RPI-RP2 drive.

    3. Hardware Wiring

    Connect the pins from your Probe Pico to your Target Pico as follows:

    • Probe GP2 $\rightarrow$ Target SWCLK
    • Probe GP3 $\rightarrow$ Target SWDIO
    • Probe GND $\rightarrow$ Target GND

    Ensure both boards are powered before proceeding to the main quickstart guide.

  6. Install development dependencies

    main

    To use the template's default development environment, install the following tools:

    • Target: thumbv6m-none-eabi (for Cortex-M0+).
    • Stack Overflow Protection: flip-link.
    • Flashing/Debugging: probe-rs-tools (includes probe-rs run).

    If you encounter the error binary 'cargo-embed' already exists during probe-rs-tools installation, uninstall your existing version first with cargo uninstall cargo-embed.

    rustup target install thumbv6m-none-eabi
    cargo install flip-link
    cargo install --locked probe-rs-tools
  7. Configure alternative runners

    main

    If you are not using a debug probe, you can configure alternative runners in .cargo/config.toml.

    Option 1: cargo embed

    Provides more configuration via Embed.toml.

    1. Install: cargo install --locked probe-rs-tools.
    2. Configure Embed.toml.
    3. Run: cargo embed --release.

    Option 2: probe-rs-debugger (VSCode)

    1. Install VSCode and probe-rs-tools.
    2. Install the debugger for probe-rs extension in VSCode.
    3. Launch via Run > Start Debugging (F5).

    Option 3: picotool (USB Bootloader)

    Flashing over USB without a probe.

    1. Install the picotool binary.
    2. Update .cargo/config with the following runner:
      [target.`cfg(all(target-arch = "arm", target_os = "none"))`]
      runner = "picotool load --update --verify --execute -t elf"
    3. Put the RP2040 into USB Bootloader mode (hold BOOTSEL while rebooting).
    4. Run: cargo run --release.
    # Example: picotool runner configuration in .cargo/config
    [target.`cfg(all(target-arch = "arm", target_os = "none"))`]
    runner = "picotool load --update --verify --execute -t elf"
  8. Enable rp2040-hal feature flags

    main

    To enable specific features in rp2040-hal (such as rom-v2-intrinsics for f64 math), uncomment the dependency in your Cargo.toml and add the desired flags:

    rp2040-hal = { version="0.10", features=["rt", "critical-section-impl", "rom-v2-intrinsics"] }
  9. Initialize the RP2040 firmware entrypoint

    main

    The firmware entrypoint uses the #[entry] macro from the Board Support Package (BSP) to define the main execution loop. To initialize the hardware, you must take ownership of the pac::Peripherals and pac::CorePeripherals, initialize the Watchdog and Sio, and configure the system clocks using init_clocks_and_plls based on your board's external crystal frequency.

    #[entry]
    fn main() -> ! {
        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);
    
        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();
    
        // ...
    }
  10. Switch between different RP2040 Board Support Packages (BSPs)

    main

    To target a different board, change the BSP alias in your main.rs file. Ensure the corresponding BSP crate is included in your Cargo.toml.

    Example for switching from Raspberry Pi Pico to SparkFun Pro Micro RP2040:

    // Use Raspberry Pi Pico
    use rp_pico as bsp;
    
    // OR use SparkFun Pro Micro RP2040
    // use sparkfun_pro_micro_rp2040 as bsp;
  11. Compatible CMSIS-DAP debug probes reference

    main

    The following hardware devices are compatible with this project for CMSIS-DAP debugging. Use these as alternatives if you do not wish to use a Raspberry Pi Pico as a probe.

    - Raspberry Pi Pico (via debugprobe firmware)
    - WeAct MiniF4
    - HS-Probe
    - ST-LINK v2 clone (requires dap42 firmware)
    - LPC-Link2
    - MCU-Link
    - DAPLink
  12. Configure GPIO pins using the BSP

    main

    Access hardware pins by initializing the bsp::Pins struct. This requires the IO_BANK0, PADS_BANK0, and sio.gpio_bank0 peripherals, along with a mutable reference to pac.RESETS. Once initialized, you can access specific pins (like pins.led) and convert them into specific modes, such as a push-pull output using .into_push_pull_output().

    let pins = bsp::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );
    
    let mut led_pin = pins.led.into_push_pull_output();