一、FreeRTOS简介
FreeRTOS 是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。FreeRTOS 提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。
FreeRTOS 是用 C 和汇编来写的,其中绝大部分都是用 C 语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的,FreeRTOS 结构简洁,可读性很强!最主要的是非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。
最新版本 V9.0.0(2016年),尽管现在 FreeRTOS 的版本已经更新到 V10.4.1 了,但是我们还是选择 V9.0.0,因为内核很稳定,并且 上资料很多,因为 V10.0.0 版本之后是亚马逊收购了FreeRTOS之后才出来的版本,主要添加了一些云端组件,一般采用 V9.0.0 版本足以。
- FreeRTOS官 :http://www.freertos.org/
- 代码托管 站:https://sourceforge.net/projects/freertos/files/FreeRTOS/
二、新建工程
1. 打开 STM32CubeMX 软件,点击“新建工程”
3. 配置时钟
RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)
4. 配置调试模式
非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
SYS 设置,选择 Debug 为 Serial Wire
在基于STM32 HAL的项目中,一般需要维护的 “时基” 主要有2个:
- HAL的时基,SYS Timebase Source
- OS的时基(仅在使用OS的情况下才考虑)
而这些 “时基” 该去如何维护,主要分为两种情况考虑:
-
裸机运行:
可以通过 (滴答定时器)或 ()定时器 的方式来维护 ,也就是HAL库中的 ,这是HAL库中维护的一个全局变量。在裸机运行的情况下,我们一般选择默认的 (滴答定时器) 方式即可,也就是直接放在 中断服务函数中来维护。 -
带OS运行:
前面提到的 是STM32的HAL库中的新增部分,主要用于实现 以及作为各种 timeout 的时钟基准。在使用了OS(操作系统)之后,OS的运行也需要一个时钟基准(简称“时基”),来对任务和时间等进行管理。而OS的这个 时基 一般也都是通过 (滴答定时器) 来维护的,这时就需要考虑 “HAL的时基” 和 “OS的时基” 是否要共用 (滴答定时器) 了。
如果共用SysTick,当我们在CubeMX中选择启用FreeRTOS之后,在生成代码时,CubeMX一定会 如下提示:
我们创建三个任务,两个接收任务,一个发送任务。
- Task Name: 任务名称
- Priority: 优先级,在 FreeRTOS 中,数值越大优先级越高,0 代表最低优先级
- Stack Size (Words): 堆栈大小,单位为字,在32位处理器(STM32),一个字等于4字节,如果传入512那么任务大小为512*4字节
- Entry Function: 入口函数
- Code Generation Option: 代码生成选项
- Parameter: 任务入口函数形参,不用的时候配置为0或NULL即可
- Allocation: 分配方式: 动态内存创建
- Buffer Name: 缓冲区名称
- Conrol Block Name: 控制块名称
五、KEY
5.1 参数配置
在 中选择 设置。
六、UART串口打印
查看 STM32CubeMX学习笔记(6)——USART串口使用
七、生成代码
输入项目名和项目路径
八、任务通知
8.1 基本概念
FreeRTOS 从 V8.2.0 版本开始提供任务通知这个功能,每个任务都有 一个 32 位 的通知值,在大多数情况下,任务通知可以 替代二值信 量、计数信 量、事件组,也可以替代长度为 1 的队列(可以保存一个 32 位整数或指针值)。
相对于以前使用 FreeRTOS 内核通信的资源,必须创建队列、二进制信 量、计数信 量或事件组的情况,使用任务通知显然更灵活。按照 FreeRTOS 官方的说法,使用任务通知比通过信 量等 ICP 通信方式解除阻塞的任务要快 45%,并且更加省 RAM 内存空间(使用 GCC 编译器,-o2 优化级别),任务通知的使用无需创建队列。 想要使用任务通知,必须将 中的宏定义 设置为 ,其实FreeRTOS 默认是为 1 的,所以任务通知是默认使能的。
FreeRTOS 提供以下几种方式发送通知给任务 :
- 发送通知给任务, 如果有通知未读,不覆盖通知值。
- 发送通知给任务,直接覆盖通知值。
- 发送通知给任务,设置通知值的一个或者多个位 ,可以当做事件组来使用。
- 发送通知给任务,递增通知值,可以当做计数信 量使用。
通过对以上任务通知方式的合理使用,可以在一定场合下替代 FreeRTOS 的信 量,队列、事件组等。
当然,凡是都有利弊,不然的话 FreeRTOS 还要内核的 IPC 通信机制干嘛,消息通知虽然处理更快,RAM 开销更小,但也有以下限制 :
- 只能有一个任务接收通知消息,因为必须指定接收通知的任务。
- 只有等待通知的任务可以被阻塞,发送通知的任务,在任何情况下都不会因为发送失败而进入阻塞态。
8.2 运作机制
由于任务通知的数据结构包含在任务控制块中,只要任务存在,任务通知数据结构就已经创建完毕,可以直接使用,所以使用的时候很是方便。
任务通知可以在任务中向指定任务发送通知,也可以在中断中向指定任务发送通知,FreeRTOS 的每个任务都有一个 32 位的通知值,任务控制块中的成员变量 ulNotifiedValue 就是这个通知值。只有在任务中可以等待通知,而不允许在中断中等待通知。如果任务在等待的通知暂时无效,任务会根据用户指定的阻塞超时时间进入阻塞状态,我们可以将等待通知的任务看作是消费者;其它任务和中断可以向等待通知的任务发送通知,发送通知的任务和中断服务函数可以看作是生产者,当其他任务或者中断向这个任务发送任务通知,任务获得通知以后,该任务就会从阻塞态中解除,这与 FreeRTOS 中内核的其他通信机制一致。
九、相关API说明
9.1 osSignalSet
向指定的任务发送一个任务通知,带有通知值并且用户可以指定通知值的发送方式。该函数可以在中断函数中使用。
函数 int32_t osSignalSet (osThreadId thread_id, int32_t signal) 参数 thread_id: 接收通知的任务ID signal: 任务通知值,一般按位操作数字,一个事件用一个类似这样的值表示(即0x0001,0x0002,0x0004,0x0008,0x0010…)
返回值 错误码 9.2 osSignalWait
用于实现等待任务通知,根据用户指定的参数的不同,可以灵活的用于实现轻量级的消息队列队列、二值信 量、计数信 量和事件组功能,并带有超时等待。函数不允许在中断函数中使用。
函数 osEvent osSignalWait (int32_t signals, uint32_t millisec) 参数 signals: 接收完成后等待被清零的数据位,比如一个任务状态切换,由四个不同的事件分别影响着,通知osSignalSet中的signal分别为0x0001,0x0002,0x0004,0x0008,那么接收端osSignalWait 中的signals应该为0x000F(0x0001|0x0002|0x0004|0x0008) millisec: 等待超时时间,单位为系统节拍周期。宏 pdMS_TO_TICKS 用于将单位毫秒转化为系统节拍数
返回值 错误码 十、示例
按下按键1触发任务通知到接收任务1Receive1Task,按下按键2触发任务通知到接收任务2Receive2Task。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!