一、STM32CubeIDE使用内置的FreeRTOS
不同于STM32CubeIDE使用像RTThread这些第三方物联网系统,STM32CubeIDE在安装时就已经在MiddleWare中间件一栏直接支持了FreeRTOS操作系统。
既然STM32CubeIDE已经把FreeRTOS深度整合到了自家的系统中,所以移植及使用FreeRTOS变得非常方便。STM32CubeMX图形配置界面的MiddleWare一栏,可以设置FreeRTOS是否开启来使用该实时系统。
二、创建使用FreeRTOS系统的STM32CubeIDE工程
本文是基于STM32L496VGT3的MCU芯片创建一个新的STM32工程“stm32L496VGT3_CMSIS_OS_V1”,并使用FreeRTOS系统前,已经开启了lpusart串口通信及三个LED的GPIO_OUTPUT接口,及实现了串口lpusart及LED灯驱动(关于这边部分设置及实现就略过,读者可以参考本专栏的其他博文)。
现双击(.ioc)文件进入cubeMX图像配置界面,开启使用FreeRTOS系统。在MiddleWare中间件一栏,选择FreeRTOS,在右边Interface下来框,会出现Disable、CMSIS_V1和CMSIS_V2三个选项。本文选择CMSIS_V1进行测试。
关于CMSIS_V1和CMSIS_V2的不同,详见CMSIS ARM官方关于微控制器软件接口标准CMSIS定义(如下图)。Cortex微控制器软件接口标准(CMSIS)是独立于供应商的硬件抽象层,用于基于Arm Cortex处理器的微控制器,并且CMSIS提供了到处理器和外围设备,实时操作系统以及中间件组件的接口。不同之处简单来说,v1使得软件能够在不同的实时操作系统下运行(屏蔽不同RTOS提供的API的差别),而v2则是拓展了RTOS v1,兼容更多的CPU架构和实时操作系统,说白话就是,CMSIS_V2是在CMSIS_V1上,兼容CMSIS_V1的,具有更多功能及支持更多硬件型号。
点击保存或生成代码按钮,会弹出下面对话框:
这是关于freertos暴露给用户的API接口并不是原生的freertos接口,是经过cmsis-rtos进行一次包装之后的,在使用timebase源是有所冲突,编译器会建议你把timebase源切换到非systick。这是因为freertos的调度时钟是强制性使用systick的并且systick的中断优先级被设置为最低。
而hal 库需要使用到的tick计数源,HAL标准库有很多有超时功能的函数接口都用到这个hal timebase。所以编辑器在生成代码时候就强烈建议hal timebase和freertos 使用的systick不要共用。systick已经被强制为最低优先级,hal timebase用的话就可能产生计数不准的情况。
至于systick已经被强制为最低优先级,是因为freertos是一个嵌入式实时操作系统,要确保中断能够立马得到响应,就要把调度器的时钟优先级设置为最低就不会影响其他外设中断的及时响应。在一旦在stm32cubemx中勾选了freertos后,systick的优先级自动被设置为最低。
freertos还有个配置优先级选项:configMAX_SYSCALL_INTERRUPT_PRIORITY高于该配置的优先级中断中都不能调用freertos的任何API,但是同时他也不会受freertos的内核影响而可以得到最实时的响应。如果在中断服务函数中需要使用freertos的API接口函数的话就要把该中断的优先级配置为小于或等于 configMAX_SYSCALL_INTERRUPT_PRIORITY。
在stm32L0系列单片机的优先级一共有四个等级:0-3,0为最高优先级3为最低。使用freertos以后sytick就在该等级。把 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 配置为2,这样特别实时的中断优先级就可以配置为0或者1,而正常需要调用freertos API的中断就可以配置为2或者3优先级。
现在按编辑器建议,去修改开启USE_NEWLIB_REENTRANT
同时调整HAL TimeBase设置更换TimeBase源。
再次点击保存,编辑器就无告警弹出,生成代码后,关于FreeRTOS生成代码如下:
并在main,c主函数文件中,给出了关于FreeRTOS最简要的调用代码。
并能编译通过。
三、使用FreeRTOS功能
现在再次回到cubeMX图形编辑界面,进入FreeRTOS配置的任务与队列配置页面,添加一个LedTask(闪灯任务),修改任务名为LEDTask,修改Function名为LEDTaskFunc,注意任务名和Function名不能一样,其他保持默认。
关于NewTask几个属性栏:
- Task Name: 设置任务的名称,它会基于此名字建立一个指向任务的句柄
- Priority: 设置任务的优先级,高优先级的任务会抢占低优先级的任务
- Stack Size: 设置任务栈的大小,用于储存任务相关的变量,关于堆栈详细内容请参考
- Entry Function:设置任务的入口函数,这个函数便是开发者实现任务功能的地方
- Code Generation Option: IDE自动生产初始代码的选项,这里选择默认设置
- Parameter: 传递给任务的参数
- Allocation: 选择动态的话是生成在堆中,选择静态的话则生成在静态区
- Buffer Name和ControlBlock Name:在Allocation选择静态时生效。
配置好这个LedTask后,保存生成输出代码,去FreeRTOS的用户可编译源文件freertos.c中,找到LEDTaskFunc函数,这就是我们在cubeMX图形界面配置的任务入口,可以在这里修改实现自己任务内容。
例如本文在源码文件引入"../../ICore/led/led.h"驱动头文件,该LEDTaskFunc函数循环体内加上闪灯功能Toggle_led0()。
关于LEDTaskFunc函数调用,在主函数中初始化先调用FreeRTOS初始化API:“MX_FREERTOS_Init()”,然后在调用osKernelStart()启用。MX_FREERTOS_Init函数是图形配置生成的,在freertos.c文件中。另外为了防止主函数循环一直占用资源,调用一个延时HLA_Delay(100),防止LEDTaskFunc函数循环抢不到资源。
四、编译及测试
【1】进入项目属性设置页面,配置工程输出文件格式支持。
【2】配置程序运行按钮下来列表,点击“运行配置”,新建一个配置选项,默认配置即可,选择串口支持格式。或者采用其他烧写工具实现。
本文开发板支持ST-Link加载。
【3】点击运行按钮,完成编译下载
【4】观察效果,只有LED0在闪烁,而代码实现中只有在LEDTaskFunc函数循环中调用了Toggle_led0(),说明FreeRTOS系统已经被争取使用:
CubeIDE调用FreeRTOS实现闪灯任务-CSDN直播
补充,不好意思,忘了自己等级不够,放不了视频,给出图片效果如下: