Rust实时中断和任务调度库rtic-core的使用,RTIC框架核心组件助力嵌入式系统开发
Rust实时中断和任务调度库rtic-core的使用,RTIC框架核心组件助力嵌入式系统开发
rtic-core
是Real-Time Interrupt-driven Concurrency(实时中断驱动并发)的核心抽象库。
许可证
采用以下任一许可证:
- Apache License, Version 2.0
- MIT license
贡献
除非您明确声明,否则任何有意提交的贡献都将按照上述双重许可证授权,无需任何附加条款或条件。
示例代码
以下是一个使用rtic-core的完整示例demo:
// 导入必要的库
use rtic_core::app;
use cortex_m::peripheral::{syst::SystClkSource, SYST};
use cortex_m_rt::entry;
// 定义RTIC应用程序
#[app(device = stm32f4xx_hal::stm32)]
mod app {
use super::*;
use stm32f4xx_hal::{
gpio::gpioa::PA5,
gpio::{Output, PushPull},
prelude::*,
};
// 共享资源
#[shared]
struct Shared {
led: PA5<Output<PushPull>>,
}
// 本地资源
#[local]
struct Local {}
// 初始化函数
#[init]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
// 获取设备外围设备访问权限
let dp = cx.device;
// 配置GPIO引脚
let gpioa = dp.GPIOA.split();
let led = gpioa.pa5.into_push_pull_output();
// 配置系统定时器
let mut syst = cx.core.SYST;
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(8_000_000); // 1秒间隔
syst.enable_counter();
syst.enable_interrupt();
(Shared { led }, Local {}, init::Monotonics())
}
// 系统定时器中断处理
#[task(binds = SysTick, shared = [led])]
fn systick(cx: systick::Context) {
// 切换LED状态
cx.shared.led.lock(|led| led.toggle().unwrap());
}
}
// 主入口点
#[entry]
fn main() -> ! {
// 启动RTIC应用程序
app::init();
loop {
cortex_m::asm::wfi();
}
}
安装
在项目目录中运行以下Cargo命令:
cargo add rtic-core
或者在Cargo.toml中添加:
rtic-core = "1.0.0"
分类
- 并发(Concurrency)
- 嵌入式开发(Embedded development)
- 无标准库(No standard library)
1 回复
Rust实时中断和任务调度库rtic-core的使用
简介
rtic-core是Rust实时中断和并发(RTIC)框架的核心组件,专为嵌入式系统开发设计。它提供了一种简洁高效的方式来管理硬件中断和任务调度,特别适合实时性要求高的嵌入式应用。
RTIC框架基于优先级的中断和任务调度模型,允许开发者以声明式的方式定义系统资源,自动处理资源共享和并发访问问题。
主要特性
- 基于优先级的任务调度
- 高效的资源管理
- 零成本抽象
- 最小运行时开销
- 与Cortex-M等嵌入式架构紧密集成
完整示例代码
下面是一个完整的RTIC应用示例,结合了中断处理、资源共享和定时任务:
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use rtic::app;
use stm32f4xx_hal::{
gpio::{gpioa::PA5, Edge, Input, Output, PushPull},
prelude::*,
stm32,
timer::Timer,
};
#[app(device = stm32f4xx_hal::stm32)]
mod app {
use super::*;
use core::fmt::Write;
use cortex_m::interrupt::Mutex;
use core::cell::RefCell;
use stm32f4xx_hal::serial::{Serial, Config};
// 共享资源
#[shared]
struct Shared {
counter: u32,
serial: Mutex<RefCell<Option<Serial<stm32::USART2>>>>,
}
// 局部资源
#[local]
struct Local {
led: PA5<Output<PushPull>>,
button: PA0<Input>,
timer: Timer<stm32::TIM2>,
}
#[init]
fn init(cx: init::Context) -> (Shared, Local) {
// 获取设备外设
let dp = cx.device;
// 配置时钟
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(48.mhz()).freeze();
// 初始化GPIO
let gpioa = dp.GPIOA.split();
let led = gpioa.pa5.into_push_pull_output();
let button = gpioa.pa0.into_pull_up_input();
// 配置串口
let tx = gpioa.pa2.into_alternate_af7();
let rx = gpioa.pa3.into_alternate_af7();
let serial = Serial::usart2(
dp.USART2,
(tx, rx),
Config::default().baudrate(115200.bps()),
clocks,
).unwrap();
// 配置定时器
let mut timer = Timer::tim2(dp.TIM2, 1.hz(), clocks);
timer.listen(stm32f4xx_hal::timer::Event::TimeOut);
// 配置外部中断
let mut syscfg = dp.SYSCFG.constrain();
let mut exti = dp.EXTI;
button.make_interrupt_source(&mut syscfg);
button.trigger_on_edge(&mut exti, Edge::Falling);
button.enable_interrupt(&mut exti);
// 初始调度
periodic_task::schedule_after(500.millis()).unwrap();
(
Shared {
counter: 0,
serial: Mutex::new(RefCell::new(Some(serial))),
},
Local {
led,
button,
timer,
},
)
}
#[idle]
fn idle(_cx: idle::Context) -> ! {
loop {
// 进入低功耗模式
cortex_m::asm::wfi();
}
}
// 按钮中断处理
#[task(binds = EXTI0, priority = 1, shared = [counter, serial])]
fn button_press(cx: button_press::Context) {
*cx.shared.counter += 1;
cx.shared.serial.lock(|serial| {
if let Some(serial) = &mut *serial.borrow_mut() {
let _ = writeln!(serial, "Button pressed! Count: {}", *cx.shared.counter);
}
});
}
// 定时器中断处理
#[task(binds = TIM2, priority = 2, local = [led, timer])]
fn timer_tick(cx: timer_tick::Context) {
// 翻转LED状态
cx.local.led.toggle();
// 清除中断标志
cx.local.timer.clear_interrupt(stm32f4xx_hal::timer::Event::TimeOut);
}
// 周期性软件任务
#[task(priority = 1, shared = [serial])]
fn periodic_task(cx: periodic_task::Context) {
cx.shared.serial.lock(|serial| {
if let Some(serial) = &mut *serial.borrow_mut() {
let _ = writeln!(serial, "Periodic task executed");
}
});
// 每500毫秒重新调度自己
periodic_task::schedule_after(500.millis()).unwrap();
}
}
代码说明
-
初始化(init): 配置硬件外设,包括GPIO、串口、定时器和外部中断。
-
空闲任务(idle): 系统空闲时进入低功耗模式。
-
按钮中断(button_press):
- 优先级1的中断处理函数
- 每次按钮按下时增加计数器
- 通过串口输出当前计数
-
定时器中断(timer_tick):
- 优先级2的中断处理函数
- 定期翻转LED状态
- 清除定时器中断标志
-
周期性任务(periodic_task):
- 优先级1的软件任务
- 每500毫秒通过串口输出信息
- 自动重新调度自身
项目配置
Cargo.toml需要包含以下依赖:
[dependencies]
rtic = "1.0"
cortex-m = "0.7"
cortex-m-rt = "0.7"
stm32f4xx-hal = { version = "0.13", features = ["rt"] }
panic-halt = "0.2"
注意事项
-
确保使用正确的目标设备配置,示例中使用的是STM32F4系列
-
根据实际硬件调整GPIO引脚配置
-
优先级设置要合理,避免优先级反转问题
-
共享资源的访问要通过RTIC提供的锁机制
-
定时器周期需要根据实际需求调整