Rust嵌入式开发库rp2040-hal的使用,为Raspberry Pi RP2040芯片提供硬件抽象层支持

Rust嵌入式开发库rp2040-hal的使用,为Raspberry Pi RP2040芯片提供硬件抽象层支持

Logo

简介

rp2040-hal是一个为Raspberry Silicon RP2040微控制器提供高级Rust驱动程序的库包,同时包含一系列非板级特定的示例程序供学习。名称中的"HAL"代表"硬件抽象层",因为许多包含的驱动程序实现了Rust嵌入式工作组在embedded-hal crate中定义的通用硬件抽象接口。

我们还提供了一系列板级支持包(BSP) crates,这些crate使用这个HAL crate并根据特定PCB设计预先配置引脚。如果您使用受支持的开发板之一,应该优先使用这些crate中的某个,然后返回这里查看有关RP2040上特定外设的文档以及如何使用它们。

快速开始

要在项目中包含此crate,修改您的Cargo.toml文件以包含:

rp2040-hal = "0.11.0"

要获取源代码副本(例如,如果您想提出错误修复或新功能,或者只是想研究代码),运行:

$ git clone https://github.com/rp-rs/rp-hal.git

完整示例代码

以下是一个使用rp2040-hal的完整示例,展示了如何初始化RP2040并控制LED:

//! 简单的RP2040 HAL示例 - 闪烁LED

#![no_std]
#![no_main]

// 导入必要的库
use panic_halt as _;
use rp2040_hal as hal;

use embedded_hal::digital::v2::OutputPin;
use hal::{
    clocks::{init_clocks_and_plls, Clock},
    gpio::Pins,
    pac,
    sio::Sio,
    watchdog::Watchdog,
};
use rp_pico::entry;

#[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);

    // 外部高频率晶振配置
    const EXTERNAL_XTAL_FREQ_HZ: u32 = 12_000_000;
    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();

    // 初始化GPIO
    let pins = Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    // 配置LED引脚为输出
    let mut led_pin = pins.gpio25.into_push_pull_output();

    // 简单的延迟函数
    let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());

    // 主循环 - 闪烁LED
    loop {
        led_pin.set_high().unwrap();
        delay.delay_ms(500);
        led_pin.set_low().unwrap();
        delay.delay_ms(500);
    }
}

特性实现

这个crate旨在实现embedded-hal的所有特性,包括版本0.2和1.0。它们可以同时使用,因此您可以逐步升级驱动程序。

贡献

贡献使开源社区成为学习、激励和创造的绝佳场所。任何贡献都非常感激。

  1. 派生项目
  2. 创建您的特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交您的更改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 打开拉取请求

许可证

此存储库的内容采用MIT OR Apache 2.0许可证双重许可。这意味着您可以在重新使用此代码时选择MIT许可证或Apache 2.0许可证。除非您明确声明,否则根据Apache-2.0许可证定义的任何有意提交包含在作品中的贡献,均应如上所述双重许可,无需任何附加条款或条件。

扩展示例代码

以下是一个更完整的RP2040 HAL使用示例,展示了PWM控制和串口通信:

//! RP2040 HAL扩展示例 - PWM和串口通信

#![no_std]
#![no_main]

use cortex_m::asm::wfi;
use embedded_hal::PwmPin;
use panic_halt as _;
use rp2040_hal::{
    clocks::{init_clocks_and_plls, Clock},
    gpio::Pins,
    pac,
    pwm::{FreeRunning, Pwm0, Pwm1, PwmConfig, Slices},
    sio::Sio,
    uart::{self, UartPeripheral},
    watchdog::Watchdog,
};
use rp_pico::entry;

#[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);

    // 时钟配置
    const EXTERNAL_XTAL_FREQ_HZ: u32 = 12_000_000;
    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();

    // 初始化GPIO
    let pins = Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    // 配置PWM
    let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
    
    // 配置PWM0
    let mut pwm0 = pwm_slices.pwm0;
    pwm0.set_ph_correct();
    pwm0.enable();
    let pwm0_channel = pwm0.channel_a;
    pwm0_channel.output_to(pins.gpio0);
    
    // 配置PWM1
    let mut pwm1 = pwm_slices.pwm1;
    pwm1.set_ph_correct();
    pwm1.enable();
    let pwm1_channel = pwm1.channel_a;
    pwm1_channel.output_to(pins.gpio1);

    // 配置UART
    let uart = UartPeripheral::new(pac.UART0, &mut pac.RESETS)
        .enable(
            uart::common_configs::_9600_8_N_1,
            clocks.peripheral_clock.freq(),
        )
        .unwrap();
    let (mut tx, _rx) = uart.split();

    // 主循环
    let mut duty_cycle = 0u16;
    loop {
        // PWM控制
        pwm0_channel.set_duty(duty_cycle);
        pwm1_channel.set_duty(u16::MAX - duty_cycle);
        
        // 串口发送
        let _ = tx.write(b"Current duty cycle: ");
        let _ = tx.write(duty_cycle.to_string().as_bytes());
        let _ = tx.write(b"\r\n");
        
        // 更新占空比
        duty_cycle = duty_cycle.wrapping_add(100);
        if duty_cycle > 10000 {
            duty_cycle = 0;
        }
        
        // 延迟
        cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz())
            .delay_ms(50);
    }
}

