FreeRTOS的裁剪和配置

1. 引言

嵌入式系统中的软、硬件支持裁剪和配置,作为嵌入式实时操作系统,FreeRTOS 同样支持裁剪和配置。FreeRTOS 使用 FreeRTOSConfig.h头文件来进行裁剪和配置,每个FreeRTOS 应用项目中都必须有一个FreeRTOSConfig.h头文件。由于FreeRTOSConfig.h头文件不是FreeRTOS内核的一部分,因此可将这个头文件放入应用程序目录。
FreeRTOSConfig.h头文件中有很多以 INCLUDE_和config 开始的宏。以INCLUDE开始的宏用来明确在FreeRTOS中哪些API(应用程序接口)函数可用,以config开始的宏一般用来进行特定功能的条件编译。并非所有与 FreeRTOS 裁剪相关的宏都必须在FreeRTOSConfig.h 头文件中定义。当有些宏没有在 FreeRTOSConfig.h头文件中定义时,FreeRTOS 会在另外一个头文件 FreeRTOS.h中自动定义一个宏,然后给它分配一个默认值。例如,宏 configUSE_TIME_SLICING没有在 FreeRTOSConfig.h头文件中定义时,FreeRTOS 会在 FreeRTOS.h头文件中定义这个宏,且其默认值为1,宏configUSE_TRACE_FACILITY 也一样,但它的默认值为0。

2. 基础配置

2.1 configUSE_PREEMPTION

configUSE_PREEMPTION 用来定义内核的调度方式。当此宏为1时,使用抢占式调度方式;当此宏为0时,使用合作式调度方式。合作式调度方式在硬件资源极为有限的系统中使用,此宏一般设为1。

2.2 configUSE_PORT_OPTIMISED_TASK_SELECTION

在 FreeRTOS 任务切换时,configUSE PORT_ OPTIMISED TASK SELECTION 用于设置查找下一个要运行的任务的方法。当此宏为1时,使用硬件方法查找下一个要运行的任务,需要硬件指令支持,运行速度快,但一般会有优先级数量限制。当此宏为0时,使用通用方法查找下一个要运行的任务,用纯软件方法实现,没有优先级数量限制,但运行速度比硬件方法慢。STM32微控制器有一个计算前导零指令,支持用硬件方法查找下一个要运行的任务,此宏设为1。

2.3 configCPU_CLOCK_HZ

configCPU_CLOCK_HZ用于设置系统时钟频率,单位为 Hz。对于 STM32微控制器,可使用SystemCoreClock这个全局变量来设置系统时钟频率,也可以手动的设置。

2.4 configTICK_RATE_HZ

configTICK_RATE_HZ 用于定义系统时钟节拍,单位为Hz。在STM32微控制器中,此频率就是嘀嗒定时器的中断频率,其倒数就是一个时间片的长度。设置系统时钟节拍需要综合考虑任务实时性、任务数量、优先级数量等。设置过高的系统时钟节拍,会使CPU花在任务切换上的时间过多,导致系统性能的下降。本文的小实验,均使用1000Hz作为系统时钟节拍,即时间片的长度为1ms。

2.5 configMAX_PRIORITIES

configMAX_PRIORITIES 用于定义可供使用的任务的最大优先级值。FreeRTOS本身对任务的优先级数量没有限制,但优先级数量越多,消耗的资源也就越多。当配置宏configUSE_PORT_OPTIMISED_TASK_SELECTION为1时,表示使用硬件方法查找下一个要运行的任务,由于硬件的限制,任务的优先级数量也会受到限制。对于STM32微控制器,在使用硬件方法查找下一个要运行的任务时,任务的优先级最多为32个,优先级为从0到31。

2.6 configMINIMAL_STACK_SIZE

configMINIMAL_STACK_SIZE用于定义空闲任务使用的堆栈大小,单位为word,即4B。FreeRTOS在开启调度器时,会自动创建空闲任务,空闲任务使用的堆栈大小由此宏决定。

2.7 conRgTOTAL_HEAP_SIZE

conRgTOTAL_HEAP_SIZE 用于定义 FreeRTOS管理的堆内存大小。如果使用了动态内存营理方式,则PreeRTOS在创建任务通知、信号量、队列时会从这个堆内存中分配内存、内存其实就是一个定义好的数组 ucHeap[configTOTAL_HEAP SIZE],类型为uint8_t,大小为conRgTOTAL_HEAP_SIZE。

