关于线程
RT-Thread中,线程由三部分组成:
- 线程代码(入口函数)
- 线程控制块
- 线程栈
线程代码(入口函数)
可以是无限循环结构或者顺序执行。
void thread1_entry(void* parameter)
{
while(1)
{
...
}
}
void thread2_entry(void* parameter)
{
//事务处理1
//事务处理2
...
//事务处理n
}
线程控制块
线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包线程与线程之间连接用的链表结构,线程等待事件集合等。
struct rt_thread
struct rt_thread* rt_thread_t
线程栈
RT-Thread每个线程都具有独立的栈空间,当进行线程切换时,系统会将当前线程的上下文保存在线程栈中,当线程要恢复运行时,再从线程栈中读取上下文信息,恢复线程的运行。
线程上下文是指线程执行时的环境,具体来说就是各个变量和数据包括所有寄存器变量、堆栈信息、内存信息等。
线程栈在形式上是一段连续的内存空间,我们可以通过定义一个数组或者申请一段动态内存来作为线程的栈。
相关API
创建线程
有两个API:
rt_thread_create(...)
用于创建动态线程,返回类型是rt_thread_t
,此时线程栈由系统动态分配。rt_thread_init(...)
用于创建静态线程,此时线程栈需要在代码中事先分配,它需要栈对齐,返回类型是rt_err_t
/**
* This function will create a thread object and allocate thread object memory
* and stack.
*
* @param name the name of thread, which shall be unique
* @param entry the entry function of thread
* @param parameter the parameter of thread enter function
* @param stack_size the size of thread stack
* @param priority the priority of thread
* @param tick the time slice if there are same priority thread
*
* @return the created thread object
*/
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)
/**
* This function will initialize a thread, normally it's used to initialize a
* static thread object.
*
* @param thread the static thread object
* @param name the name of thread, which shall be unique
* @param entry the entry function of thread
* @param parameter the parameter of thread enter function
* @param stack_start the start address of thread stack
* @param stack_size the size of thread stack
* @param priority the priority of thread
* @param tick the time slice if there are same priority thread
*
* @return the operation status, RT_EOK on OK, -RT_ERROR on error
*/
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_startup(rt_thread_t thread);
调用此函数后创建的线程会被加入到线程的就绪队列,执行调度。
例程
本例程目标:
使用两种不同方式创建线程,分别控制两个ART-Pi板载LED在不同频率下闪烁。(注意线程控制块声明方式、创建方式、启动方式都有区别)
/*
使用两种不同方式创建线程,分别控制两个ART-Pi板载LED在不同频率下闪烁。
(注意线程控制块声明方式、创建方式、启动方式都有区别)
*/
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#define LOG_TAG "thread_app"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
#define LED_PIN_B GET_PIN(I, 8)
#define LED_PIN_R GET_PIN(C, 15)
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
//线程1控制块声明
static rt_thread_t led_red_tid = RT_NULL;
//线程2控制块声明,静态线程需要栈对齐
ALIGN(RT_ALIGN_SIZE);
static rt_uint8_t led_blue_thread_stack[THREAD_STACK_SIZE];
static struct rt_thread led_blue_tid;
/* 线程1的入口函数 */
static void led_red_thread_entry(void *parameter)
{
rt_uint32_t count = 1;
while(count ++)
{
rt_thread_mdelay(250);
rt_pin_write(LED_PIN_R, PIN_HIGH);
rt_thread_mdelay(250);
rt_pin_write(LED_PIN_R, PIN_LOW);
LOG_D("led_red_thread count: %d", count);
}
}
/* 线程2的入口函数 */
static void led_blue_thread_entry(void *parameter)
{
rt_uint32_t count = 1;
while(count ++)
{
rt_thread_mdelay(1000);
rt_pin_write(LED_PIN_B, count%2);
LOG_D("led_blue_thread count: %d", count);
}
}
int main(void)
{
rt_pin_mode(LED_PIN_B, PIN_MODE_OUTPUT);
rt_pin_mode(LED_PIN_R, PIN_MODE_OUTPUT);
/* 创建线程1,线程控制块是led_red_tid,名称是led_red_thread,入口是led_red_thread_entry*/
led_red_tid = rt_thread_create("led_red_thread",
led_red_thread_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (led_red_tid != RT_NULL)
{
//启动线程1
rt_thread_startup(led_red_tid);
LOG_D("led_red_thread created successful");
}
else {
LOG_D("led_red_thread created failed");
}
/* 初始化线程2,线程控制块是led_blue_tid,名称是led_blue_thread,入口是led_blue_thread_entry */
rt_thread_init(&led_blue_tid,
"led_blue_thread",
led_blue_thread_entry,
RT_NULL,
&led_blue_thread_stack[0],
sizeof(led_blue_thread_stack),
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
//启动线程2,注意这里参数取地址
rt_thread_startup(&led_blue_tid);
return RT_EOK;
}
#include "stm32h7xx.h"
static int vtor_config(void)
{
/* Vector Table Relocation in Internal QSPI_FLASH */
SCB->VTOR = QSPI_BASE;
return 0;
}
INIT_BOARD_EXPORT(vtor_config);
注:
- RT-Thread最大支持 256 个线程优先级 (0~255),数值越小的优先级越高,0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持 8 个或 32 个优先级的系统配置;对于 ARM Cortex-M 系列,普遍采用 32 个优先级。最低优先级默认分配给空闲线程使用,用户一般不使用。
- finsh中使用
list_thread
命令可以看到线程的内存占用,一般以70%为最佳配置。