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. go开发包下载,IDE工具下载,基础配置命令

    目录 go语言介绍 go开发包下载 命令介绍 配置 修改配置 golandIDE工具下载 编译并执行命令 命令 go语言介绍 # 1 诞生于 2009年,10年的时间,非常新的语言,天然支持并发,很新 ...

  2. OpenAL试水

    参考了https://wysaid.org/976.html. 这个博客给了一个EGE+OpenAL的demo和源代码.一开始没注意,博主也没有给EGE相关信息.会找不到EGE相关头文件,建议如果要二 ...

  3. [html][javascript] 关于SVG环形进度条

    下面是个例子: <style> .demo2{ transform-origin: center; transform: rotate(-90deg); transition: strok ...

  4. [腾讯云]简单在腾讯云 CenTOS7.0 安装Nginx,Mysql(MariaDB),Memcache,解析PHP!

    1.安装LNMP之前要安装EPEL,以便安装源以外的软件,如Nginx,phpMyAdmin等. yum install epel-release 2.安装Nginx a) yum install n ...

  5. 转载-linux内核长什么样

    来源:Linux中国 今天,我来为大家解读一幅来自 TurnOff.us 的漫画 "InSide The Linux Kernel" . TurnOff.us是一个极客漫画网站,作 ...

  6. JS+Selenium+excel追加写入,使用python成功爬取京东任何商品~

    之前一直是requests库做爬虫,这次尝试下使用selenium做爬虫,效率不高,但是却没有限制,文章是分别结合大牛的selenium爬虫以及excel追加写入操作而成,还有待优化,打算爬取更多信息 ...

  7. 计算某天的下一天:黑盒测试之等价类划分+JUnit参数化测试

    题目要求 测试以下程序:该程序有三个输入变量month.day.year(month.day和year均为整数值,并且满足:1≤month≤12.1≤day≤31和1900≤year≤2050),分别 ...

  8. python爬虫实战之爬取智联职位信息和博客文章信息

    1.python爬取招聘信息 简单爬取智联招聘职位信息 # !/usr/bin/env python # -*-coding:utf-8-*- """ @Author  ...

  9. DZ注册登录流程梳理

    用户注册流程第一步:/source/class/class_member.php: on_register注册入口 if(!$activation) {//不为空,说明用户已经注册过 //将用户注册到 ...

  10. [Qt] 通过socket将另一个程序的某个窗口调到最前端

    @ // THIS IS A HACK: // from QT documentation: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...