2.8 configUSE_16_BIT_TICKS

configUSE_16_BIT_TICKS为系统时钟节拍计数器数据类型,用于定义TickType_t是哪种数据类型的,若此宏为1,则TickType_t使用16位无符号数;若此宏为0,则TickTypes使用32位无符号数。对于8位或16位架构的处理器,此宏应设为1;对于32位构架的处理器(如STM32),此宏应设为0。此宏还会影响可用的任务最大阻塞时间,阻塞时间为portMAX_DELAY 表示无限期阻塞。

2.9 configIDLE_SHOULD_YIELD

configIDLE_SHOULD_YIELD 用于实现空闲任务和与空闲任务同优先级的任务之间的切换。在使用抢占式调度方式,且创建了与空闲任务同优先级的任务时,此宏才会起作用。此宏为1表示不等空闲任务时间片用完,就可立即从空闲任务切换到与空闲任务同优先级的任务。

2.10 configMAX_TASK_NAME_LEN

configMAX_TASK_NAME_LEN用于定义任务名最长的字符串长度。此宏越大,消耗
的内存就越大,字符串结束符0也要计算在内。

2.11 configUSE_TICKLESS_IDLE

configUSE_TICKLESS_IDLE 用于低功耗 tickless 模式设置。当此宏为1时,使用低
功耗tickless模式;当此宏为0时,不使用低功耗tickless 模式。

2.12 关于列队、信号量和任务通知

configUSE_QUEUE_SETS用于定义是否使用队列集,configUSE_MUTEXES 用于定义是否使用互斥信号量,configUSE_RECURSIVE MUTEXES用于定义是否使用递归互斥信号量,configUSE_COUNTING SEMAPHORES用于定义是否使用计数信号量,configUSE_TASK_NOTIFICATIONS用于定义是否使用任务通知。当这些宏设为1时,相应功能的API函数就会被编译。

2.13 关于钩子函数

configUSE_IDLE_HOOK用于使能空闲任务钩子函数,configUSE_TICK_HOOK用于使能时间片钩子函数,configUSE_MALLOC_FAILED HOOK用于使能动态内存分配失败钩子函数,configCHECK_FOR_STACK_OVERFLOW 用于使能堆栈溢出检测钩子函数。钩子函数需要由用户实现,当对应的宏不为0时,必须提供相应的钩子函数。

2.14 FreeRTOS 中断配置

STM32微控制器使用ARM Cortex-M 内核。ARM Cortex-M 内核采用8位(二进制位)来表示可编程的中断优先级,共有256个中断优先级。实际的中断优先级数量由芯片生产厂家决定,如STM32微控制器就没有使用全部的8位,只使用了4位,共有16个中断优先级。不管采用多少位表达中断优先级,均采用MSB对齐方式。

2.15 configPRIO_BITS

configPRIO_BITS 用于设置硬件用于表达中断优先级的二进制位数。STM32微控制器使用了4位,故此宏应设为4。因为在core_cm3.h头文件中定义了表达中断优先级位数据的宏_NVIC_PRIO_BITS,并且该宏已设为4,所以可通过这个宏来设定configPRIO_BITS,或者直接将configPRIO_BITS设为4。

2.16 configLIBRARY_LOWEST_INTERRUPT_PRIORITY

configLIBRARY_LOWEST_INTERRUPT_PRIORITY 用于设置最低中断优先级。STM32微控制器使用4位二进制位表达中断优先级,中断优先级最多为16个。STM32控制器表达的中断优先级高低与中断优先级值的关系比较特殊,中断优先级值越大,中断优先级越低,中断优先级值为0表示最高中断优先级。所以,此宏应设为15。

2.17 configKERNEL_INTERRUPT_PRIORITY

configKERNEL_INTERRUPT_PRIORITY用于设置内核的中断优先级,即嘀嗒定时器和 PendSV 的中断优先级。此宏的定义通过 configLIBRARY LOWEST_INTERRUPT PRIORITY<<(8-configPRIO_BITS)替换得到,替换结果应该是中断系统中的最低中断代先级。用前面定义好的宏,替换为0x0F<<(8-4),结果为0xF0,高4位正好为15,也就是STM32微控制器的最低中断优先级。

2.18 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY

configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 用于设置FreeRTOS 可管理的最高中断优先级。可以在硬件中断优先级数量之内任意设置,如设置为5,表示中断优先级高于5的中断(对于STM32微控制器,为中断优先级0至中断优先级4的中断)不归 FreeRTOS 管理。

