freeRTOS通过FreeRTOSConfig.h配置文件实现定制化。每个分支都需要包含这个文件。FreeRTOSConfig.h实现了RTOS内核的裁剪,需要根据实际应用情况合理配置,也因此,这个文件是应用相关的,而非RTOS内核。

每个demo例程中都有一个特定的配置文件,有些分支因为太老了可能没有全部包含所有的配置选项,freeRTOS源码中会将那些无配置的配置选项设定为系统的默认值

下面是一个典型的配置文件配置代码:

  1. #ifndef FREERTOS_CONFIG_H
  2. #define FREERTOS_CONFIG_H
  3. /* 包含应用所需的头文件 */
  4. #include "something.h"
  5. #define configUSE_PREEMPTION 1
  6. #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
  7. #define configUSE_TICKLESS_IDLE 0
  8. #define configCPU_CLOCK_HZ 60000000
  9. #define configTICK_RATE_HZ 250
  10. #define configMAX_PRIORITIES 5
  11. #define configMINIMAL_STACK_SIZE 128
  12. #define configMAX_TASK_NAME_LEN 16
  13. #define configUSE_16_BIT_TICKS 0
  14. #define configIDLE_SHOULD_YIELD 1
  15. #define configUSE_TASK_NOTIFICATIONS 1
  16. #define configUSE_MUTEXES 0
  17. #define configUSE_RECURSIVE_MUTEXES 0
  18. #define configUSE_COUNTING_SEMAPHORES 0
  19. #define configUSE_ALTERNATIVE_API 0 /* 过时的! */
  20. #define configQUEUE_REGISTRY_SIZE 10
  21. #define configUSE_QUEUE_SETS 0
  22. #define configUSE_TIME_SLICING 0
  23. #define configUSE_NEWLIB_REENTRANT 0
  24. #define configENABLE_BACKWARD_COMPATIBILITY 0
  25. #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5
  26. /* 内存分配相关的配置 */
  27. #define configSUPPORT_STATIC_ALLOCATION 1
  28. #define configSUPPORT_DYNAMIC_ALLOCATION 1
  29. #define configTOTAL_HEAP_SIZE 10240
  30. #define configAPPLICATION_ALLOCATED_HEAP 1
  31. /* 钩子函数相关配置*/
  32. #define configUSE_IDLE_HOOK 0
  33. #define configUSE_TICK_HOOK 0
  34. #define configCHECK_FOR_STACK_OVERFLOW 0
  35. #define configUSE_MALLOC_FAILED_HOOK 0
  36. #define configUSE_DAEMON_TASK_STARTUP_HOOK 0
  37. /* 运行时与任务状态采集相关配置*/
  38. #define configGENERATE_RUN_TIME_STATS 0
  39. #define configUSE_TRACE_FACILITY 0
  40. #define configUSE_STATS_FORMATTING_FUNCTIONS 0
  41. /* 协程*/
  42. #define configUSE_CO_ROUTINES 0
  43. #define configMAX_CO_ROUTINE_PRIORITIES 1
  44. /* 软件定时器 */
  45. #define configUSE_TIMERS 1
  46. #define configTIMER_TASK_PRIORITY 3
  47. #define configTIMER_QUEUE_LENGTH 10
  48. #define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
  49. /* 中断嵌套 */
  50. #define configKERNEL_INTERRUPT_PRIORITY [dependent of processor]
  51. #define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application]
  52. #define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application]
  53. /* 用于在开发器件捕获错误的宏*/
  54. #define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
  55. /* FreeRTOS MPU 具体配置. */
  56. #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
  57. /* 可选功能*/
  58. #define INCLUDE_vTaskPrioritySet 1
  59. #define INCLUDE_uxTaskPriorityGet 1
  60. #define INCLUDE_vTaskDelete 1
  61. #define INCLUDE_vTaskSuspend 1
  62. #define INCLUDE_xResumeFromISR 1
  63. #define INCLUDE_vTaskDelayUntil 1
  64. #define INCLUDE_vTaskDelay 1
  65. #define INCLUDE_xTaskGetSchedulerState 1
  66. #define INCLUDE_xTaskGetCurrentTaskHandle 1
  67. #define INCLUDE_uxTaskGetStackHighWaterMark 0
  68. #define INCLUDE_xTaskGetIdleTaskHandle 0
  69. #define INCLUDE_eTaskGetState 0
  70. #define INCLUDE_xEventGroupSetBitFromISR 1
  71. #define INCLUDE_xTimerPendFunctionCall 0
  72. #define INCLUDE_xTaskAbortDelay 0
  73. #define INCLUDE_xTaskGetHandle 0
  74. #define INCLUDE_xTaskResumeFromISR 1
  75. /* 追踪宏的定义包含可以在这里包含 */
  76. #endif /* FREERTOS_CONFIG_H */

config参数

configUSE_PREEMPTION

设置为1,使用抢占式调度(强制切换到高优先级就绪任务);设置为0,使用合作式调度(任务主动交出CPU使用权)。

configUSE_PORT_OPTIMISED_TASK_SELECTION

一些freeRTOS支持的处理器可以通过两种方法选择下一个执行的任务—通用方法和特有方法。

通用方法

  • configUSE_PORT_OPTIMISED_TASK_SELECTION设置为0的时候,或者特有方法没有实现的时候
  • 可以在所有freeRTOS支持的分支上使用
  • 完全使用C语言实现,因此在效率上比特有方法低
  • 可用优先级的上限没有限制

特有方法

  • 不是所有的处理器上都可用
  • configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1
  • 使用一条或多条特地给汇编指令实现
  • 比通用方法高效
  • 通常优先级的最大数量限制在32

configUSE_TICKLESS_IDLE

configUSE_TICKLESS_IDLE设置为1使用低功耗低节拍模式,或者设置为0使节拍中断移植运行。低功耗低节拍的实现不是所有的处理器都支持。

configUSE_IDLE_HOOK

设置为1,使用空闲任务的钩子函数,设置为0,不使用。

configUSE_MALLOC_FAILED_HOOK

在创建任务、队列、信号量的时候,内核使用pvPortMalloc()从堆上分配内存。官方源码中提供四个内存分配机制的例程。这种机制在heap_1.c, heap_2.c, heap_3.c, heap_4.cheap_5.c中分别实现。configUSE_MALLOC_FAILED_HOOK之与使用这几种内存分配机制时有关。

如果定义并配置了内存分配失败钩子函数,freeRTOS因为内存不足,在调用pvPortMalloc()后返回NULL,此时钩子函数将自动调用。

如果将configUSE_MALLOC_FAILED_HOOK设置为1使用内存分配失败钩子函数,则必须实现这个钩子函数的定义:

void vApplicationMallocFailedHook( void );

configUSE_DAEMON_TASK_STARTUP_HOOK

如果configUSE_TIMERSconfigUSE_DAEMON_TASK_STARTUP_HOOK同时设置为1,这用户需要声明具有如下形式的钩子函数,这个钩子函数会在软件定时器服务任务第一次执行时被调用,因此,这个钩子函数可以做一些应用程序的初始化任务。

void void vApplicationDaemonTaskStartupHook( void );

configUSE_TICK_HOOK

设置为1,使用节拍钩子函数,设置为0,将忽略节拍钩子函数。节拍钩子函数在节拍中断中调用,因此务必短小精悍。

configCPU_CLOCK_HZ

用以产生节拍中断的内部时钟频率,通常与CPU时钟频率相同。为了正确配置定时器外设,这个值是必需要的。

configTICK_RATE_HZ

RTOS节拍中断频率。节拍中断用以测量时间,因此频率越高,测量精度越高。但是,高频率的节拍中断也意味着内核将占用更多的CPU时间,导致效率降低。RTOS使用的例程中的节拍频率为1000Hz。这个频率用来测试内核,通常比需要的高。

多个任务可以共享同一个优先级,RTOS调度器将在每个节拍时进行任务切换,高频率的节拍因此会减少每个任务的时间片。

configMAX_PRIORITIES

用来配置任务可用优先级的最大数量,多个任务可以共用一个优先级。协程的优先级与任务时分开的,使用configMAX_CO_ROUTINE_PRIORITIES配置最大协程可用优先级数量。

在内核中,每个可用的优先级数量都会消耗RAM,即使这个优先级是没有使用的。因此强烈建议,在实际应用中,这个最大优先级数量应该与实际任务数量相同

