术语
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进行处理,非常感谢!