2.19 confgMAX_SYSCALL_INTERRUPT_PRIORITY

 confgMAX_SYSCALL_INTERRUPT_PRIORITY 的定义通过 configLIBRARY_MAX SYSCALL_INTERRUPT_PRIORITY <<(8-configPRIO_BITS)替换得到。例如,宏configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 设为5,表示优先级高于5的中断不归 FreeRTOS管理,在这些中断服务函数中不能调用 FreeRTOS 的 API 函数。

3. 可选API函数配置

通过配置以INCLUDE_开始的宏,可对FreeRTOS的一些可选API函数进行配置。当对应的宏为1时,使能相应功能的API函数,这些API 函数就会参与编译,从而可供应用程序调用。例如,当INCLUDE_vTaskDelay设为1时,vTaskDelayO函数将会被编译,从而在应用程序中可用vTaskDelayO函数实现阻塞式延时。下面列出了几个常用的使能API函数对应的宏。

#define INCLUDE_vTaskPrioritySet                 1        /*任务优先级设置*/
#define INCLUDE_uxTaskPriorityGet                1        /*任务优先级获取*/
#define INCLUDE_vTaskDelete                      1        /*任务删除*/
#define INCLUDE_vTaskSuspend                     1        /*任务挂起*/
#define INCLUDE_vTaskDelayUntil                  1        /*绝对延时阻塞 */
#define INCLUDE_vTaskDelay                       1        /*相对延时阻塞*/
#define INCLUDE_xTaskGetSchedulerState           1        /*获取调度器状态*/
#define INCLUDE_xTaskGetCurrentTaskHandle        1        /*获取当前任务句柄*/
#define INCLUDE_uxTaskGetStackHighWaterMark      1        /*获取任务堆栈高水位线*/
#define INCLUDE_xTaskGetIdleTaskHandle           1        /*获取空闲任务句柄*/
#define INCLUDE_xTimerGetTimerDaemonTaskHandle   1        /*获取软件定时器服务句柄*)
#define INCLUDE_pcTaskGetTaskName                1        /*获取任务名*/

 4. 其他配置

4.1 协程相关

4.1.1 configUSE_CO_ROUTINES

configUSE_CO_ROUTINES 用于定义是否使用协程。此宏为0表示不使用协程,为1表示使用协程。在抢占式调度方式中也可使用协程,使用协程可以节约开销,但功能将受到限制。现在的微处理器功能都已经很强大了,协程很少采用,故此宏应该设为0。

4.1.2 configMAX_CO_ROUTINE_PRIORITIES

configMAX_CO_ROUTINE_PRIORITIES 用于定义协程的有效优先级数量,优先级从0到configMAX_CO_ROUTINE_PRIORITIES-1,其中0为最低优先级。

4.2 任务运行信息相关

 4.2.1 configUSE_TRACE_FACILITY

configUSE_TRACE_FACILITY 用于使能可视化跟踪和调试。此宏为1表示使能可视化跟踪和调试。

4.2.2 confgUSE_STATS_FORMATTING_FUNCTIONS

confgUSE_STATS_FORMATTING_FUNCTIONS 与 configUSE_TRACE_FACILIy
同时为1时,vTaskList()和vTaskGetRunTimeStat()两个函数会参与编译,从而可以通过这
两个数获取任务运行信息。

4.2.3 configGENERATE_RUN_TIME_STATS

configGENERATE_RUN_TIME_STATS用于定义是否开启时间统计功能。此宏为1表示开启时间统计功能。当此宏为1时,还需要用户实现两个宏:portCONFIGURE_TIMER_FOR_RUN_TIME_STATSO和 ponGET_RUN_TIME_COUNTER_VALUEO。前者对应于一个精度是嘀嗒定时器时间精度10倍以上的定时器初始化函数,后者对应于一个取统计时间值的函数,这两个函数均需要由用户实现。

4.3 软件定时器相关

4.3.1 configUSE_TIMERS

configUSE_TIMERS用于定义是否使用软件定时器功能。此宏为1表示使用软件定时器功能。当此宏为1时,会在调度器开启函数中自动创建软件定时器服务任务,同时需要正确配置后面几个宏。

4.3.2 configTIMER_TASK_PRIORITY

configTIMER_TASK_PRIORITY 用于定义软件定时器服务任务的默认优先级。

