文章目录
上一章我们介绍了怎么去移植一个有RTT的工程模板,这一章我们就去学习怎么去使用操作系统。
从最基本的点灯开始。
一、测试LED硬件
我们要点亮开发板的LED灯,首先我们应该确保这个硬件程序初始化没有问题,怎么测试呢,当然是用裸机的思想,直接去看这个效果。
1.LED GPIO初始化
在 board.c 的 rt_hw_board_init()函数中初始化LED灯
执行到rt_hw_board_init()函数的时候,操作系统完全都还没有涉及到。
运行完rt_hw_board_init()函数,接下来才慢慢启动操作系统,最后运行创建好的线程。
2.测试LED灯
在初始化硬件之后,可以测试一下硬件有没有问题。
编译下载后,开发板上的三个小灯都会被点亮。
完成这一步说明我们的硬件部分和LED软件初始化都没有任何问题。
二、创建静态线程
我们创建一个单线程,线程使用的栈和线程控制块都使用静态内存,即预先定义好的全局变量 ,这些预先定义好的全局变量都存放在内部的SRAM中。
1.定义线程栈
我们为线程定义一个栈,目前我们使用的是静态内存,所以线程栈是一个独立的全局变量。线程栈的占用的是MCU的内部RAM,当线程越多的时候,需要使用的栈空间就越大。一个MCU能够支持多少个线程,就得看你的RAM空间有多少。
2.定义线程控制块
我们为线程定义一个线程控制块,通常我们称这个线程控制块为线程的身份证。
3.定义线程函数
线程实际上就是一个无限循环且不带返回值的c函数。
我们创建LED1灯以500ms频率闪烁的一个线程。
线程里的延时函数必须使用RT_Thread里面提供的延时函数。
RT_Thread的延时是阻塞延时,即调用rt_thread_delay()函数的时候,当前线程会被挂起,调度器会切换到其他的就绪线程,从而实现多线程。
4.初始化线程
一个线程的三要素就是线程主体函数、线程栈、线程控制块。RT-Thread 里面有一个叫线程初始化函数 rt_thread_init(),用这个函数可以把这三个要素联系起来。
放到main函数里。
5.启动线程
当线程初始化好后,是处于线程初始态(RT_THREAD_INIT),并不能够参与操作系统的调度,只有当线程进入就绪态(RT_THREAD_READY)之后才能参与操作系统的调度.
线程由初始态进入就绪态可由函数 rt_thread_startup()来实现.
放到main函数里。
三、下载测试
我们把程序下载到开发板之后,会发现LED1(L1)会以500ms的频率闪烁。
四、扩展实验
创建两个线程,一个让LED1 以500ms闪烁,另外一个让LED2以1000ms闪烁。
MAIN函数代码:
**#include "All.h"
#include "board.h"
#include "rtthread.h"
/* 定义线程控制块 */
static struct rt_thread Led1_thread; // LED1线程控制块
static struct rt_thread Led2_thread; // LED2线程控制块
/* 定义线程栈时要求RT_ALIGN_SIZE个字节对齐 */
ALIGN(RT_ALIGN_SIZE)
/* 定义线程栈 */
static rt_uint8_t rt_Led1_thread_stack[1024]; // LED1 线程栈
static rt_uint8_t rt_Led2_thread_stack[1024]; // LED2 线程栈
/* LED1闪烁500ms 线程入口 */
static void Led1_thread_entry(void *parameter)
{
while(1)
{
LED1 = 0; // 点亮LED1
rt_thread_delay(500); // 延时500个tick
LED1 = 1; // 关闭LED1
rt_thread_delay(500); // 延时500个tick
}
}
/* LED2闪烁1000ms 线程入口 */
static void Led2_thread_entry(void *parameter)
{
while(1)
{
LED2 = 0; // 点亮LED2
rt_thread_delay(1000); // 延时500个tick
LED2 = 1; // 关闭LED2
rt_thread_delay(1000); // 延时500个tick
}
}
/********************************************
@功能:main函数
@说明:
@参数: 无
@返回值: 无
*********************************************/
int main()
{
/* 开发板硬件初始化,RTT系统初始化在main函数之前已经完成 */
/* LED1线程初始化函数*/
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);
/* LED1线程初始化函数*/
rt_thread_init( &Led2_thread, // 线程控制块
"LED2", // 线程名字
Led2_thread_entry, // 线程入口函数
RT_NULL, // 线程入口函数参数
&rt_Led2_thread_stack[0], // 线程栈起始地址
sizeof(rt_Led2_thread_stack), // 线程栈大小
3, // 线程的优先级
20 // 线程轮询时间片
);
/* 启动线程,开始调度 */
rt_thread_startup(&Led2_thread);
}**