天天看点

FreeRTOS系统1. 任务队列中断管理资源管理内存管理错误排查

frertos是可剥夺内核

1. 任务

与线程类似

任务函数

void ARaskFunction(void *);

无返回值,功能在死循环中运行。

顶层任务状态

任务有两种状态,运行态,非运行态。只有调度器能进行切换。

任务优先级

调度器保证选择最好优先级的任务,并使其进入运行态。

心跳中断的周期性中断用于调度器在每一个任务结束时运行调度程序。

如果一个高优先级一个低优先级,在心跳中断下,总是执行高优先级的任务,低优先级的任务被饿死

非运行态

  1. 阻塞态:一个任务在等待某个事件,事件驱动任务。
  2. 挂起态:对调度器不可见,使用挂起vTaskSuspend()唤醒vTaskResume()
  3. 就绪态:未阻塞未挂起态

空闲任务

空闲任务是保证至少有一个任务处于运行态,拥有最低的优先级保证随时切出,不浪费资源。

钩子函数

通过(回调,hook)钩子,可以直接在空闲任务中添加应用程序相关功能

作用:1. 执行后台或需要不停处理的代码

2. 测试处理器处理裕量,了解系统有多少富裕的处理时间

3. 将处理器配置到低功耗模式

限制:不能阻塞挂起,任务被删除后,空闲任务负责回收资源,需要钩子尽快返回

任务的删除

只有内核为任务分配的空间才会被任务删除后自动回收,任务自己占用的资源需要自己显示释放。

调度算法

优先级抢占调度

优先级高的任务可以抢低任务的cpu资源

协作调度

使用一个纯粹的协作式调度器,任务永远不会被抢占。

混合调度方案

同步事件产生抢占,时间事件不行

队列

rtos中的任务的通信通过队列实现

队列的特性

数据存储 :可以存数据

可被多任务存取:队列是具有自己独立权限的内核对象,并不属于任务。

读/写队列时阻塞:队列为空,任务阻塞,当队列中有数据时,只会有一个任务解除阻塞优先级高且等待时间久的。会有阻塞超时时间,当超时后任务切换到就绪态。

使用队列传递复合数据类型

队列接收方需要知道数据来源,所以可以使用结构体进行数据传递

大型数据单元需要读写

当数据量大时,队列中为数据的指针,使用指针需要注意

  1. 指针指向的内存空间大的所有权必须明确
  2. 指针指向的内存空间必须有效

中断管理

通常采用中断方式检测事件

延迟中断处理

采用二值信号量同步

二值信号量深度为1的队列,跟pv原子操作类似,p获取,v给出

FreeRTOS系统1. 任务队列中断管理资源管理内存管理错误排查

当中断到来时,阻塞任务解除阻塞,这个任务称为延迟处理任务,以此实现中断与任务的同步。缺点中断以相对较慢的的频率发生。且只能存一个中断事件。

计数信号量

维持深度大于一的队列,二值信号量的升级版

事件计数

中断服务程序“给出give”信号量时,计数值加1.延时处理任务每处理一个任务就“获取take”一个信号量。计数器初始化为0

资源管理

计数值表示可用资源数目,任务获取资源计数值减一,任务利用完资源归还信号量,计数值加一。

初始化为资源总数。

资源管理

可重入函数:如果一个函数除了访问自己栈上的空间或内核寄存器上的空间,不访问其他数据

临界区与挂起调度器

临界区

rtos中的临界区与linux中的临界区一样都是指从获取锁开始,到执行完程序,释放锁。rtos没有锁这个概念,他是从宏定义taskENTER_CRITICAL开始到另一个宏结束,这里的宏跟锁的含义类似。

**不会被其他任务或中断打断。**简单的把所有中断关闭

挂起调度器

**只能保证不会被任务中断,中断使能。**不关中断

挂起调度器会停止上下文切换,当有中断发生时,这个中断请求被挂起,直到调度器被唤醒才会得到执行。唤醒调度器是一个相对较长的操作。

互斥量

跟Linux中的互斥量一样,持有者访问共享资源。互斥的信号量必须归还。同步的信号量使用后被丢弃。

优先级反转

问题:当高优先级没有互斥量的持有权而低优先级有时,会造成高优先级等待低优先级,此时中等有限级任务先执行。

FreeRTOS系统1. 任务队列中断管理资源管理内存管理错误排查

通过提前规划好资源解决

优先级继承

将持有互斥量的任务优先级提至最高,结束过后复原。

死锁

死锁是指任务运行时因为互斥量被相互占据,造成任务永久阻塞。例如两个任务在等待对方释放共享资源,

解决方法,在设计时就考虑这种风险。

守护任务

作用:可以防止优先级反转与死锁。

含义:是对某个资源有唯一所有权的任务。其他任务必须通过守护任务访问该资源。

内存管理

三种内存分配方案

heap_1

将内存堆空间看成一个简单的数组,当调用内存使用函数时,将数组分成更小的块。为每个创建的 任务在 堆上分配一个任务控制块与一个栈空间。只创建空间,不释放空间。

heap_2

  1. 采用一个最佳匹配算法来分配内存,并且支持内存释放。
  2. 会产生内存碎片
  3. 适用于重复创建与删除具有相同栈空间的应用程序。

    最佳匹配算法使用最接近请求大小的空间内存块。就像提前将蛋糕分成不同的块,有人吃就拿一块,只拿大于等于自己需求的块,有可能剩下碎块,剩下的就放下,没人吃就一直存放。

heap_3

简单调用标准函数,通过暂时挂起调度器是函数线程安全。

错误排查

在一个demo应用程序中增加一个小任务,程序崩溃

原因在堆上没有分配足够的内存

解决删除不需要的任务,或在配置中增加内存