![](https://img-blog.csdnimg.cn/20201014180756926.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
FreeRTOS
文章平均质量分 93
light_2025
Looking back, there is no regret !
展开
-
FreeRTOS_内存管理
如果此时有个应用需要 50B 的内存,那么它可以从两个地方来获取到,一个是最前面的还没被分配过的剩余内存块,另一个就是刚刚释放出来的 80B 的内存块。heap_2 不会把释放的内存块合并成一个大块,这样有一个缺点,随着不断的申请内存,内存堆就会被分为很多个大小不一的内存(块),也就是会导致内存碎片!任务会不断的获取按键情况,当检测到 KEY_UP 按下的时候就会申请内存,当 KEY0 按下以后就会使用申请到的内存,如果检测到 KEY1 按下的话就会释放申请到的内存。原创 2023-11-09 20:15:55 · 254 阅读 · 0 评论 -
FreeRTOS_空闲任务
空闲任务还有另外一个重要的职责,如果某个任务要调用函数 vTaskDelete() 删除自身,那么这个任务的任务控制块 TCB 和任务堆栈等这些由 FreeRTOS 系统自动分配的内存需要在空闲任务中释放掉,如果删除的是别的任务那么相应的内存就会被直接释放掉,不需要在空闲任务中释放。顾名思义,空闲任务就是处理器空闲的时候去运行的一个任务,当系统中没有其他就绪任务的时候空闲任务就会开始运行,空闲任务最重要的作用就是让处理器在无事可做的时候找点事做,防止处理器无聊,因此,空闲任务的优先级必然是最低的。原创 2023-11-08 21:50:41 · 576 阅读 · 0 评论 -
FreeRTOS_低功耗Tickless模式
如果处理器在进入低功耗模式之前能够获取到还有多长时间运行下一个任务那么问题就迎刃而解了,我们只需要设置一个定时器,定时器的定时周期设置为这个时间值就可以了,定时时间到了以后产生定时器中断,处理器就从低功耗模式中唤醒了。一般的简单应用中处理器大量的时间都在处理空闲任务,所以我们就可以考虑当处理器处理空闲任务的时候就进入低功耗模式,当需要处理应用层代码的时候就将处理器从低功耗模式中唤醒。很多 MCU 都有相应的低功耗模式,以此来降低设备运行时的功耗,进行裸机开发的时候就可以使用这些低功耗模式。原创 2023-11-07 19:59:01 · 511 阅读 · 0 评论 -
FreeRTOS_任务通知
当任务通知用于替代二值信号量的时候任务通知值就会代替信号量值,函数 ulTaskNotifyTake() 就可以代替信号量获取函数 xSemaphoreTake(),函数 ulTaskNotifyTake() 的参数 xClearCountOnExit 设置为 pdTRUE。pxHigherPriorityTaskWoken: 记退出此函数以后是否进行任务切换,这个变量的值函数会自动设置,用户不用进行设置,用户只需要提供一个变量来保存这个值就可以了。原创 2023-11-06 20:01:15 · 382 阅读 · 0 评论 -
FreeRTOS_事件标志组
由于内部处理的原因,事件标志组可用的 bit 数取决于 configUSE_16_BIT_TICKS,当 configUSE_16_BIT_TICKS 为 1 的时候事件标志组有 8 个可用的位(bit 0 ~ bit 7),当 configUSE_16_BIT_TICKS 为 0 的时候事件标志组有 24 个可用的位(bit 0 ~ bit 23)。实验还创建了一个事件标志组:EventGroupHandler,实验中用到了这个事件标志组的三个事件位,分别位 bit0,bit1 和 bit2。原创 2023-11-04 21:56:35 · 433 阅读 · 0 评论 -
FreeRTOS_软件定时器
MCU 自带的定时器属于硬件定时器,不同的 MCU 其硬件定时器数量不同,因为要考虑成本的问题。如果定时器服务任务的优先级设置的高的话,定时器命令队列中的命令和定时器回调函数就会及时的得到处理。定时器 AutoReloadTimer_Handle 的定时器周期为 1000 个时钟节拍(1s),定时器 OneShotTimer_Handle 的定时器周期为 2000 个时钟节拍(2s)。由于定时器服务任务中会执行定时器的回调函数,因此任务堆栈的大小一定要根据定时器的回调函数来设置。原创 2023-11-03 15:58:01 · 406 阅读 · 0 评论 -
FreeRTOS_信号量之递归互斥信号量
一个任务使用函数 xSemaphoreTakeRecursive() 成功的获取了多少次递归互斥信号量就得使用函数 xSemaphoreGiveRecursive() 释放多少次!递归互斥信号量也有优先级继承的机制,所以当任务使用完递归互斥信号量以后一定要记得释放(如果不释放那么低优先级的任务的优先级将永远和高优先级任务保持一致)。已经获取了互斥信号量的任务就不能再次获取这个互斥信号量,但是递归互斥信号量不同,已经获取了递归互斥信号量的任务可以再次获取这个递归互斥信号量,而且次数不限。原创 2023-11-01 22:12:36 · 318 阅读 · 0 评论 -
FreeRTOS_信号量之互斥信号量
意思就是说:低优先级的任务获得互斥信号量,此时高优先级的任务无法访问获得互斥信号量,其他中等优先级的任务也无法获得互斥信号量,这样一来,低优先级任务就不能被中等优先级任务所打断,高优先级任务只需要等待低优先级任务释放互斥信号量即可,不用担心被其他的中等任务所打断;:低优先级任务正在使用互斥信号量,而高优先级任务请求使用互斥信号量,此时会临时的将低优先级任务的优先级提高到和高优先级任务一个层次,这时被提升上来的任务就不会被其他优先级任务所打断,最大程度保证高优先级任务尽快获得互斥信号量,提高系统的响应性能。原创 2023-11-01 20:54:29 · 801 阅读 · 0 评论 -
FreeRTOS_信号量之优先级翻转
综上所述,任务 H 的优先级实际上降到了任务 L 的优先级水平。由于任务 M 剥夺了任务 L 的 CPU 使用权,使得任务 H 的情况更加恶化,这样就相当于任务 M 的优先级高于了任务 H,导致优先级翻转。如果低优先级任务获取到了信号量,那么高优先级任务就会处于等待状态,但是,中等优先级任务可以打断低优先级任务而先于高优先级任务运行!(6)、任务 H 运行过程中也要使用任务 L 正在使用着的资源,由于该资源的信号量还被任务 L 占用着,任务 H 只能进入挂起状态,等待任务 L 释放该信号量。原创 2023-10-31 10:19:59 · 237 阅读 · 0 评论 -
FreeRTOS_信号量之计数型信号量
(1)、计数型信号量也是在队列的基础上实现的,所以需要调用函数 xQueueGenericCreate() 创建一个队列,队列长度为 uxMaxCount,队列项长度为 queueSEMAPHORE_QUEUE_ITEM_LENGTH (此宏为 0 ),队列的类型为 queueQUEUE_TYPE_COUNTING_SEMAPHORE,表示是个计数型信号量。另外一个任务获取信号量,当信号量获取成功以后就刷新 LCD 上指定区域的背景颜色,并且显示计数型信号量的值。当信号量值为 0 的时候说明没有资源了。原创 2023-10-31 09:31:04 · 180 阅读 · 0 评论 -
FreeRTOS_信号量之二值信号量
现在使用二值信号量就可以实现这样的功能,任务通过获取信号量来判断是否有网络数据,没有的话就进入阻塞态,而网络中断服务函数(大多数的网络外设都有中断功能,比如 STM32 的 MAC 专用 DMA 中断,通过中断可以判断是否接收到了数据)通过释放信号量来通知任务以太网外设接收到了网络数据,网络任务可以去提取处理了。具体的处理过程做成一个任务,这个任务会获取信号量,如果获取到信号量就说明中断发生了,那么就开始完成相应的处理,这么做的好处就是中断执行的时间非常短。,在这个案例中使用的就是计数型信号量。原创 2023-10-30 22:02:25 · 528 阅读 · 0 评论 -
FreeRTOS_队列
这三个函数都是用于向队列中发送消息的,这三个函数的本质都是宏,其中函数 xQueueSend() 和 xQueueSendToBack() 是一样的,都是后向入队,也就是将新的消息插入到队列的后面。此函数也是向队列发送数据的,当队列满了以后会覆写掉旧的数据,不管这个旧数据有没有被其他任务或中断取走。这里我们创建一个长度为 4 的队列,因为要传递的是 x 的值,而 x 是个 int 类型的变量,所以每条消息的长度就是 int 类型的长度,在 STM32 中就是 4 字节,即每条消息是 4 个字节的。原创 2023-10-22 11:25:24 · 191 阅读 · 0 评论 -
FreeRTOS_时间管理
在使用 FreeRTOS 的过程中我们通常会在一个任务函数中使用延时函数对这个任务延时,当执行延时函数的时候就会进行任务切换,并且此任务就会进入阻塞态,直到延时完成,任务重新进入就绪态。函数的第一个参数就是设置任务的阻塞时间,在之前,我们已经计算出了任务的下一次唤醒时间点了,那么任务还需要的阻塞时间就是下一次唤醒时间点 xTimeToWake 减去当前的时间 xConstTickCount。可以看出这个延时时间是相对于 pxPreviousWakeTime 的,也就是上一次任务被唤醒的时间点。原创 2023-07-04 17:13:05 · 1247 阅读 · 0 评论 -
FreeRTOS_其他任务API函数
在结构体 TaskStatus_t 中有个字段 usStackHighWaterMark 来保存自任务运行以来任务堆栈剩余的历史最小大小,这个值越小说明越接近堆栈溢出,但是计算这个值需要花费一点时间,所以我们可以通过将 xGetFreeStackSpace 设置为 pdFALSE 来跳过这个步骤,当设置为 pdTRUE 的时候就会检查堆栈的历史剩余最小值。,每个任务都有它自己的指针数组来作为线程本地存储,使用这些线程本地存储可以用来在任务控制块中存储一些应用信息,这些信息只属于任务自己。原创 2023-07-03 16:47:02 · 269 阅读 · 0 评论 -
FreeRTOS_系统内核控制函数
在调用 vTaskSuspendAll() 函数后,任务调度器将停止进行任务切换,所有任务都会暂时被挂起。通过使用 taskENTER_CRITICAL_FROM_ISR() 和 taskEXIT_CRITICAL_FROM_ISR() 宏对中断服务程序中的临界区进行保护,可以确保在中断服务程序执行期间不被同优先级的中断或其他任务切换打断,从而保证了临界区代码的原子性和一致性。任务切换涉及保存当前任务的上下文,切换到下一个任务的上下文,并执行与任务切换相关的操作,如栈切换、任务状态更新等。原创 2023-07-03 16:46:50 · 1717 阅读 · 0 评论 -
FreeRTOS_任务切换
函数 prvAddTaskToReadyList() 也会修改这个值,也就是说将某个任务添加到就绪列表中的时候都会用 uxTopReadyPriority 来记录就绪列表中的最高优先级(也就是说这个变量始终记录着列表中的最高优先级),这样直接去看每个列表的最高优先级即可,从这个最高优先级开始判断,看看哪个列表不为空就说明哪个优先级有就绪的任务(因为一个列表代表着一个优先级,一个列表中所有任务的优先级都是一样的)。如果我们想要深入的了解 FreeRTOS 的运行过程,那么任务切换是必须要掌握的。原创 2023-07-03 16:46:23 · 1773 阅读 · 0 评论 -
FreeRTOS_调度器开启和任务相关函数详解
在之前的学习过程中,已经学习了 FreeRTOS 的任务创建和删除,挂起和恢复等基本操作,并且也学习了分析 FreeRTOS 源码所必须掌握的知识:列表和列表项。但是深究其过程,任务究竟是如何被创建、删除、挂起和恢复的?以及系统是如何被启动的?这些我们还并不了解,一个操作系统最核心的内容就是多任务管理,所以我们非常有必要去学习一下 FreeRTOS 的任务创建、删除、挂起、恢复和系统启动等。 在学习调度器开启过程之前,我们先来学习以下 ARM 的相关汇编指令。汇编语言:基本语法原创 2023-06-29 21:39:57 · 1290 阅读 · 0 评论 -
FreeRTOS_列表和列表项
列表的索引指针 pxIndex 还是指向列表项 1,其地址为 0x200000cc,列表的最后一个列表项的后继指针应该指向列表项 2 ,其地址也就是 0x200000e0,列表项 2 的后继指针应该指向列表项 1,其地址为 0x20000cc,列表项 1 的后继指针应该指向列表项 3 ,其地址为0x200000f4,列表项 3 的后继指针应该指向 xListEnd,其地址为 0x200000e0;此时列表的最后一个列表项和列表项 1 、列表项 2 以及 列表项 3 形成环形结构。原创 2023-06-27 16:16:07 · 824 阅读 · 0 评论 -
FreeRTOS_任务相关API函数
其他任务的创建就放在开始任务的任务函数中,由于开始任务的职责就是创建其他应用任务和信号量、队列等这些内核对象的,所以它只需要执行一次,当这些东西创建完成以后就可以删除掉开始任务了。只有那些由内核分配给任务的内存才会在任务被删除以后自动的释放掉,用户分配给任务的内存需要用户自行释放掉,比如某个任务中用户调用函数 pvPortMalloc() 分配了 500 字节的内存,那么在此任务被删除以后用户也必须调用函数 vPortFree() 将这 500 字节的内存释放掉,否则会导致内存泄露。原创 2023-06-07 20:38:41 · 841 阅读 · 0 评论 -
FreeRTOS_任务基础知识
(这就好比我们数学上的定积分是一样的,定积分处理的思想就是把无限长的曲线截成无限段,那么每一小段都可以近似的看做是直线,这样分别的处理每一小段进行叠加即可,多任务也是这样,大任务分成无限多的小任务,每一个小任务占用系统的时间很小,因此导致。要完成什么样的功能都是在这个任务函数中实现的。,任务调度器在进行任务切换的时候会将当前任务的现场(CPU寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。原创 2023-06-06 14:20:26 · 605 阅读 · 0 评论 -
FreeRTOS_从底层学习实时操作系统
首先后台会分布着多个任务,假设是 A B C D ,这个时候会通过调度器分配哪个任务开始运行,任务中也会存在优先级高的任务,优先级高的任务先执行,执行完以后会返回后台接着执行优先级低的任务,如果有中断,那么会优先执行中断;,即任务需要延时的时候,任务会放弃 CPU 的使用权,CPU 可以去干其他的事情,当任务延时时间到以后,任务重新获得 CPU 的使用权,任务继续运行,这样可以充分的利用 CPU 的资源,而不是让 CPU 干等着。(空闲任务是主函数在进行任务调度的时候创建的,它的任务优先级是最低的)。原创 2023-05-30 20:57:19 · 826 阅读 · 0 评论 -
FreeRTOS_中断配置和临界段
UCOS 中的临界区代码保护就是通过开关中断实现的(UCOSIII 也可以使用禁止任务调度的方法来实现临界区代码保护),而开关中断就是直接操作 PRIMASK 寄存器的,所以在 UCOS 中关闭中断的时候关闭了除复位、NMI 和 HardFault 以外的所有中断!FreeRTOS 的中断配置需要根据所使用的 MCU 来具体配置。上图中 PRIGROUP 就是优先级分组,他把优先级分为两个位段:MSB 所在的位段(左边的)对应抢占优先级,LSB 所在的位段(右边的)对应亚优先级,也就是子优先级。原创 2023-05-24 14:26:26 · 927 阅读 · 0 评论 -
FreeRTOS_系统配置
默认情况下,FreeRTOS 使用抢占式调度器,这意味着调度器永远都在执行已经就绪了的最高优先级任务,优先级相同的任务在时钟节拍中断中进行切换,当宏 configUSE_TIME_SLICING 为 0 的时候不会在时钟节拍中断中执行相同优先级任务的任务切换,默认情况下宏 configUSE_TIME_SLICING 为1。当为 1 的时候空闲任务就会为处于同等优先级的用户任务让出 CPU 使用权,除非没有就绪的用户任务,这样花费在空闲任务上的时间就会很少,但是这种方法也带了副作用。方法一的优点就是快!原创 2023-05-17 16:12:27 · 881 阅读 · 0 评论 -
FreeRTOS_移植和配置
RTOS 的任务调度器被设计为可预测的,而这正是嵌入式实时操作系统所需要的,实时环境中要求操作系统必须对某一个事件做出实时的响应,因此系统任务调度器的行为必须是可预测的。我们先看 FreeRTOS 的名字,可以分成两部分:Free 和 RTOS,Free 就是免费的、自由的、不受约束的意思,RTOS 全称是 Real Time Operating System,中文名就是。比如说 UCOS,FreeRTOS,RTX,RT - Thread 等这些都是 RTOS 类操作系统。紧接着要在原有的基础之上,修改。原创 2023-05-14 11:02:37 · 1821 阅读 · 0 评论