【FreeRTOS学习05】深度解剖FreeRTOSConfig.h实现对系统的自定义剪裁
ROM/RAM太小,因此要对系统进行剪裁;
相关文章
【FreeRTOS实战汇总】小白博主的RTOS学习实战快速进阶之路(持续更新)
文章目录
- 1 系统的剪裁
- 2 FreeRTOSConfig.h
- 3 应用相关配置
- configUSE_PREEMPTION
- configMAX_PRIORITIES
- configMINIMAL_STACK_SIZE
- configUSE_16_BIT_TICKS
- configUSE_CO_ROUTINES
- configMAX_CO_ROUTINE_PRIORITIES
- 4 内存管理配置
- configSUPPORT_STATIC_ALLOCATION
- configSUPPORT_DYNAMIC_ALLOCATION
- configTOTAL_HEAP_SIZE
- configAPPLICATION_ALLOCATED_HEAP
- 5 hook 钩子函数
- configUSE_TICK_HOOK
- configUSE_IDLE_HOOK
- configUSE_MALLOC_FAILED_HOOK
- configUSE_DAEMON_TASK_STARTUP_HOOK
- 6 功能选配
- 7 总结
1 系统的剪裁
嵌入式系统通常都支持用户自定义进行剪裁,比较常见的Linux系统通过Kbuild在构建系统的时候进行剪裁,同样,国产的RT-Thread也支持Kbuild,可以很方便地通过menuconfig进行内核的剪裁,具体如下所示;

另外也支持通过对config文件进行配置,Linux的内核构建过程可以参考文章《探索Linux内核:Kconfig / kbuild的秘密》;
FreeRTOS支持使用FreeRTOSConfig.h配置文件进行定制,下面有几点需要注意的地方;
- 每个FreeRTOS应用程序的预处理器必须包含头文件
FreeRTOSConfig.h; FreeRTOSConfig.h是根据用户需求而进行定制产生的文件,它应位于应用程序的目录中,而不是RTOS内核代码的目录;FreeRTOS源码中的每一个demo程序都有属于自己的FreeRTOSConfig.h文件,如果一下配置选项被省略,那这些设置为默认值;- 用户通过修改
FreeRTOSConfig.h头文件中的宏定义,从而删减系统的模块,设置任务栈空间大小,设置系统分配的堆大小等等,下面配合源码进行详细解析。
2 FreeRTOSConfig.h
这里先找到文件FreeRTOSConfig.h,这个FreeRTOS工程是通过CubeIDE进行快速整合的,具体可以参考《【FreeRTOS学习01】CubeIDE快速整合FreeRTOS创建第一个任务》;工程结构如下图所示;

