rt_thread 的定时器管理源码分析
- 格式:doc
- 大小:256.50 KB
- 文档页数:19
rtthread里面的堆设置原理-概述说明以及解释1.引言1.1 概述在嵌入式实时操作系统中,堆是一个重要的概念,也是实现动态内存分配的重要手段。
在rtthread中,堆的设置尤为重要,它不仅影响系统的内存管理效率,还直接影响到系统的稳定性和可维护性。
因此,深入理解rtthread中堆设置的原理是非常必要的。
本文将围绕rtthread中堆的概念、作用、设置方法以及原理展开讨论,希望读者能够通过本文全面了解rtthread中堆设置的重要性,并为今后在实际应用中做好相关设置提供指导。
1.2文章结构文章结构部分的内容如下:"1.2 文章结构:本文将分为三个主要部分,分别是引言、正文和结论。
在引言部分,将介绍本文的概述、文章结构以及撰写的目的。
在正文部分,将详细介绍rtthread中堆的概念及作用,堆的设置方法,以及堆设置的原理。
在结论部分,将总结rtthread中堆设置的重要性,展望堆设置的未来发展,并进行结语。
通过这样的结构,读者可以全面了解rtthread中堆设置的相关内容,从而更好地理解其原理和作用。
"1.3 目的在本文中,我们的主要目的是探讨rtthread中堆设置的原理。
通过深入研究rtthread中堆设置的工作原理,可以帮助开发人员更深入地了解如何优化堆的使用,提升系统的性能和稳定性。
同时,通过对堆设置原理的解析,也可以帮助开发人员更好地理解rtthread的内部机制,为日后的开发和调试工作提供更加清晰的指导和帮助。
通过本文的学习,读者能够更好地掌握rtthread操作系统的核心概念和原理,从而更加熟练地应用这些知识进行系统开发和优化工作。
2.正文2.1 rtthread中堆的概念及作用在rtthread中,堆是用来存放动态分配内存的区域。
堆是由系统在程序运行时动态管理的,程序员可以根据需要在堆中动态分配内存空间,而不需要在编写程序时提前确定内存分配的大小。
堆的作用主要体现在以下几个方面:1. 动态内存分配:堆为程序提供了一种灵活的内存分配方式,可以根据实际情况动态给变量分配内存,避免了静态内存分配时出现内存浪费或内存不足的情况。
从0到1教你写RT-Thread之线程的定义《《《《《正文》》》》》《前言》本章是我们真正从从 0 到 1 写RT-Thread的第一章,属于基础中的基础,必须要学会创建线程,并重点掌握线程是如何切换的。
因为线程的切换是由汇编代码来完成的,所以代码看起来比较难懂,但是我会尽力把代码讲得透彻。
如果本章内容学不会,后面的内容根本无从下手。
在这章中,我们会创建两个线程,并让这两个线程不断地切换,线程的主体都是让一个变量按照一定的频率翻转,通过KEIL的软件仿真功能,在逻辑分析仪中观察变量的波形变化,最终的波形图具体见图 6-1。
其实,图 6-1 的波形图的效果,并不是真正的多线程系统中线程切换的效果图,这个效果其实可以完全由裸机代码来实现,具体见代码清单 6-1。
在多线程系统中,两个线程不断切换的效果图应该像图 6-2 所示那样,即两个变量的波形是完全一样的,就好像CPU在同时干两件事一样,这才是多线程的意义。
虽然两者的波形图一样,但是,代码的实现方式是完全不一样的,由原来的顺序执行变成了线程的主动切换,这是根本区别。
这章只是开始,我们先掌握好线程是如何切换,在后面章节中,我们会陆续的完善功能代码,加入系统调度,实现真正的多线程。
千里之行,始于本章节,不要急。
《什么是线程》在裸机系统中,系统的主体就是 main 函数里面顺序执行的无限循环,这个无限循环里面 CPU 按照顺序完成各种事情。
在多线程系统中,我们根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数我们称为线程。
线程的大概形式具体见代码清单 6-2。
《创建线程》1、定义线程栈我们先回想下,在一个裸机系统中,如果有全局变量,有子函数调用,有中断发生。
那么系统在运行的时候,全局变量放在哪里,子函数调用时,局部变量放在哪里,中断发生时,函数返回地址发哪里。
如果只是单纯的裸机编程,它们放哪里我们不用管,但是如果要写一个RTOS,这些种种环境参数,我们必须弄清楚他们是如何存储的。
rtthread 项目例程RT-Thread 是一个开源的物联网操作系统,以其高效、灵活和可靠的特性,被广泛应用于各种嵌入式设备和物联网应用中。
本文将以一个实际的 RT-Thread 项目例程为例,来展示其功能和应用场景。
这个项目例程是一个智能家居控制系统,它可以实现远程控制家庭中的各种设备,例如灯光、温度、门窗等。
用户可以通过手机或者电脑上的应用程序来实时监控和控制家中的各种设备。
我们需要在RT-Thread 上创建一个通信模块,该模块可以与手机或电脑上的应用程序进行通信。
通过这个模块,用户可以与智能家居系统进行交互,发送指令和接收信息。
这个通信模块需要支持多种通信协议,例如 Wi-Fi、蓝牙或者 Zigbee。
这样,用户可以根据自己的需求选择合适的通信方式。
接下来,我们需要连接各种设备到智能家居系统上。
例如,我们可以通过GPIO 接口将灯光、温度传感器、门窗传感器等设备连接到RT-Thread 上。
这样,智能家居系统就可以获取到这些设备的状态信息,并根据用户的指令进行相应的控制。
例如,当用户发送开灯指令时,智能家居系统会通过 GPIO 接口控制灯光的开关。
除了基本的设备控制功能,智能家居系统还可以实现一些高级功能,例如定时控制、情景模式等。
用户可以通过应用程序设置定时任务,例如在某个时间点打开灯光,或者在某个温度阈值达到时发送警报。
情景模式可以让用户一键切换不同的家居状态,例如回家模式、离家模式等。
智能家居系统还可以集成语音控制功能。
用户可以通过语音指令来控制家中的各种设备,例如“打开客厅的灯光”或者“调高温度”。
为了实现语音控制功能,我们可以使用一个语音识别模块,并将其连接到RT-Thread 上。
这样,用户就可以通过语音与智能家居系统进行交互。
RT-Thread 项目例程中的智能家居控制系统具有多种功能和应用场景。
它可以实现远程控制、定时控制、情景模式和语音控制等功能,为用户带来便利和舒适的生活体验。
rtthread任务调度原理rt-thread是一个开源的实时操作系统,广泛应用于嵌入式系统中。
它具有高效的任务调度机制,能够有效地管理和调度系统中的各个任务。
本文将从任务调度的原理和实现方式两个方面介绍rt-thread任务调度的工作原理。
一、任务调度的原理rt-thread采用的是抢占式的优先级调度算法。
此算法通过为每个任务分配优先级,并根据优先级来决定任务的执行顺序。
具体来说,rt-thread将任务划分为两种类型:线程和实时线程。
线程是最基本的任务单元,通过线程来实现系统中不同功能的并发执行。
每个线程都有自己的优先级,优先级高的线程在系统空闲时会被优先执行。
线程的调度是通过rt-thread内核中的调度器来完成的。
实时线程是一种特殊的线程,它具有固定的周期和执行时间要求。
为了满足实时线程的要求,rt-thread引入了时钟滴答机制,以固定的时间间隔来调度实时线程的执行。
时钟滴答机制是rt-thread 的核心功能之一,它通过硬件定时器来实现,确保实时线程能够按时执行。
任务调度的过程是在时钟滴答中完成的。
每当时钟滴答到来时,调度器会根据当前任务的状态和优先级来选择下一个要执行的任务,并进行上下文切换。
上下文切换是指将当前任务的上下文保存起来,并恢复下一个任务的上下文,使其能够继续执行。
二、任务调度的实现方式rt-thread任务调度的实现方式主要包括任务控制块、就绪队列和调度器三个部分。
任务控制块(TCB)是rt-thread中用于管理任务的数据结构,它包含了任务的状态、优先级、堆栈等信息。
每个任务都有一个对应的任务控制块,通过任务控制块可以对任务进行管理和调度。
就绪队列是用来保存所有处于就绪状态的任务的数据结构,它按照任务的优先级进行排序。
当任务进入就绪状态时,会被插入到就绪队列中的适当位置。
调度器会从就绪队列中选择优先级最高的任务进行执行。
调度器是rt-thread中的核心组件,它负责任务的调度和上下文切换。
RTThread学习笔记——对线程的个⼈了解线程?它是啥? 在我们刚开始进⼊嵌⼊式软件的编程领域时,每次都会接触到⼀个函数——main函数,在裸机的编程中,程序的执⾏流程就是在main 函数中进⾏的,main函数也可以理解为⼀个线程,它也有它的栈空间来存储变量。
但是,如果有许多线程呢,怎样来区分它们?⼜怎样来分配存储空间? 对于这个问题,RTThread有它的解决办法。
⾸先是线程栈 栈,是⼀种经典的储存结构,RTThread为每个线程都分配了栈空间,来看看它是怎样定义的。
ALIGN(RT_ALIGN_SIZE) //线程栈对齐static rt_uint8_t rt_led1_thread_stack[1024]; //定义线程栈 这是⼀个rt_uint8_t(RTThread中的宏定义,⽆符号8位)类型的全局数组,第⼀句话是为了栈空间对齐,使得CPU对数据的访问更加⾼效,第⼆句就是线程的具体定义了,这⾥定义1024的长度。
然后是线程的ID卡——线程控制块 在操作系统中,常常有许多的线程在运⾏,⾯对着这么多的的线程,⾃然需要⼀个⾝份块来标识每个线程,使得系统便于管理。
⽽这个⾝份,就是线程控制块。
具体定义如下:struct rt_thread{/* rt object */char name[RT_NAME_MAX]; /**< the name of thread */rt_uint8_t type; /**< type of object */rt_uint8_t flags; /**< thread's flags */#ifdef RT_USING_MODULEvoid *module_id; /**< id of application module */#endifrt_list_t list; /**< the object list */rt_list_t tlist; /**< the thread list *//* stack point and entry */void *sp; /**< stack point */void *entry; /**< entry */void *parameter; /**< parameter */void *stack_addr; /**< stack address */rt_uint32_t stack_size; /**< stack size *//* error code */rt_err_t error; /**< error code */rt_uint8_t stat; /**< thread status *//* priority */rt_uint8_t current_priority; /**< current priority */rt_uint8_t init_priority; /**< initialized priority */#if RT_THREAD_PRIORITY_MAX > 32rt_uint8_t number;rt_uint8_t high_mask;#endifrt_uint32_t number_mask;#if defined(RT_USING_EVENT)/* thread event */rt_uint32_t event_set;rt_uint8_t event_info;#endif#if defined(RT_USING_SIGNALS)rt_sigset_t sig_pending; /**< the pending signals */rt_sigset_t sig_mask; /**< the mask bits of signal */void *sig_ret; /**< the return stack pointer from signal */rt_sighandler_t *sig_vectors; /**< vectors of signal handler */void *si_list; /**< the signal infor list */#endifrt_ubase_t init_tick; /**< thread's initialized tick */rt_ubase_t remaining_tick; /**< remaining tick */struct rt_timer thread_timer; /**< built-in thread timer */void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit *//* light weight process if present */#ifdef RT_USING_LWPvoid *lwp;#endifrt_uint32_t user_data; /**< private user data beyond this thread */}; 看起来线程控制块的定义⾮常复杂,实际上,线程控制块的主要包含信息有对象成员相关(RTT(hread)通过对象来进⾏管理),线程链表相关(RTT通过线程链表实现调度,也被称为优先级表/就绪链表),线程栈相关和线程本⾝的相关地址。
rtthread 任务调度原理## RT-Thread 任务调度原理RT-Thread是一个实时操作系统(RTOS),其任务调度原理是其核心设计之一。
任务调度是操作系统的关键功能之一,它决定了任务的执行顺序和时间分配。
RT-Thread采用抢占式优先级调度算法,下面将介绍RT-Thread任务调度的原理。
### 任务调度器RT-Thread的任务调度器是操作系统内核中的一个重要组件,主要负责管理和调度任务。
任务调度器根据任务的优先级和状态来决定任务的执行顺序。
### 任务控制块(TCB)每个任务在RT-Thread中都有一个对应的任务控制块(Task Control Block,TCB),TCB是一个数据结构,用于描述和管理任务的各种信息。
TCB中包含了任务的优先级、状态、栈空间等。
### 任务状态RT-Thread中的任务有以下几种状态:1. 就绪态(Ready):任务已经创建完成,但还未执行。
2. 运行态(Running):任务正在执行。
3. 阻塞态(Blocked):任务由于某些原因暂时无法执行,如等待信号量、等待事件等。
4. 挂起态(Suspended):任务被挂起,不会被调度执行。
### 优先级调度算法RT-Thread采用抢占式优先级调度算法,具体如下:1. 在就绪队列中,任务按照优先级由高到低排序。
当就绪队列中只有一个任务时,该任务被调度执行。
2. 当有新的任务就绪或者当前任务被阻塞等原因无法继续执行时,调度器会选择优先级最高的就绪任务来执行。
3. 当高优先级任务被调度执行后,低优先级任务会被挂起,等待下一次调度执行。
### 任务调度过程下面是RT-Thread任务调度的基本流程:1. 系统启动后,创建和初始化空闲任务。
空闲任务是一个特殊任务,当没有其他任务可以运行时,被调度器执行。
2. 创建其他任务,并设置它们的优先级和初始状态为就绪态。
3. 启动调度器,开始任务调度。
4. 调度器会根据任务的优先级来选择一个就绪任务,将其状态设置为运行态,切换到该任务执行。
rtthread设计与实现RT-Thread 是一个开源的实时操作系统(RTOS),它主要适用于嵌入式系统开发。
RT-Thread 具有高度可定制性,并且提供了丰富的中间件组件,例如TCP/IP 网络堆栈、文件系统、GUI 图形界面等。
RT-Thread 的设计和实现主要包括以下几个部分:1、内核:RT-Thread 的内核基于组件化的设计思想,提供了一个可配置的核心框架。
核心组件包括:(1)RT-Thread Scheduler:这是RT-Thread 的核心调度器,负责任务管理和调度。
(2)RT-Thread Timer:定时器管理,用于实现延迟操作和定时任务。
(3)RT-Thread Mailbox:用于实现任务间的通信和同步。
(4)RT-Thread Message Queue:消息队列,用于任务间的数据传输。
(5)RT-Thread Memory Pool:内存池管理,用于动态内存分配和管理。
2、组件:RT-Thread 提供了一系列中间件组件,例如:(1)RT-Thread Networking:TCP/IP 网络协议栈,支持各种网络接口和协议。
(2)RT-Thread File System:支持多种文件系统,例如Fat 文件系统、ext2/3 文件系统等。
(3)RT-Thread GUI:支持多种图形界面,例如Qt、MiniGUI 等。
(4)RT-Thread Device Driver:设备驱动框架,用于支持各种硬件设备的驱动程序开发。
3、工具链:RT-Thread 提供了一套完整的工具链,包括编译器、调试器、烧录器等。
同时,RT-Thread 支持多种编程语言,例如C/C++、Python 等。
4、应用编程接口(API):RT-Thread 提供了一套简单易用的API,使得开发者可以方便地使用RT-Thread 的各种功能。
例如,通过RT-Thread 的API 可以创建任务、管理任务、管理内存、管理网络连接等。
RT-Thread——线程管理1.线程的概念线程可以理解为⼀个个相互独⽴运⾏的单元任务。
这些任务共同使⽤CPU和内存空间等系统资源,不过,每⼀时刻,只能有⼀个线程在运⾏。
各个线程的运⾏是相互独⽴,不断切换的,所以线程都要有⾃⼰的堆栈,从⽽再次运⾏时能够恢复运⾏环境。
2.线程的调度RT-Thread提供的线程调度器是基于优先级的全抢占式调度,但中断函数和临界段程序是不可抢占的。
系统总共⽀持256个优先级,即0~255,数值越⼩,优先级越⾼,0为最⾼优先级,255是空闲线程的优先级,⽤户⼀般不会使⽤。
当有⽐当前运⾏线程优先级更⾼的线程就绪时,当前线程将⽴刻被换出,⾼优先级线程抢占运⾏。
RT-Thread还⽀持创建相同优先级的线程。
这些线程采⽤时间⽚轮转进⾏调度,但前提是没有更⾼优先级的线程出现。
所有准备好的线程都链接到了优先级队列中,选择优先级⾼的线程就是在优先级数组中寻找最⾼优先级线程对应的⾮空链表。
3.线程的状态操作系统中的线程有的在执⾏,有的被抢占,还有的即将被运⾏,也就是说有多种运⾏状态。
RT-Thread分5种运⾏状态:①初始态:RT_THREAD_INIT,创建线程时设置为初始态;②就绪态:RT_THREAD_READY,线程在就绪列表中,具备执⾏的条件,等待CPU运⾏;③运⾏态:RT_THREAD_RUNNING,线程正在被CPU执⾏;④挂起态:RT_THREAD_SUSPEND,线程正在等待某个信号量、消息队列、、事件或被延时等情况,不在就绪列表;⑤关闭态:RT_THREAD_CLOSE,线程运⾏结束,等待系统回收资源。
线程的状态是不断转换的,⽤⼀张图来表⽰线程状态迁移:4.建⽴线程实例下⾯介绍⼀下线程创建的步骤,以下发⽣在main.c源⽂件中。
(1)定义线程控制块和声明线程函数static rt_thread_t example_thread = RT_NULL; //初始化线程控制块static void example_thread_entry(void *parameter); //线程函数声明(2)在main函数中创建线程example_thread = //线程控制块指针rt_thread_create("example", //线程名字example_thread_entry, //线程⼊⼝函数RT_NULL, //线程⼊⼝函数参数512, //线程栈⼤⼩3, //线程的优先级20); //线程时间⽚(单位tick)// 启动线程,开启调度if(example_thread != RT_NULL)rt_thread_startup(example_thread);elsereturn -1;(3)编写线程函数内容static void example_thread_entry(void *parameter){while(1){ //⽆限循环,该线程不会被系统删除//若⽆这个循环,则线程运⾏完毕后会被系统⾃动删除// ....⽤户⾃定义线程操作}}通过以上三个步骤,就能建⽴可运⾏的线程了。
Rt-thread:任务调度启动顺序:1 rtthread_startup进⾏对象初始化2 rt_application_init进⾏线程对象初始化rt_thread_create创建线程1 调⽤rt_object_allocate(RT_Object_Class_Thread,name);获取线程对象并创建线程(a) rt_object_get_information(type),根据type获取线程的对象实例。
查找⽅法是遍历rt_object_container并找到type能匹配上的。
Rt-thread中所有的对象都包含在object.c中的静态变量rt_object_container中static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] ={/* initialize object container - thread */{RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},#ifdef RT_USING_SEMAPHORE/* initialize object container - semaphore */{RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},#endif#ifdef RT_USING_MUTEX/* initialize object container - mutex */{RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},#endif#ifdef RT_USING_EVENT/* initialize object container - event */{RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},#endif#ifdef RT_USING_MAILBOX/* initialize object container - mailbox */{RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},#endif#ifdef RT_USING_MESSAGEQUEUE/* initialize object container - message queue */{RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(structrt_messagequeue)},#endif#ifdef RT_USING_MEMHEAP/* initialize object container - memory heap */{RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},#endif#ifdef RT_USING_MEMPOOL/* initialize object container - memory pool */{RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},#endif#ifdef RT_USING_DEVICE/* initialize object container - device */{RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},#endif/* initialize object container - timer */{RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},#ifdef RT_USING_MODULE/* initialize object container - module */{RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},#endif};(b) object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size); 根据该对象的object_size⼤⼩⽣成线程对象。
1. FreeRTOS特点:免费嵌入式软件源代码,设计小巧,简单易用,有许多支持架构的免费开发工具,可移植性非常好的源代码结构,主要用C.任务调度:对任务优先级分配没有限制 - 可以为多个实时任务分配相同的优先级,0优先级为最低的优先级。
固定优先级抢占式,调度器保证总是在所有可运行的任务中训责具有最高优先级的任务;被选中的任务具有不止一个任务,调度器会让这些任务轮流运行。
对可创建的实时任务数量没有软件限制。
对于优先级反转,采用优先级继承机制。
支持实时任务和协同程序。
任务运行要在主函数中启动调度器,任务在主函数或其他任务中声明拥有心跳中断钩子函数允许调度器的关闭与开启、中断的开关通讯机制:队列、二进制信号量、计数信号量、递归信号量和互斥体,用于任务之间的通信和同步,或实时任务和中断之间(没有邮箱机制)创新事件组(或事件标志)实施。
具有优先级继承的互斥体。
信号量和队列没有控制块,使用前要在主函数中定义中断服务程序要在主函数中声明,如:声明:_dos_setvect(0x82,vExampleInterruptHandler)而在任务中要用_asm{int 0x82}进入中断。
2.UC/0S特点:μC/OS-II是一种完整的、可移植的、可固化的、可剪裁的占先式实时多任务内核,绝大多数代码用c语言编写,与微处理器密切相关的部分用汇编语言编写,不过开源收费任务调度:对任务优先级分配有限制 - 一个优先级只能有一个任务,通常最低的两个优先级被赋给空闲任务和统计任务,0优先级为最高的优先级。
固定优先级抢占式,调度器保证总是在所有可运行的任务中训责具有最高优先级的任务;不支持时间片轮询机制。
因为优先级不能相同,所以不支持优先级继承机制,UC/0S在互斥信号量中引用了优先级提升的方法。
任务运行不需要在主函数中启动调度器,任务在主函数或其他任务中创建允许调度器的关闭与开启、中断的开关通讯机制:二进制信号量、计数信号量、消息邮箱、消息队列、事件标志组用于任务之间的通信和同步,或实时任务和中断之间3.RT-Thread特点:RT-Thread是一款来自中国的开源嵌入式实时操作系统,除了类似FreeRTOS和UCOS的实时操作系统内核外,也包括一系列应用组件和驱动框架,遵循GPLv2+许可证,实时操作系统内核及所有开源组件可以免费在商业产品中使用,不需要公布应用源码,没有任何潜在商业风险。
rt-thread原理RT-Thread是一个基于实时操作系统(RTOS)的开源项目,它提供了一个可嵌入式的实时操作系统内核,适用于各种微处理器、微控制器和DSP等嵌入式设备。
RT-Thread的设计目标是为嵌入式系统提供高效、稳定和可靠的实时运行环境。
1. RT-Thread内核架构RT-Thread内核采用了多线程模型,支持多任务并发执行。
它的内核架构主要由以下几个组件组成:a. 调度器:RT-Thread内核提供了一个简单的优先级调度器,用于管理多个任务的执行顺序。
调度器基于优先级对任务进行调度,高优先级的任务优先执行。
b. 任务管理:RT-Thread内核提供了任务管理功能,可以创建、删除、挂起和恢复任务。
每个任务都有一个独立的栈空间和优先级,可以通过任务切换实现多任务并发执行。
c. 时钟管理:RT-Thread内核提供了时钟管理功能,可以定时触发任务的执行。
通过时钟管理,可以实现定时任务和延时功能。
d. 中断管理:RT-Thread内核提供了中断管理功能,可以处理外部中断和软件中断。
中断处理函数可以在中断发生时被调用,执行特定的操作。
e. 内存管理:RT-Thread内核提供了内存管理功能,可以动态分配和释放内存。
内存管理模块可以有效地管理系统资源,提高系统的稳定性和可靠性。
f. 设备驱动:RT-Thread内核提供了设备驱动框架,支持各种外设的驱动。
设备驱动模块可以与硬件进行交互,实现设备的读写操作。
2. RT-Thread应用RT-Thread可以用于各种嵌入式系统的开发,包括通信设备、工业控制、医疗设备、智能家居等。
它具有以下几个特点:a. 灵活性:RT-Thread内核具有可配置的特性,可以根据具体需求进行定制。
用户可以选择需要的功能模块,以减小内核的体积和内存占用。
b. 可移植性:RT-Thread内核支持多种处理器架构和编译器,可以在不同的硬件平台上进行移植。
它提供了一套统一的API接口,方便应用程序的移植和开发。
RT-Thread--线程管理线程管理的功能特点RT-Thread系统中线程是调度的最⼩单位;线程分为:系统线程和⽤户线程,系统线程是由 RT-Thread 内核创建的线程,⽤户线程是由应⽤程序创建的线程,这两类线程都会从内核对象容器中分配线程对象,当线程被删除时,也会被从对象容器中删除RT-Thread 的线程调度器是抢占式的,主要的⼯作就是从就绪线程列表中查找最⾼优先级线程,保证最⾼优先级的线程能够被运⾏,最⾼优先级的任务⼀旦就绪,总能得到 CPU 的使⽤权。
当调度器调度线程切换时,先将当前线程上下⽂保存起来,当再切回到这个线程时,线程调度器将该线程的上下⽂信息恢复。
线程的⼯作机制线程控制块线程控制块由结构体 struct rt_thread 表⽰,线程控制块是操作系统⽤于管理线程的⼀个数据结构,它会存放线程的⼀些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接⽤的链表结构,线程等待事件集合等/*** Thread structure*/struct rt_thread{/* rt object */char name[RT_NAME_MAX]; /**< the name of thread */rt_uint8_t type; /**< type of object */rt_uint8_t flags; /**< thread's flags */#ifdef RT_USING_MODULEvoid *module_id; /**< id of application module */#endifrt_list_t list; /**< the object list */rt_list_t tlist; /**< the thread list *//* stack point and entry */void *sp; /**< stack point */void *entry; /**< entry */void *parameter; /**< parameter */void *stack_addr; /**< stack address */rt_uint32_t stack_size; /**< stack size *//* error code */rt_err_t error; /**< error code */rt_uint8_t stat; /**< thread status *//* priority */rt_uint8_t current_priority; /**< current priority */rt_uint8_t init_priority; /**< initialized priority */#if RT_THREAD_PRIORITY_MAX > 32rt_uint8_t number;rt_uint8_t high_mask;#endifrt_uint32_t number_mask;#if defined(RT_USING_EVENT)/* thread event */rt_uint32_t event_set;rt_uint8_t event_info;#endif#if defined(RT_USING_SIGNALS)rt_sigset_t sig_pending; /**< the pending signals */rt_sigset_t sig_mask; /**< the mask bits of signal */void *sig_ret; /**< the return stack pointer from signal */rt_sighandler_t *sig_vectors; /**< vectors of signal handler */void *si_list; /**< the signal infor list */#endifrt_ubase_t init_tick; /**< thread's initialized tick */rt_ubase_t remaining_tick; /**< remaining tick */struct rt_timer thread_timer; /**< built-in thread timer */void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit *//* light weight process if present */#ifdef RT_USING_LWPvoid *lwp;#endifrt_uint32_t user_data; /**< private user data beyond this thread */};typedef struct rt_thread *rt_thread_t;nit_priority 是线程创建时指定的线程优先级,在线程运⾏过程当中是不会被改变的(除⾮⽤户执⾏线程控制函数进⾏⼿动调整线程优先级);cleanup 会在线程退出时,被空闲线程回调⼀次以执⾏⽤户设置的清理现场等⼯作;user_data 可由⽤户挂接⼀些数据信息到线程控制块中,以提供类似线程私有数据的实现。
1 前言 rt-thread可以采用软件定时器或硬件定时器来实现定时器管理的,所谓软件定时器是指由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。而硬件定时器是芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。软件定时器的精度取决于它使用的硬件定时器精度。而rt-thread操作系统在默认情况下是采用的硬件定时器的方式,用户可以通过修改宏定义#ifdef RT_USING_TIMER_SOFT来修改采用哪种。 2 rt-thread的定时器的基本工作原理
在RT-Thread定时器模块维护两个重要的全局变量,一个是当前系统的时间rt_tick(当硬件定时器中断来临时,它将加1),另一个是定时器链表rt_timer_list,系统中新创建的定时期都会被以排序的方式插入到rt_timer_list(硬件定时器模式下使用)链表中,rt_timer_list的每个节点保留了一个定时器的信息,并且在这个节点加入链表时就计算好了产生时间到达时的时间点,即tick,在rt-thread系统中如果采用软件定时器模式,则存在一定时器线程rt_thread_timer_entry,不断获取当前TICK值并与定时器链表rt_timer_list上的定时器对比判断是否时间已到,一旦发现就调用对应的回调函数,即事件处理函数进行处理,而如果采用硬件定时器管理模式的话,则该检查过程放到系统时钟中断例程中进行处理,此时,是不存在定时器线程的。如下图:注:如果采用软件定时器软件定时器,则该定时器链表为rt_soft_timer_list。
3 源码分析 3.1 数据定义 [cpp] view plaincopyprint? 1. /** 2. * timer structure 3. */ 4. struct rt_timer 5. { 6. struct rt_object parent; //内核对象 7. 8. rt_list_t list; //链表节点 9. 10. void (*timeout_func)(void *parameter); //定时器超时例程 11. void *parameter; //定时器例程的传入参数 12. 13. rt_tick_t init_tick; //定时器的超时时间,即总共多长时间将产生超时事件 14. rt_tick_t timeout_tick; //定时器超时的时间点,即产生超时事件时那一该的时间点 15. }; 16. typedef struct rt_timer *rt_timer_t;
3.2 rt-thread的软件定时器模式 软件定时器线程初始化及启动: [cpp] view plaincopyprint?
1. /** 2. * @ingroup SystemInit 3. * 4. * This function will initialize system timer thread 5. */ 6. void rt_system_timer_thread_init(void) 7. { 8. #ifdef RT_USING_TIMER_SOFT//如果采用软件定时器管理模式,则启动定时器线程 9. rt_list_init(&rt_soft_timer_list);//初始化软件定时器链表 10. 11. /* start software timer thread */ 12. rt_thread_init(&timer_thread,//初始化软件定时器线程,并启动 13. "timer", 14. rt_thread_timer_entry, 15. RT_NULL, 16. &timer_thread_stack[0], 17. sizeof(timer_thread_stack), 18. RT_TIMER_THREAD_PRIO, 19. 10); 20. 21. /* startup */ 22. rt_thread_startup(&timer_thread); 23. #endif 24. }
软件定时器线程如下: [cpp] view plaincopyprint?
1. /* system timer thread entry */ 2. static void rt_thread_timer_entry(void *parameter) 3. { 4. rt_tick_t next_timeout; 5. 6. while (1) 7. { 8. /* get the next timeout tick */ 9. next_timeout = rt_timer_list_next_timeout(&rt_soft_timer_list);//得到软件定时器链表上的下一个定时器的超时时间点 10. if (next_timeout == RT_TICK_MAX)//如果超过范围,则挂起当前线程,继续线程调度 11. { 12. /* no software timer exist, suspend self. */ 13. rt_thread_suspend(rt_thread_self()); 14. rt_schedule(); 15. } 16. else 17. { 18. rt_tick_t current_tick; 19. 20. /* get current tick */ 21. current_tick = rt_tick_get();//获取当前时间点 22. 23. if ((next_timeout - current_tick) < RT_TICK_MAX/2)//离下个中断时间点还差些时候 24. { 25. /* get the delta timeout tick */ 26. next_timeout = next_timeout - current_tick;//计算还差多长时间 27. rt_thread_delay(next_timeout);//休眠一段时间 28. } 29. } 30. 31. /* lock scheduler */ 32. rt_enter_critical();//时间到,进入临界区 33. /* check software timer */ 34. rt_soft_timer_check();//检查是否该产生超时事件 35. /* unlock scheduler */ 36. rt_exit_critical();//退出临界区 37. } 38. }
检查是否产生中断函数rt_soft_timer_check函数如下定义: [cpp] view plaincopyprint?
1. /** 2. * This function will check timer list, if a timeout event happens, the 3. * corresponding timeout function will be invoked. 4. */ 5. void rt_soft_timer_check(void) 6. { 7. rt_tick_t current_tick; 8. rt_list_t *n; 9. struct rt_timer *t; 10. 11. RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n")); 12. 13. current_tick = rt_tick_get();//得到当前时间点 14. 15. for (n = rt_soft_timer_list.next; n != &(rt_soft_timer_list);)//得到下一定时器节点 16. { 17. t = rt_list_entry(n, struct rt_timer, list);//t指向rt_timer定时器 18. 19. /* 20. * It supposes that the new tick shall less than the half duration of 21. * tick max. 22. */ 23. if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)//如果当前的时间点超过定时器的超时时间点 24. { 25. RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook, (t));//使用钩子函数 26. 27. /* move node to the next */ 28. n = n->next;//指向下一定时器 29. 30. /* remove timer from timer list firstly */ 31. rt_list_remove(&(t->list));//移除当前定时器 32. 33. /* call timeout function */ 34. t->timeout_func(t->parameter);//产生定时器超时事件,调用对应处理函数 35. 36. /* re-get tick */ 37. current_tick = rt_tick_get();//再次获取当前时间点 38. 39. RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick)); 40. 41. if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&//如果当前定时器是周期性定时器,则将其再次按序放入软件定时器链表 42. (t->parent.flag & RT_TIMER_FLAG_ACTIVATED)) 43. { 44. /* start it */ 45. t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;//置标志为非激活状态 46. rt_timer_start(t);//再次将定时器t放入软件定时器链表末尾 47. }