Free RTOS

术语

GCC

GCC : GNU C Compiler .顾名思义,GUN C 编译器。自从面世以后逐渐发展,现在不仅支持C语言,还支持很多语言,如C++、Ada、Java等。因此GCC得意思被定义为GUN Compiler Collection,即GNU 编译器套件。 其中GNU是一个自由软件组织。

Measure comlexity of C source

分析C编程函数的复杂程度的计算方法。

MISRA coding standard guidelines

MISRA: THE Motor Industry Software reliability Assosition 汽车工业软件可靠性联会。位于英国的也有一个跨国汽车工业协会。其成员包括了大部分欧美汽车生产商。
这个标准包括了127条C语言编码标准。代码编写遵循度越高,代码越容易维护和管理。

堆(heap)和堆栈(stack)

FreeRTOS port 端口

定义:每种支持的编译器和处理器组合被认为是一个端口。FreeRTOS 自持很多种编译器和处理器。
每个端口使用一个定时器来生成定期的滴答中断。许多端口使用其他中断来管理执行任务切换。RTOS端口所需的中断由提供的RTOS端口源文件提供服务。

Thread

线程: 运算调度的最小单位。

钩子函数(hook结尾)

作用:定义一些操作,函数名称确定,只需要补全函数体。钩子函数由事件触发。函数指针指向钩子函数,调用钩子函数的过程,称为挂钩子。

C语言宏定义中##符

作用:连接。
示例1:

示例2:如果使用osThreadDef(first,1,1,1,1),那么就生成了 os_thread_def_first

hard and soft real-time requirements 硬、软实时需求

软实时需求: 即使违反了时间要求,也不会导致系统失效,例如按键的响应太慢会导致系统不响应按键,但是不会导致系统没用。
硬实时需求: 违反了时间要求,会导致系统的失败。例如驾驶员气囊系统,碰撞传感器响应太慢对导致很大的问题。

one core one thread

一个核在任何时间智能执行一个线程。核通过线程的优先级来判断当前该执行哪一个任务。硬实时需求分配较高优先级,软实时需求分配较低优先级。在FreeRTOS中,把thread 通常称为task,避免线程的概念和其他领域中的概念混淆。

FreeRTOS 的适用场景、特点

适用于较为复杂的系统,任务优先级确保程序的满足处理期限。
特点:

  • Very flexible task priority assignment 灵活的任务优先级设置
  • Flexible, fast and light weight task notification mechanism 灵活、快速、轻量级的任务通知机制
  • Queues 队列
  • Binary semaphores 二进制信 量
  • Counting semaphores 计数信 量
  • mutexes 互斥信 量
  • Recursive Mutexes 递归信 量
  • Software timers 软件定时器
  • event groups 时间组
  • Tick hook functions 时间钩子函数
  • Idle hook functions 空闲钩子函数
  • Stack overflow checking 堆栈溢出检查
  • Trace recording 跟踪记录
  • Task run-time statistics gathering 任务运行时间攻击
  • Full interrupt nesting model (for some architectures) 完整的终端嵌套模型
  • A tick-less capability for extreme low power applications 没有时间的极低功耗
  • Software managed interrupt stack when appropriate (this can help save RAM) 软件管理中断堆栈

FreeRTOSConfig.h 配置文件

根据需要修改其中的参数。

task.c and list

所有的FreeRTOS 接口中共有的文件。

queue.c 队列文件

提供队列和信 服务。几乎总是需要这个文件。

timers.c

提供软件定时器功能。

event_groups.c

提供事件组功能。

croutine.c

co-routine 协程,适用于较小的核,用的较少。官方已经不打算更新了。

heap memory management 堆内存管理

低于FreeRTOS 9.0的版本必须使用heap memory manager。或者是打开了 configSUPPORT_DYNAMIC_ALLOCATION 。 使用的是heap_1 to heap_5 文件。

数据类型

针对端口类型,有两个指定的数据类型定义文件,分别为 TickType_t 和 BaseType_t .
TickType_t : 滴答时间计时。根据MCU 位数定义,16或32位。
BaseType_t: 基本数据类型,通常和MCU的位数一致。

变量名

注意前缀。会指明变量的标准类型或非标准类型。以及指针类型。

函数名

注意前缀,前缀有两层,一层是返回值,一层是文件地址。
private function 前缀 是prv.

宏定义

宏定义名大写字母,前缀小写字母,指明文件位置。
注意:semaphore API 信 接口几乎是用宏来定义的,但是使用函数的命名规则来写的。

动态内存分配

