rtt线程管理
rt_thread结构体
线程由这个结构体控制(官方文档)
/* 线程控制块 */
struct rt_thread
{
/* rt 对象 */
char name[RT_NAME_MAX]; /* 线程名称 */
rt_uint8_t type; /* 对象类型 */
rt_uint8_t flags; /* 标志位 */
rt_list_t list; /* 对象列表 */
rt_list_t tlist; /* 线程列表 */
/* 栈指针与入口指针 */
void *sp; /* 栈指针 */
void *entry; /* 入口函数指针 */
void *parameter; /* 参数 */
void *stack_addr; /* 栈地址指针 */
rt_uint32_t stack_size; /* 栈大小 */
/* 错误代码 */
rt_err_t error; /* 线程错误代码 */
rt_uint8_t stat; /* 线程状态 */
/* 优先级 */
rt_uint8_t current_priority; /* 当前优先级 */
rt_uint8_t init_priority; /* 初始优先级 */
rt_uint32_t number_mask;
......
rt_ubase_t init_tick; /* 线程初始化计数值 */
rt_ubase_t remaining_tick; /* 线程剩余计数值 */
struct rt_timer thread_timer; /* 内置线程定时器 */
void (*cleanup)(struct rt_thread *tid); /* 线程退出清除函数 */
rt_uint32_t user_data; /* 用户数据 */
};
-
可以设置线程栈大小,对于较大资源的MCU可以设置1K或者2K的大小
-
线程五种状态,同一时间之允许一个线程在处理器中处理
-
可以设置优先级,优先级为0最高,最大支持0~255,一般使用32优先级
-
每个线程都可以设置时间片
-
线程不能进入死循环,如果这样比他优先级低的线程都不会运行
-
线程状态转换 注:RT-Thread 中,实际上线程并不存在运行状态,就绪状态和运行状态是等同的。
-
空闲线程,这是系统提供最低优先级的线程,永远为就绪态,当没有其他线程存在时,可以系统自动调用,通常是死循环,在rtt中有特殊用处,
若某线程运行完毕,系统将自动删除线程:自动执行 rt_thread_exit() 函数,先将该线程从系统就绪队列中删除,再将该线程的状态更改为关闭状态,不再参与系统调度,然后挂入 rt_thread_defunct 僵尸队列(资源未回收、处于关闭状态的线程队列)中,最后空闲线程会回收被删除线程的资源。
空闲线程也提供了接口来运行用户设置的钩子函数,在空闲线程运行时会调用该钩子函数,适合钩入功耗管理、看门狗喂狗等工作。
-
rt_thread_create() 创建一个动态线程,使用 rt_thread_init() 初始化一个静态线程,动态线程与静态线程的区别是:动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化 heap 之后才能使用 create 创建动态线程),静态线程是由用户分配栈空间与线程句柄。
rt_thread_t rt_thread_create(const char* name, void (*entry)(void* parameter), void* parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick);
对于运行出错或不适用的线程可以删除
rt_err_t rt_thread_delete(rt_thread_t thread);
初始化线程
rt_err_t rt_thread_init(struct rt_thread* thread,
const char* name,
void (*entry)(void* parameter), void* parameter,
void* stack_start, rt_uint32_t stack_size,
rt_uint8_t priority, rt_uint32_t tick);
脱离线程
rt_err_t rt_thread_detach (rt_thread_t thread);
启动线程
rt_err_t rt_thread_startup(rt_thread_t thread);
线程睡眠
rt_err_t rt_thread_sleep(rt_tick_t tick);
rt_err_t rt_thread_delay(rt_tick_t tick);
rt_err_t rt_thread_mdelay(rt_int32_t ms);
线程实例
#include <rtthread.h>
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
/* 线程 1 的入口函数 */
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1)
{
/* 线程 1 采用低优先级运行,一直打印计数值 */
rt_kprintf("thread1 count: %d
", count ++);
rt_thread_mdelay(500);
}
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程 2 入口 */
static void thread2_entry(void *param)
{
rt_uint32_t count = 0;
/* 线程 2 拥有较高的优先级,以抢占线程 1 而获得执行 */
for (count = 0; count < 10 ; count++)
{
/* 线程 2 打印计数值 */
rt_kprintf("thread2 count: %d
", count);
}
rt_kprintf("thread2 exit
");
/* 线程 2 运行结束后也将自动被系统脱离 */
}
/* 线程示例 */
int thread_sample(void)
{
/* 创建线程 1,名称是 thread1,入口是 thread1_entry*/
tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
/* 初始化线程 2,名称是 thread2,入口是 thread2_entry */
rt_thread_init(&thread2,
"thread2",
thread2_entry,
RT_NULL,
&thread2_stack[0],
sizeof(thread2_stack),
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
rt_thread_startup(&thread2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(thread_sample, thread sample);