ROM/RAM太小,因此要对系统进行剪裁;

相关文章

【FreeRTOS实战汇总】小白博主的RTOS学习实战快速进阶之路(持续更新)

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.cheap_2.cheap_3.cheap_4.cheap_5.c)时,才会配置这个值;

configAPPLICATION_ALLOCATED_HEAP

  • 设置为0FreeRTOS堆由FreeRTOS声明,并由链接器放置在内存中;
  • 设置为1:可以使堆改为由用户程序进行设置,允许将堆放置在内存中任意位置;

如果使用heap_1.cheap_2.cheap_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实现对系统的自定义剪裁的更多相关文章

  1. FreeRTOS Customisation -- FreeRTOSConfig.h

    http://www.freertos.org/a00110.html FreeRTOS is customised using a configuration file called FreeRTO ...

  2. freeRTOSConfig.h文件对FreeRTOS进行系统配置

    FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制.每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核.这个配置文件是针 ...

  3. FreeRTOS学习笔记——FreeRTOS 任务基础知识

    RTOS 系统的核心就是任务管理,FreeRTOS 也不例外,而且大多数学习RTOS 系统的工程师或者学生主要就是为了使用RTOS 的多任务处理功能,初步上手RTOS 系统首先必须掌握的也是任务的创建 ...

  4. C语言深度解剖读书笔记

    开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有一段时间了,一直没有时间来写这篇博客.正巧还刚刚看完了国嵌唐老师的C语言视频,觉得两者是异曲同工,所以就把两者一起记录下 ...

  5. 【转】 C语言深度解剖读书笔记(1.关键字的秘密)

    本文出处:http://blog.csdn.net/mbh_1991/article/details/10149805 开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有 ...

  6. 【FreeRTOS学习02】源码结构/数据类型/命名规则总结

    个人不是很喜欢FreeRTOS的编程风格,但是没办法,白嫖人家的东西,只能忍了,这里先简单总结一下: 相关文章 [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 ...

  7. 【FreeRTOS学习03】小白都能懂的Task Management 任务管理基本概念介绍

    在FreeRTOS中,线程的术语又可以被称之为任务,或许这样更加合适,本文将介绍任务的创建/删除,任务参数的使用,以及任务优先级: 1 软实时和硬实时 硬实时系统的任务运行正确性与响应时限是紧密相关的 ...

  8. FreeRTOS学习及移植笔记之二:在IAR和STM32F103VET上移植FreeRTOS

    上一次,我们简单的测试了FreeRTOS的基于IAR EWARM v6.4和STM32F103VET6平台的Demo,对其有了一个基本认识.接下来我们开始自己移植FreeRTOS的过程. 1.创建一个 ...

  9. C语言深度解剖读书笔记(6.函数的核心)

    对于本节的函数内容其实就没什么难点了,但是对于函数这节又涉及到了顺序点的问题,我觉得可以还是忽略吧. 本节知识点: 1.函数中的顺序点:f(k,k++);  这样的问题大多跟编译器有关,不要去刻意追求 ...

随机推荐

  1. 小说免费看!python爬虫框架scrapy 爬取纵横网

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 风,又奈何 PS:如有需要Python学习资料的小伙伴可以加点击下方 ...

  2. 字符串的常用操作和方法(Python入门教程)

    字符串的常用操作 很好理解 字符串可以用 ' + ' 连接,或者乘一个常数重复输出字符串 字符串的索引操作 通过一对中括号可以找到字符串中的某个字符 可以通过正负数双向操作噢 用一个中括号来实现 为什 ...

  3. Oracle计算数值型的幂次方——POWER()

    Oracle计算数值型的幂次方 简介:幂次方就是幂函数的变形,在POWER(value1,value2)中,value1就是函数的底数,value2就是函数的指数.如:POWER(value1,val ...

  4. [PHP] 文件创建、写入、读取

    创建$p = fopen('text.txt','a+b'); 写入第一种方式//var_export方式存储数组到文件中 //这中方式存浮点型数据,存储后会多很多数字!只适合简单的存储吧!我感觉! ...

  5. redis: 主从复制和哨兵模式(十三)

    redis 主从复制 最低要求是一主二从(一个主机和两个从机) 主机才能写 从机只能读 只要从机连接到主机 数据就会全量复制到从机 环境配置(同一台机器) 1:配置文件 redis.conf配置如下: ...

  6. 报错:require_once cannot allocate memory----php,以前自己弄的稍微有点特殊的开发环境

    最近出现过一个问题,值得记录 类似于这样的报错的问题: Warning: require_once(/www/app/somecomponent.php): failed to open stream ...

  7. Python模块---制作新冠疫情世界地图()

    目录 pyecharts模块 简介 安装pyecharts 测试pyecharts模块 pyecharts实战:绘制新冠肺炎疫情地图 需求分析 请求数据 提取数据 处理数据 制作可视化地图 设置可视化 ...

  8. sqlliab7-8

    less-7 https://www.jianshu.com/p/20d1282e6e1d ?id=0')) union select 1,'2','<?php @eval($_POST[&qu ...

  9. PHP Ajax 跨域问题解决方案

    本文通过设置Access-Control-Allow-Origin来实现跨域. 例如:客户端的域名是client.0751.tv,而请求的域名是server.0751.tv. 如果直接使用ajax访问 ...

  10. 作业3-k均值算法

    4. 作业: 1). 扑克牌手动演练k均值聚类过程:>30张牌,3类 2). *自主编写K-means算法 ,以鸢尾花花瓣长度数据做聚类,并用散点图显示.(加分题) 3). 用sklearn.c ...