更新中---韦东山FreeRTOS快速上手

FreeRTOS

内存管理

内核对象:task,queue,信号量,event group

Head_1

它只实现了pvPortMalloc,没有实现vPortFree。
如果不需要删除的内核对象,可以使用head_1:

  1. 实现最简单
  2. 没有碎片化
  3. 一些要求非常严格的系统里,不允许使用动态内存,就可以使用head_1

Head_2

heap_2 也是在数组上分配内存,跟Heap_1不一样地方在于:
1.Heap_2使用最佳匹配算法(best fit)来分配内存。

缺点碎片化 , 与Heap_4相比,Heap_2不会合并相邻的空闲内存,所以有严重的碎片化的问题

但是,如果申请,分配内存是大小总是相同的,这类情境下Heap_2没有碎片化的问题。
在这里插入图片描述

heap_3

heap_3 使用标准C库里的malloc ,free 函数,所以堆大小由链接器的配置决定。
与C库里的malloc,free函数并非线程安全的,Heap_3中先暂停FreeRTOS的调度器,再去调用这些函数,使用这种方法实现了线程安全。

heap_4

跟Heap_1、Heap_2一样,Heap_4 也是使用大数组分配内存。
Heap_4 使用首次适应算法(first fit)来分配内存,它还会把相邻的空闲内存合并一个更多的空闲内存,有助于较小内存的碎片问题。

在这里插入图片描述

首次适应(First-Fit)

定义:首次适应策略从内存的低地址开始,顺序扫描空闲块表,找到第一个大小足够满足请求的空闲块。

最佳适应(best-Fit)

定义:最佳适应策略会扫描整个空闲块表,找到最小的且能满足请求的空闲块,即最接近请求大小的空闲块。

Heap_5

Heap_5 分配内存、释放内存的算法跟 Heap_4 是一样的。
相比于 Heap_4,Heap_5 并不局限于管理一个大数组:它可以管理多块、分隔开的内存

任务管理

任务状态

running 和 not running 状态
ready就绪,随时可以运行
blocked阻塞,卡住了,母亲在等待同事回信息。
suspended:挂起,同事废话太多,不管他了。

优先级

我工作生活兼顾,喂饭、回消息优先级一样,轮流做。
我忙里偷闲:还有空闲任务,休息一下
厨房着火了,什么都别说了,先灭火,优先级更高。

栈(Stack)

 喂小孩时,我要记得上一口喂了米饭,这口要喂青菜了
 回信息时,我要记得刚才聊的是啥
 做不同的任务,这些细节不一样
 对于人来说,当然是记在脑子里
 对于程序,是记在栈里
 每个任务有自己的

事件驱动

孩子吃饭太慢了:先休息一会,等他咽下去了,等他提醒我了,再喂下一口

协调式调度(Co-operative Scheduling)

在给同事回消息

同事说:好了,你先去给小孩喂一口饭吧,你才能离开
同事不放你走,即使孩子哭了你也不能走

你好不容易可以给孩子喂饭了
孩子说:好了,妈妈你去处理一下工作吧
孩子不放你走,即使同事连发新消息你也不能走。

任务的删除

删除任务是使用的函数如下:

void  vTaskDelete(TaskHandle_t xTaskToDelete )

pvTaskCode ———— 任务句柄,使用 xTaskCreate 创建任务时可以得到一个句柄,也可传入 NULL,这表示删除自己.。

怎么删除任务?
自杀:vTaskDelete(NULL)
被杀: 别的任务执行vTaskDelete(pvTaskCode),pvTaskCode 是自己的句柄。
杀人:执行 vTaskDelete(pvTaskCode),pvTaskCode 是别的任务的句柄

在学习调度方法之前,你只要初略地知道
FreeRTOS会确保最高优先级,可运行的任务,马上就能执行。
对于相同优先级的,可运行的任务,轮流执行。

3.4 任务状态

