前言:这只是一篇FreeRTOS入门的文章,用于自己忘记的时候回看复习。本文是采用CubeMX生成的STM32F407的基础工程后来进行移植的。
一、FreeRTOS简介
1.什么是实时操作系统
实时操作系统(Real-time operating system, RTOS),又称即时操作系统,它会按照排序运行、管理系统资源,并为开发应用程序提供一致的基础。实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。实时操作系统中都要包含一个实时任务调度器,这个任务调度器与其它操作系统的最大不同是强调:严格按照优先级来分配CPU时间,并且时间片轮转不是实时调度器的一个必选项。
2.FreeRTOS功能
FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
二、FreeRTOS源码下载
首先我们先去到FreeRTOS的官网:FreeRTOS - 市场领先的 RTOS(实时操作系统),适用于具有物联网扩展的嵌入式系统
官网页面如下,点击 "下载FreeRTOS" 。
在弹出的界面中我们点击第二个LTS版本的下载,第二个是长期维护的版本。
进去后选择git和zip方式下载都可以,写博客的时候打不开网站就不贴图了。
和我一样没法打开网站的可以用我下面这个网盘的链接下载:
链接:https://pan.baidu.com/s/1_7HMV8de3_wIyXlptGKudw?pwd=hyun
提取码:hyun
三、CubeMX配置工程
注意:FreeRTOS中使用的时钟源是STM32的SysTick定时器,它用来实现我们的任务切换,所以在CubeMX配置的时候我们需要将Timebase Source的时钟源改成其他定时器,如下图,我改成了TIM2。
1.时基源配置
2.GPIO配置
我的开发板实物PA0-PA3连接的是按键,设置为输入,PB12-PB15连接的是LED的阴极,配置为推挽输出,这样就可以生成工程了(配置时钟树,调试那些没贴图了)。
四、移植FreeRTOS
1.创建FreeRTOS文件夹
如下图所示,在前面CubeMX生成的工程文件夹下创建一个application文件夹和一个middlewares文件夹,前者用来存放测试源文件,后者用来存放FreeRTOS文件。
2.将FreeRTOS源码添加到工程
前面下载的FreeRTOS源码的压缩包解压如下:
打开上图中的FreeRTOS文件夹如下图所示,我们只需将其中的FreeRTOS-Kernel文件夹复制到工程的02_middlewares文件夹下即可。其他文件夹都不需要,就可以打开工程了。
3.创建FreeRTOS工程组
如下图,在工程中创建两个新的组,只在middlewares/FreeRTOS组中加入以下6个源文件,各源文件在工程中的位置见后图。
在FreeRTOS-Kernel文件夹下就有其中四个
因为我使用的是F4系列的,所以是ARM_CM4F文件夹,如果使用的是F103C8T6那就是ARM_CM3文件夹,以此类推。
还有MemMang文件夹下的heap_4.c,据说heap4比较好用一些。
4.设置头文件路径
keil主页点击魔术棒进入如下对话框添加三个路径
5.创建一个FreeRTOSConfig.h
5.1创建一个空的头文件
因为在压缩包中没有FreeRTOSConfig.h文件,但FreeRTOS的源文件又引用了这个头文件,所以我们要先创建一个FreeRTOSConfig.h,不然编译会报找不到FreeRTOSConfig.h的错误
如下图,我们先在FreeRTOS-Kernel文件夹下创建一个空的FreeRTOSConfig.h头文件,然后在keil中将它打开。
5.2复制官网的FreeRTOSConfig.h
下图中FreeRTOSConfig.h的内容没有截完,去官网复制的时候复制到#endif /*FREERTOS_CONFIG_H */即可,即将下图中框住的整个头文件都复制到刚刚新建的FreeRTOSConfig.h中
复制过来后还需简单的修改几个地方,我的改好的FreeRTOSConfig.h如下,F407是可以正常使用的,其他型号单片机可能还需自己修改才能使用,文件中具体每个宏定义是干什么用,大家可以看看官网的FreeRTOSConfig.h,上图的那些蓝字都是可以点击进去看详细说明的。完成这一步就可以直接编译了
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/* Here is a good place to include header files that are required across
your application. */
#include "stm32f4xx_hal.h"
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ 1000
#define configMAX_PRIORITIES 5
#define configMINIMAL_STACK_SIZE 128
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS
#define configIDLE_SHOULD_YIELD 1
#define configUSE_TASK_NOTIFICATIONS 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 10
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
#define configUSE_MINI_LIST_ITEM 1
#define configSTACK_DEPTH_TYPE uint16_t
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
#define configHEAP_CLEAR_MEMORY_ON_FREE 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configSTATS_BUFFER_MAX_LENGTH 0xFFFF
/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configKERNEL_PROVIDED_STATIC_MEMORY 1
#define configTOTAL_HEAP_SIZE 81920
#define configAPPLICATION_ALLOCATED_HEAP 0
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configENABLE_HEAP_PROTECTOR 1
/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
#define configUSE_SB_COMPLETED_CALLBACK 0
/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 1
/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 3
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
/* Interrupt nesting behaviour configuration. */
#define configKERNEL_INTERRUPT_PRIORITY 16
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 15
#define configMAX_API_CALL_INTERRUPT_PRIORITY 15
/* Define to trap errors during development. */
//#define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
/* FreeRTOS MPU specific definitions. */
#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
#define configTOTAL_MPU_REGIONS 8 /* Default value. */
#define configTEX_S_C_B_FLASH 0x07UL /* Default value. */
#define configTEX_S_C_B_SRAM 0x07UL /* Default value. */
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
#define configENABLE_ERRATA_837070_WORKAROUND 1
#define configUSE_MPU_WRAPPERS_V1 0
#define configPROTECTED_KERNEL_OBJECT_POOL_SIZE 10
#define configSYSTEM_CALL_STACK_SIZE 128
#define configENABLE_ACCESS_CONTROL_LIST 1
/* ARMv8-M secure side port related definitions. */
#define secureconfigMAX_SECURE_CONTEXTS 5
/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_uxTaskGetStackHighWaterMark2 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 0
#define INCLUDE_xTaskAbortDelay 0
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xTaskResumeFromISR 1
/* A header file that defines trace macro can be included here. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */
6.解决编译报错
下述报错信息是说我们有三个函数重定义了,需要我们去stm32f4xx_it.c中找到这三个函数并在函数前用__weak修饰,(这里就说明如果我们再次使用CubeMX重新生成这个工程的话,那每生成一次都需要去stm32f4xx_it.c给这三个函数加__weak),加了__weak之后再次编译
如下图,就没有报错了,可以写一些最简单的任务了
7.写测试程序
在一开始创建的01_application文件夹下创建一个测试的源文件rtos_test.c,并将它添加到01_application工程组里,再将函数rtos_test在main函数中声明和调用就可以实现两个LED同步闪烁了,在我的开发板上实现成功了
#include "gpio.h"
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
/* 任务函数需要是void task(void *arg)类型的 */
static void task1(void *arg)
{
for( ; ; )
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_12);
vTaskDelay(500);
}
}
static void task2(void *arg)
{
for( ; ; )
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_13);
vTaskDelay(500);
}
}
void rtos_test(void)
{
xTaskCreate(task1,"Task1",128,NULL,1,NULL);//创建任务1
xTaskCreate(task2,"Task2",128,NULL,1,NULL);//创建任务2
vTaskStartScheduler();//启动任务调度器
}
本文只是快速的移植FreeRTOS,FreeRTOS更多的内容还需大家慢慢去了解和深入