configMINIMAL_STACK_SIZE

配置空闲任务使用的占空间大小。与xTaskCreat()xTaskCreatStatic()类似,栈空间的大小以字(word)为单位,而不是字节(byte),如果栈内成员放置在32-bit的栈中,栈大小100意味着400字节。

configMAX_TASK_NAME_LEN

任务名称的最大长度,包括最后面的终止字符,超出部分会被截断。

configUSE_TRACE_FACILITY

如果你希望包括其他结构成员和功能,以协助执行可视化和跟踪设置为1。

configUSE_STATS_FORMATTING_FUNCTIONS

configUSE_TRACE_FACILITYconfigUSE_STATS_FORMATTING_FUNCTIONS同时设置为1将包含vTaskList()vTaskGetRunTimeStats()函数,设置为0,在编译的时候将忽略这两个函数。

configUSE_16_BIT_TICKS

时间在节拍中断中测量—代表从内核开始到每个节拍中断的时间间隔。节拍计数值通常保存在TickType_t类型的变量中。

configUSE_16_BIT_TICKS设置为1,将把TickType_t定义为无符号的16位类型。将configUSE_16_BIT_TICKS设置为0,把TickType_t定义为无符号的32位类型

使用16位类型可以改善在8位和16位架构上的表现,但是最大可以计的节拍数位65535,因此,假设节拍中断的频率位250Hz,最大的延时或者组鄂塞时间是262秒。

configIDLE_SHOULD_YIELD

这个参数控制处在空闲任务优先级的任务行为。只在下列条件下有效:

  • 使用抢占式调度器
  • 应用程序创建的任务在空闲任务的优先级上运行

如果configUSE_TIME_SLICING设置为1(或者未定义,使用内核默认值),拥有同一个优先级的任务将共享时间片。如果没有任务被抢占,那么可以认为每个任务拥有等量的时间片—优先级在空闲任务之上,情况也的确如此。

当任务与空闲任务共享优先级时,行为上会有些不同。如果configIDLE_SHOULD_YIELD设置为1,那么当处在空闲任务优先级的任务就绪时,会立即抢占空闲任务而得到执行。这是为了确保当应用程序就绪时,空闲任务所占用的时间打到最小。这种行为有时会产生意想不到的效果(取决于你的应用程序),如下图所示:

配置文件 - 图1

图上A、B、C时应用程序任务,I是空闲任务,T0…T6是任务切换的时刻,可以看出,在T2时刻,空闲任务因为A任务就绪而被切换到A任务中执行,导致A任务与其它任务相比获得的时间片要少。

可以通过以下方式避免上述现象:

  • 如果可以,使用空闲任务的钩子函数替代创建与空闲任务相同优先级的任务
  • 所有任务的优先级都比空闲任务高
  • 设置configIDLE_SHOULD_YIELD为0,直到空闲任务主动交出CPU使用权,再去执行其它任务,但是会导致空闲任务分配的时间比例增大

configUSE_TASK_NOTIFICATIONS

如果使用任务通知,需要将这个配置项设为1。

configUSE_MUTEXES

如果使用互斥量,将此配置项设为1。

configUSE_RECURSIVE_MUTEXES

如果使用递归互斥量,设为1 。

configUSE_COUNTING_SEMAPHORES

如果使用计数信号量,设为1 。

configUSE_ALTERNATIVE_API

设置为1,使用队列的另一组API,因为这组API已经不再使用,建议不要在新设计中使用。

configCHECK_FOR_STACK_OVERFLOW

如果设置为非0值,在栈溢出的时候调用栈溢出钩子函数。

configQUEUE_REGISTRY_SIZE

队列注册表有两个目的,都与RTOS的内核调试有关。

  • 为队列提供一个文本名称用在调试界面中区分队列
  • 包含用于定位队列和信号量的调试信息

队列注册表只在你使用内核调试的时候有用。