非运行状态

  1. 阻塞状态(Blocked)
  2. 暂停状态(Suspended)
  3. 就绪状态(Ready)

在日常生活例子中,母亲在电脑前跟同事沟通时,如果同事一直没回复,那么母亲的工作被卡住了、被堵住了、处于阻塞状态(Blocked)。 重点在于:母亲在等待。

在实际产品中,我们不会让一个任务一直运行,而是使用"事件驱动"的方法让它运行:

  1. 任务要等待某个事件,事件发生后它才能运行。
  2. 在等待时间过程中,它消耗CPU资源
  3. 在等待事件的过程中,这个任务就处于阻塞状态。

在阻塞的状态的任务,它可以等待两种类型的事件:
时间相关的事件
1.可以等待一段时间,我等2分钟
2. 也可以一直等待,直到某个绝对时间: 我等到下午3点。
同步事件:这事件由别的任务,或者是中断程序产生。
例子:任务A 等待任务B 给它发送数据
例子: 任务A 等待用户按下按键。

同步事件的来源有很多
1.队列(queue)
2.二进制信号量
3.计数信号量
4.互斥量
5.递归互斥量,递归锁
6.事件组
7.任务通知

暂停状态(Suspended)

在日常生活的例子中,母亲正在电脑前跟同时沟通,母亲可以暂停。

  1. 好烦啊,我暂停一会。
  2. 领导说:你暂停一会。

FreeRTOS 中的任务也可以进入暂停状态,唯一的方法是通过vTaskSuspend 函数。函数原型如下:

void vTaskSuspend( TaskHandle_t xTaskToSuspend );

参数xTaskToSuspend 表示要暂停的任务,如果为NULL,表示暂停自己。

要退出暂停,只能由别人来操作:
1.别的任务调用:vTaskResume
2.中断函数调用:xTaskResumeFromISR
实际开发中,暂停状态用的不多

就绪状态(Ready)
这个任务完全准备好了,随时可以运行,只是还轮不到它。这时,它就处于就绪状态。

在这里插入图片描述

Delay 函数
两个Delay函数
  1. vTaskDelay: 至少等待指定个数的Tick Interrupt才能变为就绪状态。
  2. vTaskDelayUntil:等待到指定的绝对时刻,才能变为就绪状态

在这里插入图片描述

在这里插入图片描述

空闲任务及其钩子函数
介绍

空闲任务(Idle 任务)的作用: 释放被删除的任务的内存。

为什么必须由空闲任务?
它的任务都是事件驱动的:平时大部分时间处于阻塞状态。有可能我们自己创建所有任务都无法执行,但是调度器必须能找到一个可以运行的任务:所以我们要提供空闲任务。 在使用vTaskStartScheduler()函数来创建、启动调度器时,这个函数内部会创建空闲任务:
1.空闲任务优先级为0:他不能阻碍用户任务运行。
2.空闲任务要么处于就绪态,要么处于运行态,永远不会阻塞。

空闲任务的优先级为0,这意味着一旦某个用户的任务变为就绪状态,那么空闲任务马上被切换出去,让这个用户任务运行。在这种情况下,我们说用户任务“抢占”(Pre-empt)了空闲任务,这是由调度器实现的。

要注意的是,如果使用vTaskDelete()来删除任务,那么你就要确保空闲任务有机会执行,否则就无法释放被删除任务的内存。

我们可以添加一个空闲任务的钩子函数(Idle Task Hook Functions),空闲任务的循环每执行一次,就会调用一次钩子函数,钩子函数的作用有这些。

  1. 执行一些低优先级的,后台的,需要连续执行的函数。
  2. 测量系统的空闲时间:空闲任务被执行就意味着所有的高优先级都停止了,所以测量空闲任务占据的时间,就可以算出处理器的占用率。
  3. 让系统进入省电模式:空闲任务能被执行就意味着没有重要的事情要做,当然可以进入省电模式了
  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值