在这里有人也许会疑惑,在单片机有限的FLASH和RAM中运行一个操作系统,资源耗费是不是会很大?这个顾虑完全是多余的,如今单片机的内部FLASH和RAM越来越大,如果不够用,很方便外扩,完全可以流畅运行一个操作系统并在此基础上做很多事情~~~
2.操作系统的基础——线程 2.1.什么是线程(在1.2节中提到)在多线程系统中将整个程序主体分为一个个独立的,无限循环且不能返回的小程序,这一个个小程序就称为线程,每个线程都是独立的,互不干扰的,且具备自身的优先级,由操作系统进行调度和管理;
2.2.线程的组成RT-Thread中的线程由三部分组成:
线程主体(函数)
线程控制块
线程堆栈
接下来以工程所含例程中的"/package/samples/basic/led/led.c"文件为例进来探索RTT中的线程:
{
unsigned int count = 0;
rt_hw_led_init();
while (1)
{
/* led1 on */
rt_kprintf("led on, count : %d\r\n", count);
count++;
rt_hw_led_on(0);
/* sleep 0.5 second and switch to other thread */
rt_thread_delay(RT_TICK_PER_SECOND / 2);
/* led1 off */
rt_kprintf("led off\r\n");
rt_hw_led_off(0);
rt_thread_delay(RT_TICK_PER_SECOND / 2);
}
}
这是led线程的主体,可以看到,整个线程的主体是一个无限循环的程序,和我们在裸机下点灯的程序区别不大,只是将其中的具体实现换成了RT-Thread的实现:
int main(){
/* led初始化(GPIO)*/
led_init();
/* 无限循环 */
while(1)
{
led_on();
delay();
led_off();
delay();
}
}
2.2.2.线程控制块 /* 线程的TCB控制块 */
static struct rt_thread led_thread;
线程控制块就相当于线程的身份证,记录了线程的各个属性,比如线程的名称,线程的栈指针,线程的形参等等,有了这个线程控制块后,系统可以用线程控制块链表对其进行管理,具体的线程控制块结构体声明可以在rtdef.h中看到;
2.2.3.线程堆栈 ALIGN(RT_ALIGN_SIZE)static rt_uint8_t led_stack[ 512 ];
在裸机程序中,程序的运行过程中有变量的定义,子函数的调用,中断的产生等等,那么,这些变量放在哪里?子函数调用时,子函数的局部变量放在哪里?中断发生时,函数返回地址放在哪里?这些在裸机编程时都不用考虑,但在RTOS编程中这些是程序运行的基本条件,必须要一清二楚!
这些东西都被存放在栈中,即RAM的一段空间内,栈的大小在启动文件或者链接脚本里面指定,最后由C库函数_main进行初始化。但是在多线程操作系统中,每个线程就是一个独立运行的程序,且不能互相干扰,所以每个线程都要分配独立的栈空间,这个栈空间可以是一个预先定义好的全局数组,比如led线程的堆栈,这样的线程称为静态线程,相对的,如果这个栈空间是动态分配的,该线程称为动态线程,这个在后续会具体说明;
就led线程来看,首先设置下面的变量需要多少个字节对齐,ALIGN是一个带参宏定义,在rtdef.h中可以看到:
ALIGN的参数也是由宏定义指定的,在rtconfig.h中可以看到:
#define RT_ALIGN_SIZE 4设置好变量需要多少个字节对齐后,定义led线程的线程栈,其实就是一个全局数组,数据类型为rt_uint8_t,数组大小为512;
这里需要注意一点,在RT-Thread中,凡是涉及到数据类型的地方,RT-Thread都会将标准的C数据类型用typedef重新取一个类型名,以"rt"前缀开头。这些重新定义的数据类型放在rtdef.h中,代码如下:
typedef signed char rt_int8_t; /**< 8bit integer type */
typedef signed short rt_int16_t; /**< 16bit integer type */
typedef signed long rt_int32_t; /**< 32bit integer type */
typedef unsigned char rt_uint8_t; /**< 8bit unsigned integer type */
typedef unsigned short rt_uint16_t; /**< 16bit unsigned integer type */
typedef unsigned long rt_uint32_t; /**< 32bit unsigned integer type */
typedef int rt_bool_t; /**< boolean type */
/* 32bit CPU */
typedef long rt_base_t; /**< Nbit CPU related date type */
typedef unsigned long rt_ubase_t; /**< Nbit unsigned CPU related data type */
typedef rt_base_t rt_err_t; /**< Type for error number */
typedef rt_uint32_t rt_time_t; /**< Type for time stamp */
typedef rt_uint32_t rt_tick_t; /**< Type for tick count */
typedef rt_base_t rt_flag_t; /**< Type for flags */
typedef rt_ubase_t rt_size_t; /**< Type for size number */
typedef rt_ubase_t rt_dev_t; /**< Type for device */
typedef rt_base_t rt_off_t; /**< Type for offset */
/* boolean type definitions */
#define RT_TRUE 1 /**< boolean true */
#define RT_FALSE 0 /**< boolean fails */