1 回复

Rust嵌入式开发库rp2040-hal使用指南

rp2040-hal是为Raspberry Pi RP2040微控制器芯片提供的Rust硬件抽象层(HAL)库,它允许开发者用Rust语言为RP2040编写嵌入式应用程序。

特性概述

  • 提供对RP2040所有外设的访问
  • 支持GPIO、UART、I2C、SPI、PWM、ADC等接口
  • 时钟配置和控制系统
  • 中断处理支持
  • 与RTIC(Real-Time Interrupt-driven Concurrency)框架兼容

基本使用方法

添加依赖

在Cargo.toml中添加:

[dependencies]
rp2040-hal = "0.9"
rp-pico = "0.9"  # 如果使用Raspberry Pi Pico开发板

简单示例:闪烁LED

#![no_std]
#![no_main]

use panic_halt as _;
use rp2040_hal as hal;
use hal::pac;

#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;

#[hal::entry]
fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap();
    let core = pac::CorePeripherals::take().unwrap();

    let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
    let clocks = hal::clocks::init_clocks_and_plls(
        rp_pico::XOSC_CRYSTAL_FREQ,
        pac.XOSC,
        pac.CLOCKS,
        pac.PLL_SYS,
        pac.PLL_USB,
        &mut pac.RESETS,
        &mut watchdog,
    )
    .ok()
    .unwrap();

    let sio = hal::Sio::new(pac.SIO);
    let pins = rp_pico::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    let mut led_p极简 = pins.led.into_push_pull_output();
    
    let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
    
    loop {
        led_pin.set_high().unwrap();
        delay.delay_ms(500);
        led_pin.set_low().unwrap();
        delay.delay_ms(500);
    }
}

外设使用示例

GPIO输入输出

use hal::gpio::{Pin, PushPullOutput, Input, PullUp};

// 配置GPIO25为输出
let mut output_pin: Pin<_, PushPullOutput> = pins.gpio25.into_push_pull_output();

// 配置GPIO15为输入,上拉
let input_pin: Pin<_, Input<PullUp>> = pins.gpio15.into_pull_up_input();

output_pin.set_high().unwrap();
if input_pin.is_high().unwrap() {
    // 处理高电平输入
}

UART通信

use hal::uart::{UartConfig, DataBits, StopBits, Parity, BaudRate};

let uart_pins = (
    pins.gpio0.into_mode::<hal::gp极简::FunctionUart>(),
    pins.gpio1.into_mode::<hal::gpio::FunctionUart>(),
);

let mut uart = hal::uart::UartPeripheral::new(
    pac.UART0,
    uart_pins,
    &mut pac.RESETS,
)
.enable(
    UartConfig::new(
        BaudRate::BAUD115200,
        DataBits::Eight,
        None,
        StopBits::One,
    ),
    clocks.peripheral_clock.freq(),
)
.unwrap();

uart.write_full_blocking(b"Hello, UART!\r\n").unwrap();

let mut buf = [0u8; 32];
uart.read_full_blocking(&mut buf).unwrap();

I2C通信

use hal::i2c::I2C;

let sda_pin = pins.gpio4.into_mode::<hal::gpio::FunctionI2C>();
let scl_pin = pins.gpio5.into_mode::<hal::gpio::FunctionI2C>();

let mut i2c = hal::I2C::i2c0(
    pac.I2C0,
    sda_pin,
    scl_pin,
    &mut pac.RESETS,
    clocks.peripheral_clock.freq(),
    100.kHz(),
);

let mut data = [0u8; 2];
i2c.write_read(0x68, &[0x00], &mut data).unwrap();

中断处理

use pac::interrupt;
use cortex_m::interrupt::free as disable_interrupts;

// 启用UART中断
unsafe {
    pac::NVIC::unmask(pac::Interrupt::UART0_IRQ);
    pac::UART0::ptr().as_ref().unwrap().imsc.modify(|_, w| {
        w.rxim().set_bit()  // 启用接收中断
    });
}

#[interrupt]
fn UART0_IRQ() {
    disable_interrupts(|cs| {
        let uart0 = unsafe { &*pac::UART0::ptr() };
        
        if uart0.mis.read().rxim().bit_is_set() {
            let data = uart0.dr.read().data().bits();
            // 处理接收到的数据
        }
    });
}

构建和部署

  1. 安装必要的工具链:
rustup target add thumbv6m-none-eabi
cargo install elf2uf2-rs
  1. 构建项目:
cargo build --release
  1. 将程序转换为UF2格式并刷写到RP2040:
elf2uf2-rs target/thumbv6m-none-eabi/release/your_project your_project.uf2
# 然后按住BOOTSEL按钮将Pico连接到电脑,拖放UF2文件

rp2040-hal库为Rust开发者提供了访问RP2040芯片所有功能的类型安全接口,结合Rust的所有权模型和零成本抽象特性,可以构建高效可靠的嵌入式应用程序。

回到顶部