Rust嵌入式开发库rp2040-hal的使用,为Raspberry Pi RP2040芯片提供硬件抽象层支持
Rust嵌入式开发库rp2040-hal的使用,为Raspberry Pi RP2040芯片提供硬件抽象层支持
简介
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。它们可以同时使用,因此您可以逐步升级驱动程序。
贡献
贡献使开源社区成为学习、激励和创造的绝佳场所。任何贡献都非常感激。
- 派生项目
- 创建您的特性分支 (
git checkout -b feature/AmazingFeature
) - 提交您的更改 (
git commit -m 'Add some AmazingFeature'
) - 推送到分支 (
git push origin feature/AmazingFeature
) - 打开拉取请求
许可证
此存储库的内容采用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);
}
}
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();
// 处理接收到的数据
}
});
}
构建和部署
- 安装必要的工具链:
rustup target add thumbv6m-none-eabi
cargo install elf2uf2-rs
- 构建项目:
cargo build --release
- 将程序转换为UF2格式并刷写到RP2040:
elf2uf2-rs target/thumbv6m-none-eabi/release/your_project your_project.uf2
# 然后按住BOOTSEL按钮将Pico连接到电脑,拖放UF2文件
rp2040-hal库为Rust开发者提供了访问RP2040芯片所有功能的类型安全接口,结合Rust的所有权模型和零成本抽象特性,可以构建高效可靠的嵌入式应用程序。