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 可以创建任务、管理任务、管理内存、管理网络连接等。
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. }