手动移植FreeRTOS到STM32

        前言:这只是一篇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更多的内容还需大家慢慢去了解和深入

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值