RT-Thread 操作系统
RT-Thread是一个开放源码的实时操作系统。这是第一次接触这个操作系统,主要因为它自带轻型TCP/IP协议栈。自己做的飞控是基于Wlan控制的,如果用裸机的话,通信协议相对过于复杂,而且猞猁、茶不思新出的飞控也是基于这个操作系统的。基于这些原因就开始学习这个操作系统了。
一、整体架构
先看看RT-Thread及外围组件的基本框架图,这样对整体下有个了解:
有了整体的了解,这个操作系统有是小型的,现在网上有大量的移植教程,移植起来是十分简单了。
移植完成后,我首先关注的就是main函数,在startup.c中找到main函数,这个函数特别的简单,就有3行代码:
int main(void)
{
/* disable interrupt first */
rt_hw_interrupt_disable();
/* startup RT-Thread RTOS */
rtthread_startup();
return 0;
}
第一行是关中断的操作,第三行是返回退出(永远都执行不到),这样我们就主要看rtthread_startup()这个函数了。
void rtthread_startup(void)
{
/*init board */ //初始化硬件平台相关:时钟设置、中断设置、系统滴答设置、串口设置
rt_hw_board_init();
/*show version */ //打印RT-Thread版本信息
rt_show_version();
/*init tick */
rt_system_tick_init();
/*init kernel object */ //内核对象初始化
rt_system_object_init();
/*init timer system */ //系统定时器初始化
rt_system_timer_init();
//动态内存分配
rt_system_heap_init((void*)STM32_SRAM_BEGIN, (void*)STM32_SRAM_END);
/*init scheduler system */ //系统调度器初始化
rt_system_scheduler_init();
/*init all device */ //系统设备对象初始化
rt_device_init_all();
/* init application */ //用户应用初始化
rt_application_init();
/* init timer thread */ //初始化软件定时器
rt_system_timer_thread_init();
/*init idle thread */ //初始化空线程
rt_thread_idle_init();
/*start scheduler */ //开始线程调度,此后便进入各个线程的无限循环
rt_system_scheduler_start();
/*never reach here */
return;
}
基本上上面的这些初始化是固定不变,我们主要关注的函数rt_application_init()函数,这是用户线程的创建入口函数。
二、线程
一个任务对应的程序实体就是一个“线程”(PS:个人理解),线程的调度就是怎么样很好的管理好这些任务,让它们之间不冲突、分时地完成自己的工作。一个线程一般有三部分组成:线程代码(函数)、线程控制块、线程堆栈。
线程代码:我们编写的工程代码,想要做的事。
线程控制:rt_thread结构体中的内容,包括线程的各个属性。
线程堆栈:为了满足线程切换和响应中断时保存cpu寄存器中的内容及任务调用其它函数时的准备。
线程又有静态线程和动态线程之分。
静态线程——线程堆栈由编译器静态分配,使用rt_thread_init()函数创建
动态线程——线程堆栈由系统动态分配,使用rt_thread_create()函数创建
下面就创建一个静态线程和一个动态线程
/* 静态线程的 线程堆栈 */
static rt_uint8_t fly1_stack[1024];
/* 静态线程的 线程控制块 */
static struct rt_thread fly1_thread;
void demo_thread_creat(void)
{
rt_err_tresult;
/*动态线程的 线程控制块指针 */
rt_thread_tfly2_thread;
rt_hw_fly_init();
/*创建静态线程:优先级20,时间片2个系统滴答 */
result= rt_thread_init(&fly1_thread,
"fly1",
static_thread_entry,RT_NULL,
(rt_uint8_t*)&fly1_stack[0],sizeof(fly1_stack),20,2);
if(result== RT_EOK)
{
rt_thread_startup(&fly1_thread);
}
/*创建动态线程:堆栈大小512bytes,优先级21,时间片2个系统滴答 */
fly2_thread= rt_thread_create("fly2",
dynamic_thread_entry,RT_NULL,
1024,21,2);
if(fly2_thread!= RT_NULL)
{
rt_thread_startup(fly2_thread);
}
}
创建好线程,就把程序的大概框架搭好了。剩下的就是各个线程之间的通信了填充框架,通信方式有多种如:信号量,邮箱....还有利用全局变量。