4.3.3 configTIMER_QUEUE_LENGTH

configTIMER_QUEUE_LENGTH用于定义软件定时器命令队列长度。

4.3.4 configTIMER_TASK_STACK_DEPTH

configTIMER_TASK_STACK_DEPTH用于定义软件定时器服务任务堆栈大小。

4.4 断言

断言用于在代码调试阶段检查传入的参数是否合理。FreeRTOS 内核在关键点均会调FonfgASSERT(x),如果×结果为 0,则说明有错误发生。当错误发生时有多种处理方可通过串口输出信息,也可直接停机。下面是一种停机处理方法示例,在发生错误时直接停机。

#define configASSERT(X)       if ((X) == 0)   {taskDISABLE_INTERRUPTS();

for(;;);

 }

使用断言会增加系统的开销,一般在调式阶段使用。如果要关闭这个功能,注释掉FonfgASSERT(X)就行。

4.5 中断服务函数

在 FrceRTOS 移植层的 port.c 文件中,分别定义了 vPortSVCHandler,xPortPendSVHandler 和xPortSysTickHandler这 3个中断服务函数。这3个中断服务函数分别用于实现SVC中断、PendSV 中断和嘀嗒定时器中断。实际中断服务函数名与对应架构的硬件相关,在STM32微控制器中,这3个中断服务函数名分别为 SVC_Handler、PendSV_Handler 和SysTick Handler。经过下面的宏定义处理,在编译时就可以正确进行替换。(通常移植失败时,可能就是没有进行宏处理从而进行替换)

5 FreeRTOSConfig.h 头文件参考配置

下面给出一个FreeRTOSConfig.h头文件定义,后面会做相关的例程均使用这个头文件。

///*
// * FreeRTOS Kernel V10.3.0
// * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
// *
// * Permission is hereby granted, free of charge, to any person obtaining a copy of
// * this software and associated documentation files (the "Software"), to deal in
// * the Software without restriction, including without limitation the rights to
// * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// * the Software, and to permit persons to whom the Software is furnished to do so,
// * subject to the following conditions:
// *
// * The above copyright notice and this permission notice shall be included in all
// * copies or substantial portions of the Software.
// *
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// *
// * http://www.FreeRTOS.org
// * http://aws.amazon.com/freertos
// *
// * 1 tab == 4 spaces!
// */


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html
 *----------------------------------------------------------*/
//#if defined( __ICCARM__) || defined( __CC_ARM)
//	#include <stdint.h>
//	extern uint32_t SystemCoreClock;
//#endif
/*------------------------------------------------------基础配置------------------------------------------------------*/
/*内核的调度方式:为1使用抢占式调度方式,为0使用合作式调度方式*/
#define configUSE_PREEMPTION		                        1
/*时间片调度:不定义或为1,使能*/
#define configUSE_TIME_SLICING                              1
/*查找下一个运行的任务的方法:为1使用硬件方法,为0使用通用方法*/
#define configUSE_PORT_OPTIMISED_TASK_SELECTION             1


/*系统时钟频率*/
#define configCPU_CLOCK_HZ			                       ( ( unsigned long ) 72000000 )
/*系统时钟节拍:节拍频率,其倒数就是一个时间片的长度*/
#define configTICK_RATE_HZ			                        ( ( TickType_t ) 1000 )
/*任务优先级数量*/
#define configMAX_PRIORITIES		                        ( 5 )
/*最小任务堆栈:空闲任务使用的堆栈大小*/
#define configMINIMAL_STACK_SIZE	                        ( ( unsigned short ) 128 )
/*堆内存大小:供 FreeRTOS使用的总堆内存大小*/
#define configTOTAL_HEAP_SIZE		                        ( ( size_t ) ( 17 * 1024 ) )
/*动态内存分配:为1成不定义支持*/
#define configSUPPORT_DYNAMIC_ALLOCATION                    1
/*任务名长度:任务名最长的字符串长度*/
#define configMAX_TASK_NAME_LEN		                        ( 10 )
/*系统时钟节拍计数器数据类型:为1使用16位无符号数,为0使用32位无符号数*/
#define configUSE_16_BIT_TICKS		                        0
/*空闲任务和与空闲任务同优先级的任务之间的切换:为1不等空闲任务时间片用完,就可立即切换到与空闲任
务同优化级的用户任务*/
#define configIDLE_SHOULD_YIELD		                        1
/*信号量配置:为1使用,为0不使用*/
#define configUSE_MUTEXES                                   1
#define configUSE_RECURSIVE_MUTEXES                         1
#define configUSE_COUNTING_SEMAPHORES                       1
/*队列记录数:记录的队列和信号量最大数目*/
#define configQUEUE_REGISTRY_SIZE                           8
/*任务标签:为1使用,为0不使用*/
#define configUSE_APPLICATION_TASK_TAG                      0
/*钩子函数:为1使能钩子函数,钩子函数需要由用户实现,为0不使能钩子函数*/
#define configUSE_IDLE_HOOK			                        0
#define configUSE_TICK_HOOK			                        0
#define configUSE_MALLOC_FAILED_HOOK                        0
#define configCHECK_FOR_STACK_OVERFLOW                      0