configQUEUE_REGISTRY_SIZE定义队列和信号量可以被注册的最大数量,可以通过 vQueueAddToRegistry()vQueueUnregisterQueue()`获得更多相关信息。

configUSE_QUEUE_SETS

设置为 1 将包含队列集( queue set )功能(可以阻塞或挂起在多个队列和信号量上)。详细细节可以参考”在多个RTOS对象上阻塞”章节。

configUSE_TIME_SLICING

默认情况下( configUSE_TIME_SLICING 未定义或者设置为1 ),freeRTOS将使用时间片的来进行基于优先级的抢占式调度。这意味这RTOS的调度器将一直执行的是拥有最高优先级的就绪任务,并且将在每个节拍中断中对优先级相同的任务进行切换。如果这个设置项设置为0,则不会使用时间片,即不会在节拍中断中切换同等优先级的任务。

configUSE_NEWLIB_REENTRANT

If configUSE_NEWLIB_REENTRANT is set to 1 then a newlib reent structure will be allocated for each created task. Note Newlib support has been included by popular demand, but is not used by the FreeRTOS maintainers themselves. FreeRTOS is not responsible for resulting newlib operation. User must be familiar with newlib and must provide system-wide implementations of the necessary stubs. Be warned that (at the time of writing) the current newlib design implements a system-wide malloc() that must be provided with locks.

configENABLE_BACKWARD_COMPATIBILITY

The FreeRTOS.h header file includes a set of #define macros that map the names of data types used in versions of FreeRTOS prior to version 8.0.0 to the names used in FreeRTOS version 8.0.0. The macros allow application code to update the version of FreeRTOS they are built against from a pre 8.0.0 version to a post 8.0.0 version without modification. Setting configENABLE_BACKWARD_COMPATIBILITY to 0 in FreeRTOSConfig.h excludes the macors from the build, and in so doing allowing validation that no pre version 8.0.0 names are being used.

configNUM_THREAD_LOCAL_STORAGE_POINTERS

设置任务的线程本地存储数组(thread local storage array)的索引号

configSUPPORT_STATIC_ALLOCATION

configSUPPORT_STATIC_ALLOCATION设置为1,则RTOS对象使用的RAM由应用程序编写者提供,设置为0,则由freeRTOS从堆上分配。该配置选项默认为0。

如果configSUPPORT_STATIC_ALLOCATION设置为1,应用程序编写者需要额外提供两个回调函数:vApplicationGetIdleTaskMemory()给空闲任务提供内存,vApplicationGetTimerTaskMemory()给软件定时器服务任务提供内存,如下例:

  1. /* vApplicationGetIdleTaskMemory() 给空闲任务提供内存 */
  2. void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
  3. StackType_t **ppxIdleTaskStackBuffer,
  4. uint32_t *pulIdleTaskStackSize )
  5. {
  6. /* 以数组内存分配的方式分配内存给空闲任务,注意,此处需要为static*,否则是在栈上申请的内存,在这个函数之外无法继续使用。*/
  7. static StaticTask_t xIdleTaskTCB;
  8. static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
  9. /* 传递空闲任务的TCB指针到StaticTask_t结构的缓存指针*/
  10. *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
  11. /* 将申请的内存传给空闲任务,用作空闲任务堆栈 */
  12. *ppxIdleTaskStackBuffer = uxIdleTaskStack;
  13. /* 传递空闲任务的栈大小,注意是以字(word)为单位 */
  14. *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  15. }
  16. /*-----------------------------------------------------------*/
  17. /* vApplicationGetTimerTaskMemory()
  18. 提供软件定时器的栈内存 */
  19. void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
  20. StackType_t **ppxTimerTaskStackBuffer,
  21. uint32_t *pulTimerTaskStackSize )
  22. {
  23. /* 道理和空闲任务内存分配相同,需要使用static方式申明 */
  24. static StaticTask_t xTimerTaskTCB;
  25. static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
  26. /* 传递软件定时器任务TCB指针 */
  27. *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
  28. /* 栈空间 */
  29. *ppxTimerTaskStackBuffer = uxTimerTaskStack;
  30. /* 以字(word)为单位的栈大小 */
  31. *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
  32. }

configSUPPORT_DYNAMIC_ALLOCATION

configSUPPORT_DYNAMIC_ALLOCATION设置为1,则内存分配在freeRTOS管理的堆(heap)上分配,如果设置为0,则内存分配由应用程序编写者提供。默认为1.

参考“静态分配与动态分配”。

configTOTAL_HEAP_SIZE

freeRTOS的可用堆内存大小。

这个值只在使用动态内存分配时有效,并且分配机制由应用程序选择的内存分配机制确定,详细可以参考”内存配置”部分。

configAPPLICATION_ALLOCATED_HEAP

默认情况下,freeRTOS的堆内存由freeRTOS申明,并且由链接器放置在具体的内存下,如果设置configAPPLICATION_ALLOCATED_HEAP为1,则允许堆内存由应用程序编写者自己提供,内存位置可以为内存中的任意位置。

如果使用heap_1.cheap_2.cheap_4.c,并且该设置项设置为1,则应用程序编写者必须提供类型为uint8_t的数组作为堆内存,这个数组在内存中的位置可以使用绝对定位。

uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]

configGENERATE_RUN_TIME_STATS

提供运行时间统计功能,详细可以参考”运行时间统计”。

configUSE_CO_ROUTINES

设置为1,使用协程(co-routine),设置为0将忽略协程函数。使用协程,需要包含croutine.c源文件。

configMAX_CO_ROUTINE_PRIORITIES

协程可用的优先级数量。协程之间可以共享优先级,协程的优先级与任务优先级独立。

configUSE_TIMERS

设置为1,使用软件定时器功能。

configTIMER_TASK_PRIORITY

软件定时器服务任务的优先级

configTIMER_QUEUE_LENGTH

软件定时器命令队列长度

configTIMER_TASK_STACK_DEPTH

软件定时器服务任务的栈空间深度

configKERNEL_INTERRUPT_PRIORITY configMAX_SYSCALL_INTERRUPT_PRIORITY 和 configMAX_API_CALL_INTERRUPT_PRIORITY

configKERNEL_INTERRUPT_PRIORITY设置项在某些处理器上使用,如 ARM Cortex-M3、PIC24、dsPIC、PCI32、SuperH 和 RX600。configMAX_SYSCALL_INTERRUPT_PRIORITY 设置项在 PIC32, RX600, ARM Cortex-A 和 ARM Cortex-M ports 上使用。

ARM Cortex-M3 和 ARM Cortex-M4 用户需要注意这部分内容最后的注意事项

configMAX_API_CALL_INTERRUPT_PRIORITY 和 configMAX_SYSCALL_INTERRUPT_PRIORITY 是新设置项,只在特定设备上使用。

configKERNEL_INTERRUPT_PRIORITY 需要设置为最低优先级。

注意,接下来讨论的API只有以FromISR结尾的才能在中断服务函数中调用。

只实现 configKERNEL_INTERRUPT_PRIORITY 的情况

configKERNEL_INTERRUPT_PRIORITY 设置RTOS内核使用的中断优先级。中断调用的API函数必须执行在这个优先级上,中断不会调用高于这个优先级的API,因此,在RTOS内核执行期间,这些API函数不会得到延期执行。

同事实现 configKERNEL_INTERRUPT_PRIORITY 和 configMAX_SYSCALL_INTERRUPT_PRIORITY 的情况

configKERNEL_INTERRUPT_PRIORITY 设置中断优先级,configMAX_SYSCALL_INTERRUPT_PRIORITY 设置中断安全API可以被调用的中断的最高优先级

当 configMAX_SYSCALL_INTERRUPT_PRIORITY 的优先级设置大于 configKERNEL_INTERRUPT_PRIORITY 时,可以实现中断嵌套,这意味着,RTOS内核无法完全禁用中断,即使处在临界代码段中。

简而言之,优先级比 configMAX_SYSCALL_INTERRUPT_PRIORITY 设置高的中断不能调用API,因为不会被RTOS内核延迟执行。

举例说明,假象一个处理器具有8个中断优先级,0最低,7最高,下图展示了哪些可以做哪些不可以做:

配置文件 - 图2

这些配置参数提供了很灵活的中断处理:

  • 中断处理可以交给任务来做。中断唤醒任务,中断服务函数本身应该约短越好,只用来捕捉数据,而处理交给任务来做—中断处理在时间上是连续的。好处在于,在任务处理执行时,所有的中断都可以保持使能。
  • 对于使用 configMAX_SYSCALL_INTERRUPT_PRIORITY 的处理器,优先级在 configMAX_SYSCALL_INTERRUPT_PRIORITY 和 RTOS 内核中断优先级之间的中断可以嵌套,也可以调用API。优先级在configMAX_SYSCALL_INTERRUPT_PRIORITY 之上的中断不会被延迟处理。
  • 运行在最大系统调用优先级 configMAX_SYSCALL_INTERRUPT_PRIORITY 之上的中断服务函数不会被RTOS内核所屏蔽,因此中断响应不会受影响。这样的设计主要是为了那些需要高精度的中断任务,比如电机的转向控制。当然,这样的中断服务函数不可以调用freeRTOS的API函数。

利用这种机制要求遵守如下规则:只要使用freeRTOS的API函数,那么优先级就必须小于等于configMAX_SYSCALL_INTERRUPT_PRIORITY所设置的优先级

对ARM Cortex-M3 和 ARM Cortex-M4用户的小提示: 因为ARM Cortex-M3、ARM Cortex-M4使用低数字表示高优先级(事实上,很多处理器具有这样的特性),因此如果你设置优先级为0,反而是系统中的最高优先级,这会潜在的导致你的系统崩溃,如果这个优先级大于configMAX_SYSCALL_INTERRUPT_PRIORITY。 详细的使用说明请参阅“ARM Corte-M系列处理器的中断优先级设置”。

configASSERT

在语义上,configASSERT和标准C的assert()宏相同。如果参数为0(false),则会触发。

configASSERT()常用来检查参数的合法性,在应用程序开发前期,强烈推荐使用这个宏,可以帮助开发人员快速定位隐藏的错误。在产品发布后期,只需要简单的将这个宏定义为空,就可以轻松取消这个宏的功能。

configASSERT()可以定义为,当条件为false时,向应用程序输出当前的文件名(FILE )及行号(LINE),这有助于开发者定位错误。这个宏可以在任何合适的地方使用。

同常,当这个宏触发后,建议应用程序停在这个地方(例如进入一个死循环),这样有两点好处,第一方便调试,第二,防止应用程序崩溃,导致其他问题。

当然,这个宏的使用会导致执行时间增加,同事增加代码量,因此,这个宏只建议在应用程序开发期间使用。

  1. /* 当条件为0时,调用 vAssertCalled() 输出当前行号及文件,vAssertCalled()可以通过串口或者显示器等输出错误信息,由开发者自行决定 */
  2. #define configASSERT( ( x ) ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

当freeRTOS运行在调试器的控制下,建议将宏定义为如下形式,这将有助于快速定位到异常代码:

  1. /* 带有死循环,让程序“停下来” */
  2. #define configASSERT( ( x ) ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS

configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 只会被freeRTOS 的 MPU 使用到。

如果将该设置项设置为1,开发者必须提供”application_defined_privileged_functions.h”头文件,包含开发者需要实现的特权模式函数声明,当然,具体函数代码实现也是必须的。

在“application_defined_privileged_functions.h”中声明的函数必须主动的保存和恢复处理器的特权状态,使用prvRaisePrivilege()函数,及portRESET_PRIVILEGE()宏。比如,如果一个库提供超出应用程序开发者控制的RAM访问的打印功能,因为无法分配内存保护用户模式下的任务,这个打印功能函数需要使用下面的形式封装起来:

  1. void MPU_debug_printf( const char *pcMessage )
  2. {
  3. /* 当函数调用时,先保存处理器的特权等级 */
  4. BaseType_t xRunningPrivileged = prvRaisePrivilege();
  5. /* 调用库函数,此时库函数具有全部的内存访问权限 */
  6. debug_printf( pcMessage );
  7. /* 恢复处理器的特权等级 */
  8. portRESET_PRIVILEGE( xRunningPrivileged );
  9. }

不建议在发布的应用程序中这样使用,而仅仅在开发过程中使用,因为这规避了处理器的内存保护。

INCLUDE Parameters

INCLUDE开头的宏,用来裁剪内核,可以将不适用的功能在编译时排除在外,这样的宏具有如下形式:

INCLUDE_FunctionName,其中FunctionName暗示,这个API或者一些列API可以选择性的包含:将宏设置为1,则包含,设置为0,则不包含。这会减少内存占用。比如,使用vTaskDelete()函数,则需要设置#define INCLUDE_vTaskDelete 1,反之,设置为#define INCLUDE_vTaskDelete 1