内核对象: tasks queue 、semaphore and event group.
对象不是在创建时分配的,在运行时动态分配的。创建对象时分配RAM 空间,删除对象时删除RAM空间。这样的目的是减少RAM的使用空间。
使用函数: malloc() 、free(). 缺点是占用代码空间大,不适用于小型的MCU 。在FreeRTOS 中用 pvPortMalloc() 、vPortFree()代替。
函数位置 heap_1 ~ heap_5。

  • heap_1: 只能创建任务
  • heap_2: 能够删除任务,填空式重新创建任务。是不确定性的,但是速度比标准库要快。
  • heap_3: 使用malloc()、free()标准函数。通过挂起调度器来保证分配安全。
  • heap_4: 静态声明。合并空闲块避免碎片,适合重复分配和释放RAM。是不确定性的,但是速度比标准库要快。可以定义堆的起始地址。
  • heap_5: 和heap_4算法类似。不限于单个静态arry 分配内存,可以从多个单独的内存空间分配内存。vPortDefineHeapRegions() 必须实现声明。需要创建起始地址和 RAM 大小。

堆相关函数

当函数被调用时,返回堆字节数量。可以用来优化堆的大小。

返回最小未分配的堆的字节数。作用:指示距离空间消耗完毕有多接近。

钩子函数,解决堆分配失败的的问题,指明接下来怎么做。

注意事项

