微软OneNote客户预览版学习工具下载(暂未上线):教学好帮手
873
2022-05-29
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
下面将对某些额外需要注意的进行另外注释;
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; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
7 总结
如果是学习FreRTOS的初期,只需要了解几个比价关键的配置即可,随着后期对该系统功能了解的深入,在系统的剪裁,RAM和ROM的优化上就可以进一步的了解,另外也可以参考https://www.freertos.org/a00110.html,
嵌入式
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。