FreeRTOS笔记

学习FreeRTOS操作系统的笔记再翻出来看看。内容来源 正点原子,侵权请告知,立即删除。

  1. 前后台系统和RTOS系统


  •  实时操作系统又分为硬实时和软实时。硬实时就是要求在规定的时间内必须完成操作,硬实时系统不允许超时,在软实时里面处理过程超时的后果就没有那么严格。

  • RTOS操作系统的核心内容在于:实时内核

  • 用户给每个任务分配一个任务优先级,任务调度器可以根据此优先级来决定下一刻应该运行哪个任务

  • 特点:

           (1) FreeRTOS免费

           (2)WIFI蓝牙等这些带协议栈的芯片模块都是用FreeRTOS

           (3)很多厂商用FreeRTOS做公司的操作系统

           (4) 简单,文件数量少

           (5)内核支持抢占式、合作式、时间片调度

           (6)提供了一个用于低功耗的Tickless模式

           (7)系统的组件在创建时可以选择动态或者静态的RAM

      2. FreeRTOS在STM32F429上的移植


  • FPU: 浮点单元支持单精度浮点计算、一些转换操作、存储器访问和寄存器组间的数据传输。对于没有浮点运算单元的MCU(51、AVR),CPU是按照IEEE-754标准的算法来完成运算,消耗资源多,运算时间长。对于有FPU协处理器,浮点运算是由相关指令完成。现在有硬件浮点运算能力的主要有高端DSP,通用CPU和高级的ARM+DSP处理器等。 STM32F4带有32单精度硬件FPU支持浮点指令集。相比Cortex-M3、Cortex-M0等高出数十倍甚至上百倍的运算性能。STM32M7/H7及以上处理器带有双精度硬件FPU。FPU单元是芯片上一个独立于CPU处理的浮点运算单元,整个单元可以被使能和关闭。

     3.  FreeRTOS系统配置


  • C标准库中的 assert()函数,调试代码的时候可以检查传入的参数是否合理,FreeRTOS内核中的关键点都会调用configASSERT(x),当x为0的时候说明有错误发生。在正点原子的程序中,configASSERT(x)会调用vAssertCalled()函数,该函数需要用户自己定义。发生错误可以通过串口或者LCD屏显示错误的文件和行号

  • 每个任务都有一个任务堆栈。如果使用xTaskCreate()创建任务,堆栈是自动从FreeRTOS的堆中分配,堆栈大小由函数xTaskCreate()的参数usStackDepth来决定的。如果使用xTaskCreateStatic()来创建,堆栈由用户设置,参数pxStackBuffer为任务堆栈,一般是一个数组。

  • 堆栈溢出是导致应用程序不稳定的主要因素。FreeRTOS提供两种机制来帮助检测和调试堆栈溢出,这两种机制都需要设置宏configCHECK_FOR_STACK_OVERFLOW不为0。同时需要用户提供一个钩子函数(回调函数),当内核检测到堆栈溢出时会调用这个钩子函数。设置这个检测会增加上下文切换的开销,建议在调试的时候使用。

  • 优先级设置好后,注意0是最低优先级,在uC/OS中0是最高优先级。

      4.  FreeRTOS中断配置和临界段


  •  NVIC: 嵌套向量中断控制器。SCB: 系统控制块。SCS: 系统控制空间

  • 中断嵌套:高优先级的中断(优先级编号小)首先得到响应,高优先级的中断可以抢占低优先级的中断。

  • 优先级分组:MSB所在的位段(左边的)对应抢占式优先级,LSB所在的位段(右边的)对应亚优先级。

  • FreeRTOS的中断配置没有处理亚优先级这种情况,只能配置为组4,直接就16个优先级,使用简单

  • 使用PRIMASK寄存器来暂时屏蔽所有的中断来执行一些对时序要求严格的任务。FreeRTOS的开关中断是操作BASEPRI寄存器来实现的,它可以关闭低于某个阈值的中断,高于这个阈值的中断就不会被关闭。

  • 临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程不能被打断。FreeRTOS在进入临界代码的时候需要关闭中断,当处理完临界代码以后再打开中断。分为任务级和中断级临界代码保护,后者用于中断服务程序中的临界代码保护。

      5. FreeRTOS任务基础知识


  • 裸机程序中利用while(1)和中断形式进行程序设计,相对于多任务系统而言,这个是单任务系统,也称为前后台系统,中断服务函数作为前台程序,大循环while(1)作为后台程序。前后台系统的实时性差,前后台系统各个任务都是排队等着轮流执行,相当于所有的任务的优先级都是一样的

  • 多任务系统中,并不是说同一时刻一起执行多个任务,而是每个任务执行的时间很短,导致看起来像是同一时刻执行了很多任务一样。

  • 哪个任务先执行,哪个任务后执行,完成这个功能的东西在RTOS系统中叫做任务调度器。FreeRTOS是一个抢占式的实时多任务系统,其任务调度器也是抢占式的。

  • 任务不需要了解RTOS调度器的具体行为,RTOS调度器的职责是确保一个任务执行的时候上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。为了做到这一点,每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行。

  • 任务特性:简单;没有使用限制;支持抢占;支持优先级;每个任务都拥有堆栈导致了RAM使用量增大;如果使用抢占的话必须仔细的考虑重入的问题。

  • FreeRTOS中应用既可以使用任务,也可以使用协程,协程是为那些资源很少的MCU准备的,开销很小,但FreeRTOS官方不维护更新了,只需了解。

  • 任务状态:

           (1) 运行态:当一个任务正在运行时,那么说这个任务处于运行态,处于运行态的任务就是当前正在使用处理器的任务。

           (2)就绪态:处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务,但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行。

           (3)阻塞态:如果说一个任务当前正在等待某个外部事件的话就说它处于阻塞态。比如执行 vTaskDelay()函数。任务在等待队列、信号量、事件组、通知或者互斥信号量的时候也会进行阻塞态。任务进入阻塞态会有一个超时事件,当过了这个超时事件任务就会推出阻塞态,即使所等待的事件还没来临。

           (4)挂起态:像阻塞态一样,任务进入挂起态以后也不能被调度器用进入运行态,但是进入挂起态的任务没有超时时间。

  FreeRTOS笔记_第1张图片

  • 优先级数字越低表示任务的优先级越低,0的优先级最低,空闲任务的优先级最低,为0。处于就绪状态的最高优先级的任务才会运行。

  • 任务函数本质也是函数,函数名可以根据实际情况自己命名,但返回类型一定是void类型,也就是无返回值,而且任务的参数也是void指针类型的。

  • 任务的具体执行过程是一个大循环,用while(1)或者for( ; ; )

  • 任务函数一般不允许跳出循环,如果一定要跳出循环的话在跳出循环后一定要调用函数vTaskDelete(NULL)删除此任务。

  • 任务堆栈需要用户自己定义,需要指定堆栈大小。其中StackType_t类型是4个字节,那任务的实际堆栈大小就应该是我们所定义的4倍。              

      6. FreeRTOS任务相关API函数


  • xTaskCreate()函数用来创建一个任务,任务需要RAM来保存与任务有关的状态信息(任务控制块),任务也需要一定的RAM来作为任务堆栈。所需要的RAM自动从FreeRTOS的堆中分配。

  • 删除一个用函数xTaskCreate()或者xTaskCreateStatic()创建的任务,被删除的任务不再存在,也就是说再也不会进入运行态。任务被删除后就不能再使用此任务的句柄,如果该任务是使用函数xTaskCreate()创建的,那么在此任务被删除以后此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数vTaskDelete()删除任务后必须给空闲任务一定的运行时间。

  • 只用哪些由内核分配给任务的内存才会在任务被删除后自动的释放掉,用户分配任务的内存需要用户自行释放掉,否则会导致内存泄漏

  • 有时候我们需要暂停某个任务的运行,过一段时间再重新运行,用任务挂起和恢复。如果用任务删除和重建的方法会导致数据的丢失。

  • vTaskSuspend()函数将某个任务设置为挂起态,进入挂起态的任务永远都不会进入运行状态。退出挂起态的唯一方法就是调用任务恢复函数vTaskResume()或者vTaskResumeFromISR()。

     7. FreeRTOS列表和列表项


  • 列表是FreeRTOS中的一个数据结构,概念上和链表有点类似,列表被用来跟踪FreeRTOS中的任务。

  • 列表项就是存放在列表中的项目,FreeRTOS提供了两种列表项:列表项和迷你列表项。

  • pvOwner记录此列表项归谁所有,pvContainer用来记录此列表项归哪个列表。TCB_t中有两个变量xStateListItem和xEventListItem,这两个变量类型就是ListItem_t,也就是说这两个成员变量都是列表项。以xStateListItem为例,当创建一个任务以后xStateListItem的pvOwner变量就指向这个任务的任务控制块,表示xStateListItem属于此任务。当任务处于就绪态时,xStateListItem的变量pvContainer就指向就绪列表,表明此列表项在就绪列表中。

  • 迷你列表项比列表项少几个成员变量,有时候可以避免内存浪费。

  • 新创建或者定义的列表需要对其做初始化处理,列表的初始化其实就是初始化列表结构体List_t中的各个成员变量。同列表一样,列表项在使用的时候也需要初始化。列表项要根据实际使用情况来初始化。

  • 列表项的插入操作通过函数vListInser()来完成,函数的参数pxList决定了列表项要插入哪个列表中,pxNewListItem决定了要插入的列表项,要插入的位置由列表项中成员变量xItemValue来决定。列表项的插入根据xItemValue的值按照升序的方式排列。

  • 列表项的删除只是将指定的列表项从列表中删除掉,并不会将这个列表项的内存给释放掉,如果这个列表项是动态分配内存的话。

       8. FreeRTOS调度器开启和任务相关函数详解


  • 涉及较多寄存器和《权威指南》内容,后面需要深入了解FreeRTOS再看

 

       9. FreeRTOS任务切换


  • RTOS系统的核心是任务管理,而任务管理的核心是任务切换,任务切换决定了任务的执行顺序,任务切换效率的高低也决定了一款系统的系统。

  • PenSV(可挂起的系统调用)异常对OS操作非常重要,其优先级可以通过编程设置。与SVC异常不同,它是不精确的,因此它的挂起状态可在更高优先级异常处理内设置,且会在高优先级处理完成后执行。利用该特性,若将PenSV设置为最低的异常优先级,可以让PenSV异常处理在所有其他中断处理完成后执行,这对于上下文切换非常有用,也是各种OS设计中的关键。

  • 上下文切换被触发的场合可以是:执行一个系统调用系统滴答定时器(SysTick)中断

  • 在OS中,任务调度器决定是否应该执行上下文切换。

  • 若中断请求(IRQ)在SysTick异常前产生,则SysTick异常可能会抢占IRQ的处理,在这种情况下,OS不应该执行上下文切换,否则中断请求IRQ处理会被延迟——这是不被允许的。对于Cortex-M3和Cortex-M4处理器,当存在活跃的异常服务时,设计默认不允许返回到线程模式,若存在活跃中断服务,且OS视图返回线程模式,则将触发用法fault。为了解决这个问题,PenSV异常将上下文切换请求延迟到所有其他IRQ处理器都已经完成后,此时需要将PenSV设置为最低优先级。若OS需要执行上下文切换,他会设置PenSV的挂起状态,并在PenSV异常内执行上下文切换。

  • FreeRTOS系统的任务切换最终都是在PenSV中断服务函数中完成的,uc/OS也是在PenSV中断中完成任务切换的。

  • 执行系统调用就是执行FreeRTOS系统提供的API函数

  • 涉及较多寄存器和源码内容,后面需要再深入了解

       10. FreeRTOS系统内核控制函数


  • 这一章都是简单介绍函数,用到的时候再查

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(学习笔记)