[Cortex-M users: Information on installing interrupt handers is provided in the “The application I created compiles, but does not run” FAQ]
翻译:[Cortex-M用户:“我创建的应用程序已编译但无法运行”常见问题解答中提供了有关安装中断处理程序的信息。
解决问题 址:https://www.freertos.org/FAQHelp.html

Task management 任务管理★

任务特点及任务运行状态

0、不退出,无限循环。
1、断点恢复执行。
2、任务切入、切出的名词:switch in switch out .只有任务调度器才能执行切换动作。
3、空闲任务自动创建当 scheduler 开始,保证任何时刻都有一个任务可以执行。

任务选择

优先级影响系统行为

任务状态

task 应用方法

创建 task 实例

1、 函数原型

任务创建失败的原因: 堆存储空间不够。
2、task 创建位置:main(); 或者另一个task 中。

使用任务参数

使用任务函数的意义:能够有效的提取、总结函数的核心功能,将一系列操作归类为一类操作。

创建、改变任务的优先级

优先级的设置方法: 有两种,任务开始阶段创建(设定优先级参数uxPriorty),或者调用vTaskPrioritySet(); 函数。
相关函数:

注意:函数名 pxTask 设置为 null 后,返回的是该 task 的优先级。

相关参数:configMAX_PRIORITIES : 定义的最大优先级数。
优先级和数字:小数字代表低优先级,0为最低优先级。(0 – configMAX_PRIORITIES – 1).
任务调度方法: genetic method architecture optimized method 两种。 注意优先级数不要设置太高,否则会浪费RAM。种方法选择的依据/p>

Time Measurement and the Tick interrupt 时间测量和滴答中断

time slicing 时间片: 针对 task 优先级相同的场景。每个任务对应一个时间片,时间片开始时进入运行状态,时间片结束时推出运行状态。
时间片原理: 使用 滴答中断 实现周期性中断。
相关参数:

  • configTICK_RATE_HZ ,滴答频率。两个滴答中断之间的时间称为滴答周期(tick period)。不建议直接用滴答来指定时间。使用 pdMS_TO_TICKS() 来指定时间比较好。
  • tick count 滴答计数:记录自程序运行以来的滴答中断数。

任务延迟

1、使用软件计数延时是粗糙的做法,效率低下。
2、建议的方法:vTaskDelay(). 该函数将函数blocked指定的时间来将函数延迟。注意:事先需要将 INCLUDE_vTaskDelay 设置为1.

该函数的参数是需要延迟的时间,以Ticks 为最小单位。如果需要以ms为单位,那么就结合 pdMS_TO_TICKS() 宏来转换为ms. 如 vTaskDelay(pdMS_TO_TICKS(100)), 就制定了100ms的延时。

该函数式精准延时函数。可以指定起始点。

Idle task 应用方法

意义: 1、保证时刻有一个任务处于可执行状态。2、测量备用处理能力。3、降低功耗(有一定效果)。
特点:优先级最低。
参数:

  • configIDLE_SHOULD_YIELD :
  • configUSE_IDLE_HOOK :设置为1,才可以使用idle hook function.

应用限制:
– idle task hook function 不能被挂起。
– 删除任务后,idle task hook function 应尽快被调用,清理资源。

删除任务

意义:可以删除自身或者其他任务。被删除的任务不再存在,不能再进入Running state.
相关参数: INCLUDE_vTaskDelete :设置为1 ,才可以使用删除函数。

相关函数:
注意:idle task 的清除作用。

配置调度算法

Round Robin Scheduling: 相关任务同优先级循环切换,共享处理时间。
Prioritized Pre-emptive Scheduling with Time Slicing 基于时间片的优先级调度算法:
Prioritized Pre-emptive Scheduling (without Time Slicing) 无时间片优先抢占调用: 难度大,有经验的高手使用。
Co-operative Scheduling 合作调度: 只有当前运行任务进入block状态或者使用 taskYIELD() 函数强制推迟才会切换任务。 任务不会被抢占,所以无法使用时间片。参数配置如下。

queue management 队列管理

queue 提供了 task to task task to interrupt interrupt to interrupt 的通信机制。

如何创建队列以及队列的信息

QUEUE 的 length 和 size : length 是 items 大小。size 是 队列里可以存储的 Item 的数量。

作用:FIFO buffer.
应用手段:直接复制队列内容到另一个队列。或者使用队列的指针。

特点:

  • Access by mutiple task 多任务读写:可以被多个任务读写。
  • Block on Queue Reads 读阻塞 : 可以阻塞 task 读取,并且可以指定读阻塞时间。多 task 的读取顺序取决于queue 的优先级,或者同优先级下的等待时间
  • Blocking on queue writes 读阻塞。可以阻塞 task 写入,并且可以指定写阻塞时间。多 task 的写的优先级取决于 task 的优先级或者同优先级下等待的时间。
  • 队列编组。队列可以编组, task 可以等待一组queue 的数据。

使用队列

1、创建一个队列.
先创建,再使用。通过 handle 引用,类型是 QueueHandle_t。

2、发送队列

3、接收队列
注意:有ISR版本

4、查询队列
注意:有ISR版本

处理大型或可变类型的数据

1、处理办法: 使用结构体指针,将数据源数据 编制为结构体,实现多种数据源、数据类型的传递。

  • 注意指针的拥有者。不要同时修改内存。
  • 指向的RAM仍然有效。(不是很明白)。不要轻易尝试使用被分配过的RAM。

queue sets 队列集

实现步骤

  • 创建queue
  • 创建queue set
  • 添加queue 到 queue set

使用步骤

  • 选取queue从queue set; 使用这个函数,xQueueSelectFromSet(); 如果返回值不是NULL,说明queue里有数据了,返回值就是该queue 的句柄。
  • 读取queue

mailbox 邮箱

邮箱指代 length = 1 的 queue。一种特殊用法。
主要有两种情况:

  • 使用queue 实现两个 task 之间传递数据;
  • 使用queue 存储数据,发送方始终重复写,接收方读取数据但是不删除queue 中的数据。

相关函数

software Timer management 软件定时器

定义: 周期性的调用函数,执行函数被称为 callback 函数。实现依靠 FreeRTOS 核,不需要硬件定时器支持。除非callback 函数在执行,否则不会消耗时间。只能在创建的函数中运行。
相关配置:

  • timer.c
  • congfigUSE_TIMERS = 1;

software timer callback functions 软件定时器函数

callback函数应用要求:

  • 保持短小;
  • 不能进入 Blocked 状态。不要调用FreeRTOS API函数,避免进入Block 状态。

函数原型

attribute and states 属性和状态

period of software timer: creat – executing ,创建到执行时间。
one shot and auto-reload timer 单发和自动重装定时器: 单发只能执行一次,自动重装会周期运行。

状态: dormant 休眠 、 running 两种。

软件定时器的内容

The RTOS Daemon (Timer Service) Task: callback 函数在此运行。自动创建。禁止调用API 函数的原因是会导致 deamon 函数进入BLOCKED 状态。

  • configTIMER_TASK_PRIORITY:优先级
  • configTIMER_TASK_STACK_DEPTH:堆栈大小

The Timer Command Queue: 作用是传递命令。command 传递 从timer task to daemon task ,自动创建,长度参数 configTIMER_QUEUE_LENGTH 。conmand 可以使用 time stamp 时间戳,设定传递时间。

软件定时器和任务的特点对比

RTOS demon task 守护程序任务

The timer command queue 定时器命令队列

one shot timer 和 periodic timer 的不同

如何去创建、开始、复位和修改软件定时器

创建步骤:
1、声明 TimerHandle_t 型变量。
2、使用函数创建定时器。

相关函数:

The Timer ID 标签

相关函数:

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年6月15日
下一篇 2020年6月15日

相关推荐