第8课:中断与异步事件处理
在Zephyr RTOS中,中断服务程序(ISR)是处理硬件中断的关键组件。Zephyr提供了标准化的方法来定义和连接ISR。
使用IRQ_CONNECT宏将中断服务程序连接到特定的中断线:
#include <zephyr.h>
#include <device.h>
#include <drivers/gpio.h>
#define MY_IRQ_PIN 5
#define MY_IRQ_PRIORITY 2
void my_isr(const void *arg)
{
// 中断处理代码
printk("中断触发!\n");
}
void main(void)
{
// 连接中断服务程序
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(my_device)), // 中断号
MY_IRQ_PRIORITY, // 中断优先级
my_isr, // ISR函数
NULL, // 传递给ISR的参数
0); // 标志位
// 启用中断
irq_enable(DT_IRQN(DT_NODELABEL(my_device)));
}
注意: Zephyr推荐使用设备树(DTS)来获取中断号,而不是硬编码,如DT_IRQN(DT_NODELABEL(my_device))所示。
ISR应该尽可能简短,只执行最必要的操作。长时间运行的操作应该推迟到线程上下文。
ISR中不能使用可能导致阻塞的API,如k_sleep()、k_mutex_lock()等。
可以通过信号量、消息队列等内核对象通知线程上下文有中断发生。
警告: 在ISR中调用打印函数(如printk)可能会影响实时性能,只应在调试时使用。
工作队列是Zephyr中用于延迟处理的一种机制,特别适合将ISR中的耗时操作推迟到线程上下文中执行。
Zephyr提供了一个预定义的系统工作队列(k_sys_work_q),可以直接使用:
#include <zephyr.h>
#include <sys/work_q.h>
struct k_work my_work;
void work_handler(struct k_work *work)
{
printk("工作项被执行\n");
}
void main(void)
{
// 初始化工作项
k_work_init(&my_work, work_handler);
// 提交到系统工作队列
k_work_submit(&my_work);
}
对于需要更高优先级或专用线程的情况,可以创建自定义工作队列:
#include <zephyr.h>
#include <sys/work_q.h>
#define MY_STACK_SIZE 1024
#define MY_PRIORITY 5
K_THREAD_STACK_DEFINE(my_stack_area, MY_STACK_SIZE);
struct k_work_q my_work_q;
struct k_work my_work;
void work_handler(struct k_work *work)
{
printk("自定义工作队列中的工作项被执行\n");
}
void main(void)
{
// 初始化自定义工作队列
k_work_queue_init(&my_work_q);
// 启动工作队列线程
k_work_queue_start(&my_work_q,
my_stack_area,
K_THREAD_STACK_SIZEOF(my_stack_area),
MY_PRIORITY,
NULL);
// 初始化工作项
k_work_init(&my_work, work_handler);
// 提交到自定义工作队列
k_work_submit_to_queue(&my_work_q, &my_work);
}
Zephyr还支持延迟执行的工作项:
#include <zephyr.h>
#include <sys/work_q.h>
struct k_delayed_work delayed_work;
void delayed_work_handler(struct k_work *work)
{
printk("延迟工作项被执行\n");
}
void main(void)
{
// 初始化延迟工作项
k_delayed_work_init(&delayed_work, delayed_work_handler);
// 提交延迟工作项(1秒后执行)
k_delayed_work_submit(&delayed_work, K_SECONDS(1));
}
典型的中断+工作队列处理模式:
#include <zephyr.h>
#include <sys/work_q.h>
struct k_work isr_work;
void isr_work_handler(struct k_work *work)
{
// 在线程上下文中处理中断事件
printk("处理中断事件\n");
}
void my_isr(const void *arg)
{
// 在ISR中提交工作项
k_work_submit(&isr_work);
}
void main(void)
{
// 初始化工作项
k_work_init(&isr_work, isr_work_handler);
// 连接中断
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(my_device)),
2, my_isr, NULL, 0);
irq_enable(DT_IRQN(DT_NODELABEL(my_device)));
}
| 特性 | 系统工作队列 | 自定义工作队列 |
|---|---|---|
| 预定义 | 是 | 否 |
| 优先级 | 低(通常) | 可自定义 |
| 线程资源 | 共享 | 专用 |
| 使用场景 | 一般延迟任务 | 实时性要求高的任务 |
扫描访问店铺
扫描添加客服