本文的FreeRTOSConfig.h头文件是根据集成在CubeIDE中的CubeMX插件自动生成的,源码如下所示;
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/* Ensure definitions are only used by the compiler, and not by the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
extern uint32_t SystemCoreClock;
void xPortSysTickHandler(void);
#endif
#define configUSE_PREEMPTION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configUSE_IDLE_HOOK 0 //
#define configUSE_TICK_HOOK 0 //
#define configCPU_CLOCK_HZ ( SystemCoreClock ) //输入以Hz为单位的CPU频率:例如 72Mb->72000000
#define configTICK_RATE_HZ ((TickType_t)1000) //输入以Hz为单位的滴答中断频率
#define configMAX_PRIORITIES ( 7 ) //应用程序任务可用的优先级数
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)15360)
#define configMAX_TASK_NAME_LEN ( 16 ) //创建任务时,任务的名称允许的最大长度
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1 //使用互斥功能
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 0
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
/* IMPORTANT: This define is commented when used with STM32Cube firmware, when the timebase source is SysTick,
to prevent overwriting SysTick_Handler defined within STM32Cube HAL */
/* #define xPortSysTickHandler SysTick_Handler */
#endif /* FREERTOS_CONFIG_H */
下面将对某些额外需要注意的进行另外注释;
3 应用相关配置
configUSE_PREEMPTION
这个宏定义来选择当前系统任务之间的调度算法;
- 设置为
1,则表示选择RTOS为抢占式调度; - 设置为
0,则表示调度算法为时间片调度;
通常这里需要设置为抢占式调度,一般设置为
1
configMAX_PRIORITIES
应用程序任务可用 的优先级数,任意数量的任务可以共享相同的优先级。协同例程(Co-routines)分别进行优先级排序,可以参考configMAX_CO_ROUTINE_PRIORITIES;
每个可用的优先级都会消耗RTOS内核中的RAM,因此该值不应设置为高于应用程序实际需要的值;
configMINIMAL_STACK_SIZE
空闲任务使用的堆栈大小;通常,不应将此值从演示应用程序随附的FreeRTOSConfig.h文件中为您所使用的端口设置的值中减少。
xTaskCreate()和 xTaskCreateStatic()函数的堆栈大小参数一样,堆栈大小以字而不是字节,如果放在堆栈上的每个单元都是32位,堆栈大小100则表示400字节,4bytes等于32bit;
configUSE_16_BIT_TICKS
- 设置为
1:TickType_t被定义(类型定义)为无符号的16位类型; - 设置为
0:TickType_t被定义(类型定义)为无符号的32位类型;
当系统是8位或16位的结构时,使用这个设置,可以提高能;
configUSE_CO_ROUTINES
- 设置为
1可在构建中包括协同例程功能; - 设置为
0可从构建中省略协同例程功能;
要包含协例程,必须在项目中包含
croutine.c
configMAX_CO_ROUTINE_PRIORITIES
应用程序协同例程可用的优先级数。任意数量的协同例程可以共享相同的优先级。任务分别进行优先级排序-请参阅configMAX_PRIORITIES
4 内存管理配置
configSUPPORT_STATIC_ALLOCATION
- 设置为
1:则可以使用程序中预先分配好的RAM创建RTOS对象; - 设置为
0:只能使用从FreeRTOS堆分配的RAM创建RTOS对象;
如果未定义configSUPPORT_STATIC_ALLOCATION,则默认为0
如果将configSUPPORT_STATIC_ALLOCATION设置为1,则应用程序编写器还必须提供两个回调函数:- -
vApplicationGetIdleTaskMemory():用于提供RTOS空闲任务的内存;vApplicationGetTimerTaskMemory():用于提供RTOS守护程序/计时器服务任务(如果configUSE_TIMERS设置为1)的内存: 。
这个在移植的时候可能也会遇到,具体如下所示;
/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
used by the Idle task. */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
function then they must be declared static – otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* Pass out a pointer to the StaticTask_t structure in which the Idle task’s
state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task’s stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*———————————————————–*/
/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
application must provide an implementation of vApplicationGetTimerTaskMemory()
to provide the memory that is used by the Timer service task. */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
/* If the buffers to be provided to the Timer task are declared inside this
function then they must be declared static – otherwise they will be allocated on
the stack and so not exists after this function exits. */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
/* Pass out a pointer to the StaticTask_t structure in which the Timer
task’s state will be stored. */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* Pass out the array that will be used as the Timer task’s stack. */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
Note that, as the array is necessarily of type StackType_t,
configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
configSUPPORT_DYNAMIC_ALLOCATION
- 设置为
1:则可以使用从FreeRTOS堆自动分配的RAM创建RTOS对象; - 设置为
0:则只能使用应用程序编写器提供的RAM创建RTOS对象;
如果未定义configSUPPORT_DYNAMIC_ALLOCATION,则默认为1;
configTOTAL_HEAP_SIZE
设置FreeRTOS中堆可用的RAM总量;
仅当configSUPPORT_DYNAMIC_ALLOCATION设置为1;且使用FreeRTOS源代码下载中提供的示例内存分配方案(heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c)时,才会配置这个值;
configAPPLICATION_ALLOCATED_HEAP
- 设置为
0:FreeRTOS堆由FreeRTOS声明,并由链接器放置在内存中; - 设置为
1:可以使堆改为由用户程序进行设置,允许将堆放置在内存中任意位置;
如果使用
heap_1.c,heap_2.c或heap_4.c,并且configAPPLICATION_ALLOCATED_HEAP设置为1,那么应用程序编写器必须提供一个uint8_t数组,其名称和维数如下所示。
uint8_t ucHeap [configTOTAL_HEAP_SIZE];
该数组将被作为FreeRTOS的堆来使用。如何将数组放置在特定的内存位置取决于所使用的编译器–请参阅编译器的文档。
5 hook 钩子函数
钩子函数的本质就是回调函数,有下面四个函数;
configUSE_TICK_HOOK;configUSE_IDLE_HOOK;configUSE_MALLOC_FAILED_HOOK;configUSE_DAEMON_TASK_STARTUP_HOOK;
具体参考hook函数;
configUSE_TICK_HOOK
程序必须为hook函数提供以下原型:
void vApplicationTickHook( void );
configUSE_IDLE_HOOK
configUSE_IDLE_HOOK设置为1,才会调用IDLE_HOOK,设置此选项后,应用程序必须为hook函数提供以下原型:
void vApplicationIdleHook(void);
configUSE_MALLOC_FAILED_HOOK
程序必须为hook函数提供以下原型:
void vApplicationMallocFailedHook( void );
configUSE_DAEMON_TASK_STARTUP_HOOK
RTOS守护程序任务与计时器服务任务相同。有时将其称为守护程序任务,因为该任务现在不仅用于维护计时器,还用于更多任务。
将configUSE_DAEMON_TASK_STARTUP_HOOK设置为1,则在守护程序任务首次开始执行时,将立即调用守护程序任务启动钩子函数。应用程序的初始化代码如果需要放在该钩子函数中,则该功能将很有用,这将允许初始化代码利用RTOS功能。
应用程序编写器必须使用以下名称提供原型的“守护程序任务”启动挂钩函数的实现。
void vApplicationDaemonTaskStartupHook( void );
6 功能选配
如果以下函数没有被使用到,已经设置为0,使其不被包含到应用程序中,从而减少程序的应用空间;
#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_xTaskGetIdleTaskHandle 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 0
#define INCLUDE_xTaskAbortDelay 0
#define INCLUDE_xTaskGetHandle 0
#define INCLUDE_xTaskResumeFromISR 1
7 总结
如果是学习FreRTOS的初期,只需要了解几个比价关键的配置即可,随着后期对该系统功能了解的深入,在系统的剪裁,RAM和ROM的优化上就可以进一步的了解,另外也可以参考https://www.freertos.org/a00110.html,
【FreeRTOS学习05】深度解剖FreeRTOSConfig.h实现对系统的自定义剪裁的更多相关文章
- FreeRTOS Customisation -- FreeRTOSConfig.h
http://www.freertos.org/a00110.html FreeRTOS is customised using a configuration file called FreeRTO ...
- freeRTOSConfig.h文件对FreeRTOS进行系统配置
FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制.每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核.这个配置文件是针 ...
- FreeRTOS学习笔记——FreeRTOS 任务基础知识
RTOS 系统的核心就是任务管理,FreeRTOS 也不例外,而且大多数学习RTOS 系统的工程师或者学生主要就是为了使用RTOS 的多任务处理功能,初步上手RTOS 系统首先必须掌握的也是任务的创建 ...
- C语言深度解剖读书笔记
开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有一段时间了,一直没有时间来写这篇博客.正巧还刚刚看完了国嵌唐老师的C语言视频,觉得两者是异曲同工,所以就把两者一起记录下 ...
- 【转】 C语言深度解剖读书笔记(1.关键字的秘密)
本文出处:http://blog.csdn.net/mbh_1991/article/details/10149805 开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有 ...
- 【FreeRTOS学习02】源码结构/数据类型/命名规则总结
个人不是很喜欢FreeRTOS的编程风格,但是没办法,白嫖人家的东西,只能忍了,这里先简单总结一下: 相关文章 [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 ...
- 【FreeRTOS学习03】小白都能懂的Task Management 任务管理基本概念介绍
在FreeRTOS中,线程的术语又可以被称之为任务,或许这样更加合适,本文将介绍任务的创建/删除,任务参数的使用,以及任务优先级: 1 软实时和硬实时 硬实时系统的任务运行正确性与响应时限是紧密相关的 ...
- FreeRTOS学习及移植笔记之二:在IAR和STM32F103VET上移植FreeRTOS
上一次,我们简单的测试了FreeRTOS的基于IAR EWARM v6.4和STM32F103VET6平台的Demo,对其有了一个基本认识.接下来我们开始自己移植FreeRTOS的过程. 1.创建一个 ...
- C语言深度解剖读书笔记(6.函数的核心)
对于本节的函数内容其实就没什么难点了,但是对于函数这节又涉及到了顺序点的问题,我觉得可以还是忽略吧. 本节知识点: 1.函数中的顺序点:f(k,k++); 这样的问题大多跟编译器有关,不要去刻意追求 ...
随机推荐
- 数据结构之栈—强大的四则复杂运算计算器(超过windows自带的科学计算器)【中缀转后缀表达式】
比windows自带计算器还强的四则复杂运算计算器! 实测随机打出两组复杂算式:-7.5 * 6 / ( -2 + ( -6.5 - -5.22 ) )与7.5+-3*8/(7+2) windows ...
- B. 蚂蚁觅食(二)
B. 蚂蚁觅食(二) 单点时限: 1.0 sec 内存限制: 512 MB 一只饥饿的小蚂蚁外出觅食,幸运的的小蚂蚁发现了好多食物.但是这些食物位于一个N∗M的方格魔法阵的右下角,而小蚂蚁位于方格法阵 ...
- selenium 执行js代码
获取一个input输入框的值: JavascriptExecutor js =(JavascriptExecutor) driver; merchatName=js.executeScript(&qu ...
- [YII2] 去除自带头部以及底部右下角debug调试功能
YII2 去除自带头部以及底部右下角debug调试功能
- git flow配置问题
Mac使用 git flow 的时候,当 -m 进行换行有时消息会被截断,怎么解决? 原因: brew 上的 gnu-getopt 这个包未配置好 步骤: 1. 在 ~/.gitflow_export ...
- 前端基础-HTML(1)
1.浏览器: 1.1 浏览器内核: 渲染引擎和JS引擎 渲染引擎:负责页面内容的在(html,xml,图像等).整理讯息(加入css等),以及计算网页的显示方式,然后输出至显示器后者打印机 JS引擎: ...
- Spring框架中文件目录遍历漏洞 Directory traversal in Spring framework
官方给出的描述是Spring框架中报告了一个与静态资源处理相关的目录遍历漏洞.某些URL在使用前未正确加密,使得攻击者能够获取文件系统上的任何文件,这些文件也可用于运行SpringWeb应用程序的进程 ...
- 【JAVA基础】09 Eclipse
1. Java开发工具 操作系统自带的记事本软件 高级记事本软件 集成开发环境 IDE (Integrated Development Environment) Eclipse和MyEclipse的区 ...
- 基于JSR-356实现的Tyrus WebSocket框架的消息传递机制初步了解
对阻塞.非阻塞,同步.异步初步了解了,不是太明白,其中大多数将的是对于CPU的使用率及对一个事件的处理效率. 阻塞与非阻塞各有优缺点,在知乎上也看到了下面的结论: 在处理 IO 的时候,阻塞和非阻塞都 ...
- Cobbler自动装机试验
Cobbler自动装机简介:Cobbler是一个使用Python开发的开源项目,通过将部署系统所涉及的所有服务集中在一起,来提供一个全自动的批量快速建立Linux系统的网络安装环境.Cobbler提供 ...