外观
创建自己的第一个任务
本章主要介绍怎样在RT-Thread环境中创建自己的第一个任务,从而了解任务创建需要的相关资源。同时,还会介绍特殊的任务:空闲任务。
问题引入
假设你要开发一个智能家居控制器,需要同时做两件事:
- 每2秒读取点亮一次LED灯表明机器正在运行
- 随时响应用户的按键响应
如果是祼机代码,则形式大体如下:
while (1) {
if (定时器到2秒) led_task();
if (按键按下) button_task();
}
虽然这个任务比较简单,可以直接用祼机代码来解决;不过,这里我们主要关注如何用RT-Thread对功能进行拆分。
简单来说,可以拆分成两个任务:
创建任务
我们将功能拆分为两个独立任务:
- LED心跳任务:每2秒闪烁一次LED
- 按键响应任务:实时检测按键
任务函数形式
RT-Thread的任务函数需满足以下格式:
void task_entry(void *parameter) {
// 任务通常是无限循环
while (1) {
/* 任务具体逻辑 */
}
}
其中,参数parameter保存了任务创建时,传递给该任务的初始运行参数。
动态创建任务
仅仅创建任务是不够的,还需要使用RT-Thread提供的接口来创建任务,该接口如下:
rt_thread_t rt_thread_create(
const char *name, // 任务名称(调试用)
void (*entry)(void *), // 任务入口函数
void *parameter, // 传递参数(RT_NULL表示无)
rt_uint32_t stack_size, // 栈大小(字节)
rt_uint8_t priority, // 优先级(数值越小越高)
rt_uint32_t tick // 时间片长度(通常5-10)
);
返回值:成功返回线程句柄,失败返回RT_NULL
任务在创建完成之后,还需要使用rt_thread_startup()。也就说,利用该接口,才会将任务插入到就绪队列中。
rt_err_t rt_thread_startup(rt_thread_t thread);
4. 完整示例代码
#include <rtthread.h>
#include "base.h"
/*---------------------------------------
* 任务1:LED心跳
* 每2秒闪烁一次,表示系统运行正常
*--------------------------------------*/
void led_task_entry(void *param) {
RT_UNUSED(param);
while (1) {
led_toggle(LED0);
rt_thread_mdelay(2000);
}
}
/*---------------------------------------
* 任务2:按键检测
* 实时检测按键,按下时串口打印消息
*--------------------------------------*/
void key_task_entry(void *param) {
RT_UNUSED(param);
while (1) {
if (key_pressed()) {
led_set(LED1, 1);
} else {
led_set(LED1, 0);
}
}
}
/*---------------------------------------
* 应用入口(main函数)
*--------------------------------------*/
int main(void) {
hardware_init();
/* 创建LED心跳任务 */
rt_thread_t led_thread = rt_thread_create(
"led_heartbeat",
led_task_entry,
RT_NULL,
4096, // 栈大小
0, // 优先级
5 // 时间片
);
/* 创建按键检测任务 */
rt_thread_t key_thread = rt_thread_create(
"key_monitor",
key_task_entry,
RT_NULL,
4096, // 栈大小
0, // 优先级
5 // 时间片
);
/* 启动所有任务 */
if (led_thread) rt_thread_startup(led_thread);
if (key_thread) rt_thread_startup(key_thread);
return 0;
}