/*------------------------------------------------------协程配置------------------------------------------------------*/
/*是否使用协程:为0不使用,为1使用,在抢占式调度方式中也可使用协程*/
#define configUSE_CO_ROUTINES                               0
/*协程的有效优先级数量*/
#define configMAX_CO_ROUTINE_PRIORITIES                     ( 2 )


/*------------------------------------------------------任务运行信息配置------------------------------------------------------*/
/*可视化跟踪和调试及时间统计:为1启用,为0不启用*/
#define configUSE_TRACE_FACILITY                            1
#define configUSE_STATS_FORMATTING_FUNCTIONS                1
#define configGENERATE_RUN_TIME_STATS                       0

/*------------------------------------------------------软件定时器配置------------------------------------------------------*/
/*是否使用软件定时器功能:为1使用*/
#define configUSE_TIMERS                                    1
/*软件定时器服务任务的默认优先级*/
#define configTIMER_TASK_PRIORITY                           ( 2 )
/*软件定时器命令队列长度*/
#define configTIMER_QUEUE_LENGTH                            10
/*软件定时器服务任务堆栈大小*/
#define configTIMER_TASK_STACK_DEPTH                        ( configMINIMAL_STACK_SIZE * 2)


/*------------------------------------------------------可选API函数配置------------------------------------------------------*/
#define INCLUDE_vTaskPrioritySet                 1        /*任务优先级设置*/
#define INCLUDE_uxTaskPriorityGet                1        /*任务优先级获取*/
#define INCLUDE_vTaskDelete                      1        /*任务删除*/
#define INCLUDE_vTaskSuspend                     1        /*任务挂起*/
#define INCLUDE_vTaskDelayUntil                  1        /*绝对延时阻塞 */
#define INCLUDE_vTaskDelay                       1        /*相对延时阻塞*/
#define INCLUDE_xTaskGetSchedulerState           1        /*获取调度器状态*/
#define INCLUDE_xTaskGetCurrentTaskHandle        1        /*获取当前任务句柄*/
#define INCLUDE_uxTaskGetStackHighWaterMark      1        /*获取任务堆栈高水位线*/
#define INCLUDE_xTaskGetIdleTaskHandle           1        /*获取空闲任务句柄*/
#define INCLUDE_xTimerGetTimerDaemonTaskHandle   1        /*获取软件定时器服务句柄*/
#define INCLUDE_pcTaskGetTaskName                1        /*获取任务名*/


/*------------------------------------------------------与实际硬件中断服务函数相关的配置------------------------------------------------------*/
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler




/*------------------------------------------------------与ARM Cortex-M特定硬件相关的中断配置------------------------------------------------------*/
#define configKERNEL_INTERRUPT_PRIORITY 		255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	191 /* equivalent to 0xb0, or priority 11. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY	15

#endif


有一些配置宏如果在上面的配置文件没有定义,则会在FreeRTOS.h头文件自动定义给出默认值。

6. 总结

FreeRTOS是一个可裁剪和配置的嵌入式实时操作系统,其裁剪和配置通过FreeRTOSConfig.h头文件实现,每个FreeRTOS项目中必须有一个FreeRTOSConfig.h文件,FreeRTOS通过以INCLUDE_和config_开始的宏进行裁剪和配置。configUSE_PREEMPTION 决定了内核的调度方式,configTICK_RATE_HZ决定了系统时钟节拍,configTOTAL_HEAP_SIZE 决定了用于进行动态内存分配的堆内存大小,configUSE_16_BIT_TICKS 决定了是否使用32位处理器,这些宏在配置时要格外关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值