Rt-Thread学习笔记-----线程创建(三)
经过之前的RtThread的移植,我们接下来进行简单地线程创建。从点灯开始吧。
RtThread的API参考书册
一、新建LED底层
野火的bsp_led驱动。由于板子是原子的(我不是花心,我是成年人,小孩子才做选择,我都要)
所以更改相应配置(LED1/PE5、LED2/PB5)
二、创建单线程——SRAM静态内存
/*
*************************************************************************
* 静态线程变量
*************************************************************************
*/
/* 定义线程控制块 */
static struct rt_thread led1_thread;
/* 定义线程控栈时要求RT_ALIGN_SIZE个字节对齐 */
ALIGN(RT_ALIGN_SIZE)
/* 定义线程栈 */
static rt_uint8_t rt_led1_thread_stack[1024];
/*
*************************************************************************
* 函数声明
*************************************************************************
*/
static void led1_thread_entry(void* parameter);
/* 线程示例 */
int Task_Init(void)
{
//静态线程
rt_thread_init(&led1_thread, /* 线程控制块 */
"led1", /* 线程名字 */
led1_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
&rt_led1_thread_stack[0], /* 线程栈起始地址 */
sizeof(rt_led1_thread_stack), /* 线程栈大小 */
3, /* 线程的优先级 */
20); /* 线程时间片 */
rt_thread_startup(&led1_thread); /* 启动线程,开启调度 */
return 0;
}
线程里面的延时函数必须使用 RT-Thread 里面提供的延时函数,并不能使用我们裸机编程中的那种延时。这两种的延时的区别是 RT-Thread 里面的延时是阻塞延时,即调用 rt_thread_delay()函数的时候,当前线程会被挂起,调度器会切换到其它就绪的线程,从而实现多线程。如果还是使用裸机编程中的那种延时,那么整个线程就成为了一个死循环,如果恰好该线程的优先级是最高的,那么系统永远都是在这个线程中运行,根本无法实现多线程。目前我们只创建了一个线程,当线程进入延时的时候,因为没有另外就绪的用户线程,那么系统就会进入空闲线程,空闲线程是 RT-Thread 系统自己启动的一个线程,优先级最低。当整个系统都没有就绪线程的时候,系统必须保证有一个线程在运行,空闲线程就是为这个设计的。当用户线程延时到期,又会从空闲线程切换回用户线程。
三、创建单线程——SRAM动态内存
/*
*************************************************************************
* 动态态线程变量
*************************************************************************
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
*/
/* 定义线程控制块 */
static rt_thread_t led1_thread_Dynamic = RT_NULL;
/* 线程示例 */
int Task_Init(void)
{
//动态线程
/* 创建线程 1,名称是 LED1,入口是 led1_thread_entry*/
led1_thread_Dynamic = /* 线程控制块指针 */
rt_thread_create("LED1", /* 线程名字 */
led1_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
THREAD_STACK_SIZE, /* 线程栈大小 */
THREAD_PRIORITY, /* 线程的优先级 */
THREAD_TIMESLICE /* 线程时间片 */
);
/* 启动线程,开启调度 */
if (led1_thread_Dynamic != RT_NULL){
rt_thread_startup(led1_thread_Dynamic);
rt_kprintf("动态内存创建成功\n\n");
}else{
rt_kprintf("动态内存创建失败\n\n");
return -1;
}
return 0;
}
/*
*************************************************************************
* 线程定义
*************************************************************************
*/
static void led1_thread_entry(void* parameter)
{
while (1)
{
#if 0
LED1_ON;
rt_thread_delay(500); /* 延时500个tick */
LED1_OFF;
rt_thread_delay(500); /* 延时500个tick */
#endif
LedToggle(LED1_GPIO_PORT,LED1_GPIO_PIN);
rt_thread_delay(500);
rt_kprintf("LED1 IS OK\r\n");
}
}
main函数中代码
#include "board.h"
#include <string.h>
int main(void)
{
Task_Init();
rt_kprintf("\n\n");
rt_kprintf("单线程动态内存\n\n");
while(1)
{
LedToggle(LED2_GPIO_PORT,LED2_GPIO_PIN);
rt_thread_mdelay(1000);
rt_kprintf("LED2 IS OK\n\n");
}
}
这个时候我们的单线程动态点灯线程创建完毕,编译一下。
Error: L6218E: Undefined symbol rt_thread_create (referred from task.o).*
what?咋有报错,查看头文件也添加了,路径也添加了怎么还报错?难道是keil的bug。清理编译文件,重新打开再次编译。好吧真的是错了。为什么呢?
原来在rtconfig.h中我们没有把相应宏定义打开
解决方法:
找到rtconfig.h内核配置文件 ——> #define RT_USING_HEAP
将其注释取消
再次编译。
下载验证。
三、创建多线程——SRAM静态、动态内存
创建一个动态线程初始化一个静态线程,一个线程在运行完毕后自动被系统删除,另一个线程一直打印计数
/*
*************************************************************************
* 多线程---动态、静态
*************************************************************************
*/
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\n", 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\n", count);
}
rt_kprintf("thread2 exit\n");
/* 线程 2 运行结束后也将自动被系统脱离 */
}
/* 线程示例 */
int Task_Init(void)
{
//动态线程
/* 创建线程 1,名称是 LED1,入口是 led1_thread_entry*/
led1_thread_Dynamic = /* 线程控制块指针 */
rt_thread_create("LED1", /* 线程名字 */
led1_thread_entry, /* 线程入口函数 */
RT_NULL, /* 线程入口函数参数 */
THREAD_STACK_SIZE, /* 线程栈大小 */
THREAD_PRIORITY, /* 线程的优先级 */
THREAD_TIMESLICE /* 线程时间片 */
);
#if 1
/* 启动线程,开启调度 */
if (led1_thread_Dynamic != RT_NULL){
rt_thread_startup(led1_thread_Dynamic);
rt_kprintf("单线程--动态内存创建成功\n\n");
}else{
rt_kprintf("单线程--动态内存创建失败\n\n");
return -1;
}
#endif
//--------------------------------------------------
/* 创建线程 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);
rt_kprintf("多线程--动态内存创建成功\n\n");
}else{
rt_kprintf("多线程--动态内存创建失败\n\n");
return -1;
}
/* 初始化线程 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);
rt_kprintf("多线程--静态内存创建成功\n\n");
//---------------------------------------------------
return 0;
}
下载验证:
线程 2 计数到一定值会执行完毕,线程 2 被系统自动删除,计数停止。线程 1 一直打印计数