9322 字
47 分钟
FreeRTOS 参数配置
2023-04-12

注:大部分内容为 AI 回答,仅作整理汇总

CMSIS_V 1 vs CMSIS_V 2#

当然 V2 更好

宏定义#

MPU FPU#

ENABLE_MPU#

ENABLE_MPU 是一个宏定义,用于启用或禁用 ARM Cortex-M 处理器的内存保护单元(MPU)。MPU 是一种硬件机制,用于实现内存保护和访问控制,可以帮助确保系统的安全性和稳定性。

ENABLE_MPU 宏被定义时,意味着 MPU 被启用,系统将使用 MPU 提供的内存保护和访问控制功能。这意味着您可以配置 MPU 来限制特定区域的内存访问权限,例如只读、只写、可执行等,从而增强系统的安全性。

在一些 RTOS(实时操作系统)或者裸机应用中,启用 MPU 可以提供额外的内存保护,防止错误的内存访问导致系统崩溃或者数据损坏。然而,MPU 的配置需要仔细的设计和调试,因为不正确的配置可能会导致系统功能异常或者性能下降。

因此,在启用 ENABLE_MPU 宏之前,需要确保对 MPU 的配置和使用有充分的理解,并根据系统的需求进行合适的配置。

ENABLE_FPU#

ENABLE_FPU 是一个宏定义,用于启用或禁用 ARM Cortex-M 处理器的浮点单元(FPU)。FPU 是一种硬件模块,用于执行浮点数运算,包括单精度和双精度浮点数的加减乘除等操作。

启用 ENABLE_FPU 宏意味着您的处理器支持 FPU,并且编译器将会生成相应的浮点数运算指令。通常情况下,当您的应用需要进行大量的浮点数计算时,启用 FPU 可以提高运算速度和效率。

在一些 RTOS(实时操作系统)或者裸机应用中,启用 FPU 可以使您的应用能够充分利用硬件浮点单元,从而提高性能。

要通过代码启用 FPU,具体的步骤因芯片和开发环境而异,但一般情况下包括以下几个方面:

  1. 设置处理器中的 FPU: 在一些芯片中,您需要在启动代码或初始化代码中设置处理器的 FPU。这通常涉及将相应的寄存器设置为启用 FPU。

  2. 编译器选项: 您需要确保编译器正确地配置为支持 FPU。这可能需要在编译器选项中设置一些标志,以告知编译器您的处理器支持 FPU,并启用相应的优化。

  3. 启用 FPU 相关的 CMSIS 配置: 如果您在使用 CMSIS(Cortex Microcontroller Software Interface Standard)的话,您可能需要确保 CMSIS 配置正确,以便使用 FPU 相关的功能和优化。

内核设置#

USE_PREEMPTION#

USE_PREEMPTION 是一个宏定义,用于启用或禁用 RTOS 中的抢占式调度。在 RTOS 中,任务可以按照优先级抢占式地运行,这意味着当更高优先级的任务准备就绪时,它可以抢占当前正在执行的任务,从而立即执行。

启用 USE_PREEMPTION 宏表示您希望 RTOS 支持抢占式调度。这使得更高优先级的任务能够在需要时立即执行,从而提高系统的响应性和实时性。通常情况下,对于需要实时性能的系统,启用抢占式调度是一个好的选择。

在启用抢占式调度时,需要考虑以下几个方面:

  1. 任务优先级: 确保您为任务分配了适当的优先级。较高优先级的任务将能够抢占较低优先级的任务。

  2. 临界区保护: 由于任务可以被抢占,因此在访问共享资源时需要使用适当的同步机制,如信号量、互斥量或者临界区保护。这可以防止在多任务环境下出现数据竞争和不一致性。

  3. 任务设计: 要注意任务的设计,确保它们的执行时间尽可能短,以便更容易被抢占。如果任务执行时间过长,可能会降低系统的响应性。

  4. 调度策略: 在使用抢占式调度时,RTOS 通常会根据任务的优先级来确定下一个要执行的任务。您可能需要了解 RTOS 的调度策略,并根据需要进行配置。

下面是一个简单的示例代码,演示了如何在 FreeRTOS 中启用抢占式调度:

#include "FreeRTOS.h"
#include "task.h"

// 定义任务函数
void Task1(void *pvParameters) {
    while (1) {
        // 执行任务1的工作...
    }
}

void Task2(void *pvParameters) {
    while (1) {
        // 执行任务2的工作...
    }
}

int main(void) {
    // 启用抢占式调度
    #define USE_PREEMPTION 1

    // 创建任务1
    xTaskCreate(Task1, "Task1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 创建任务2
    xTaskCreate(Task2, "Task2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    return 0;
}

在上述示例中,我们在 FreeRTOS 中启用了抢占式调度,并创建了两个任务 Task1Task2。由于它们具有相同的优先级,因此它们将以轮询的方式运行,RTOS 会根据任务的优先级来决定下一个要运行的任务。

确保您的 RTOS 正确配置和编译,并遵循 RTOS 的使用规范,以确保您的应用能够正确地利用抢占式调度。

CPU_CLOCK_HZ#

CPU_CLOCK_HZ 是一个宏定义,用于指定 CPU 的时钟频率,通常以赫兹(Hz)为单位。在 RTOS 或其他嵌入式系统中,指定正确的 CPU 时钟频率对于确保系统正常运行至关重要。

设置正确的 CPU 时钟频率可以确保任务的时间片(如果使用抢占式调度)和延迟函数(如果存在)的准确性。此外,许多外设和定时器也依赖于 CPU 时钟频率来计算其操作。

通常情况下,CPU_CLOCK_HZ 的值应该与您的实际硬件平台的 CPU 时钟频率相匹配。这个值通常在启动代码或配置文件中设置。在一些 RTOS 中,您可能需要在操作系统配置文件中指定 CPU 时钟频率。

TICK_RATE_HZ#

TICK_RATE_HZ 是一个宏定义,用于指定 FreeRTOS 中的系统时钟节拍频率,通常以赫兹(Hz)为单位。它定义了系统中定时器中断的触发频率,决定了任务调度器的运行频率以及 FreeRTOS 中延时函数的精度。

系统的节拍频率应该是一个能够满足系统实时性需求的合适值。通常情况下,它应该足够高,以便系统能够及时响应各种事件和任务,但又不能太高,以免消耗过多的处理器资源。

典型的 TICK_RATE_HZ 值可以是几十赫兹(例如 100 Hz、200 Hz)到几百赫兹(例如 1 kHz、10 kHz)不等。具体的选择取决于系统的实际需求和硬件能力。

较高的 TICK_RATE_HZ 值通常会提高系统的响应速度和实时性,但也会增加系统的负载和能耗。因此,在选择 TICK_RATE_HZ 的值时需要权衡这些因素。

以下是一些常见的 TICK_RATE_HZ 值的示例:

  • 100 Hz:用于一般嵌入式应用,对实时性要求不是非常高的场景。
  • 200 Hz:用于具有中等实时性要求的应用,对实时性有一定的要求。
  • 1 kHz:用于对实时性要求较高的应用,如实时控制系统等。
  • 10 kHz:用于对实时性要求非常高的应用,如高性能控制系统等。

您可以根据系统的实际需求和性能要求选择适当的 TICK_RATE_HZ 值。在设置 TICK_RATE_HZ 值时,还需要考虑系统的处理器速度和其他硬件限制,以确保系统的稳定性和性能。

MAX_PRIORITIES#

MAX_PRIORITIES 是一个宏定义,用于指定 FreeRTOS 中任务的最大优先级数目。在 FreeRTOS 中,任务的优先级通常从 0 开始,较小的数值表示较高的优先级,因此 MAX_PRIORITIES 定义了系统中可用的最大任务优先级数目。

适当地选择 MAX_PRIORITIES 的值非常重要,因为它直接影响了系统的资源管理、任务调度和实时性能。选择过小的 MAX_PRIORITIES 可能会导致任务优先级不足以满足系统的需求,而选择过大的 MAX_PRIORITIES 则可能会浪费系统资源和降低系统性能。

一般来说,您应该根据系统的实际需求来选择合适的 MAX_PRIORITIES 的值。以下是一些考虑因素:

  1. 任务的优先级需求: 您需要考虑系统中各个任务的优先级关系,并确保 MAX_PRIORITIES 的值足够大,以便为所有任务分配合适的优先级。通常情况下,系统中可能会有一些关键任务,它们需要较高的优先级,以确保它们能够及时响应各种事件。

  2. 系统的复杂性: 如果系统比较复杂,可能需要更多的任务优先级来管理各种任务之间的依赖关系和执行顺序。较大的 MAX_PRIORITIES 值可以提供更灵活的任务调度策略,但也会增加系统的复杂性。

  3. 系统资源限制: 考虑系统的内存和处理器资源限制,以及 FreeRTOS 对于任务管理的开销。选择过大的 MAX_PRIORITIES 值可能会消耗过多的系统资源,降低系统的性能。

通常情况下,MAX_PRIORITIES 的值可以选择为 4 到 32 之间的数值。这个范围通常能够满足大多数嵌入式系统的需求。在选择 MAX_PRIORITIES 的值时,建议先对系统进行一些简单的分析和设计,以确定任务优先级的需求,并根据需求来选择合适的值。

MINIMAL_STACK_SIZE#

MINIMAL_STACK_SIZE 是一个宏定义,用于指定 FreeRTOS 中任务的最小堆栈大小,通常以字节为单位。堆栈是用于存储任务执行期间局部变量、函数调用和中断处理的重要内存区域。适当设置堆栈大小对于确保任务的正常运行和系统的稳定性非常重要。

在 FreeRTOS 中,每个任务都需要一个堆栈,堆栈的大小取决于任务执行期间所需的内存空间。MINIMAL_STACK_SIZE 定义了任务堆栈的最小大小,确保任务有足够的堆栈空间来执行其功能。

通常情况下,您可以根据任务的功能和使用的变量数量来选择适当的 MINIMAL_STACK_SIZE 值。以下是一些考虑因素:

  1. 任务的功能和复杂性: 如果任务执行复杂的计算或涉及大量的函数调用、局部变量和参数传递,那么它可能需要更大的堆栈空间。

  2. 中断处理: 如果任务需要处理频繁的中断,或者在中断处理函数中执行大量的操作,那么它可能需要更大的堆栈空间来存储中断处理的上下文。

  3. 系统资源限制: 考虑系统的内存限制和任务数量,以及 FreeRTOS 对于堆栈管理的开销。选择合适的 MINIMAL_STACK_SIZE 值可以确保系统的稳定性和性能。

通常情况下,MINIMAL_STACK_SIZE 的值可以选择为几百字节到几千字节之间的数值。对于简单的任务,可能只需要几百字节的堆栈空间,而对于复杂的任务或处理大量数据的任务,则可能需要几千字节的堆栈空间。

在选择 MINIMAL_STACK_SIZE 的值时,建议先对任务的功能和资源使用情况进行评估,然后根据评估结果来选择适当的值。确保为任务分配足够的堆栈空间,以避免堆栈溢出和系统崩溃。

MAX_TASK_NAME_LEN#

MAX_TASK_NAME_LEN 是一个宏定义,用于指定 FreeRTOS 中任务名称的最大长度。在 FreeRTOS 中,每个任务都可以有一个唯一的名称,用于标识和调试目的。MAX_TASK_NAME_LEN 定义了任务名称的最大长度,确保任务名称能够被正确地存储和管理。

适当设置 MAX_TASK_NAME_LEN 对于确保任务名称能够满足系统的标识和调试需求非常重要。通常情况下,任务名称的长度应该足够长,以包含有意义的信息,并能够清晰地标识任务的功能或用途。

以下是一些考虑因素:

  1. 任务名称的信息量: 任务名称应该能够清晰地表达任务的功能或用途,以便于系统的标识和调试。较长的任务名称可能包含更多的信息,但也可能会增加系统的开销和复杂性。

  2. 系统资源限制: 考虑系统的内存限制和任务数量,以及 FreeRTOS 对于任务管理的开销。选择合适的 MAX_TASK_NAME_LEN 值可以确保系统的稳定性和性能。

通常情况下,MAX_TASK_NAME_LEN 的值可以选择为几十到几百之间的数值。对于大多数嵌入式系统,任务名称通常不会特别长,因此可以选择一个适度的值来满足系统的需求。

在选择 MAX_TASK_NAME_LEN 的值时,建议先评估系统的标识和调试需求,并根据需求来选择合适的值。确保任务名称能够清晰地表达任务的功能或用途,同时又不会增加系统的开销和复杂性。

USE_16_BIT_TICKS#

32 - 32

USE_16_BIT_TICKS 是一个宏定义,用于指定 FreeRTOS 是否使用 16 位的节拍计数器。在 FreeRTOS 中,节拍计数器用于跟踪系统运行的时间,以及计算任务延时和超时等。如果启用了 USE_16_BIT_TICKS 宏,FreeRTOS 将使用 16 位的节拍计数器;否则,将使用较长的节拍计数器(通常是 32 位)。

启用 USE_16_BIT_TICKS 可以节省内存空间,因为 16 位的计数器比较短,需要的内存更少。这在内存资源有限的嵌入式系统中尤其有用。

然而,使用 16 位的计数器也会带来一些限制。由于计数器的长度较短,它们的溢出周期也会相应地变短。这意味着系统运行的时间可能会受到限制,而任务的延时和超时也会受到影响。因此,启用 USE_16_BIT_TICKS 时需要谨慎考虑系统的实时性需求。

通常情况下,如果系统的实时性要求不是特别严格,而且内存资源有限,那么启用 USE_16_BIT_TICKS 可能是一个合适的选择。但如果系统的实时性要求比较高,或者需要较长的运行时间,那么可能需要禁用 USE_16_BIT_TICKS,以使用更长的计数器来确保系统的正确运行。

在启用或禁用 USE_16_BIT_TICKS 时,建议根据系统的具体需求进行评估,并进行充分的测试和验证,以确保系统能够满足实时性和稳定性要求。

IDLE_SHOULD_YIELD#

IDLE_SHOULD_YIELD 是一个宏定义,用于指定 FreeRTOS 中空闲任务(Idle Task)是否应该在没有其他任务需要执行时主动让出 CPU。如果启用了 IDLE_SHOULD_YIELD 宏,空闲任务将在空闲时执行 taskYIELD() 函数,从而让出 CPU,允许其他更高优先级的任务运行。

启用 IDLE_SHOULD_YIELD 可以提高系统的响应速度,因为空闲任务可以主动让出 CPU,让其他任务更快地执行。这对于实时性要求较高的系统尤其有用,可以确保任务能够及时地响应各种事件和输入。

然而,需要注意的是,在某些情况下,让出 CPU 可能会带来一些额外的开销和性能损失。如果系统中存在大量的空闲时间,而且没有其他更高优先级的任务需要执行,那么频繁地让出 CPU 可能会降低系统的效率。

因此,在启用 IDLE_SHOULD_YIELD 时需要谨慎考虑系统的实际情况和性能需求。如果系统的空闲时间较少,或者没有其他更高优先级的任务需要执行,那么可能不需要启用 IDLE_SHOULD_YIELD

在配置 FreeRTOS 时,可以根据系统的实际需求来决定是否启用 IDLE_SHOULD_YIELD。需要权衡系统的实时性、响应速度和性能等因素,以选择合适的配置选项。

USE_MUTEXES#

USE_MUTEXES 是一个宏定义,用于指定 FreeRTOS 是否支持互斥量(Mutexes)。互斥量是一种同步原语,用于在多任务系统中保护共享资源,以防止多个任务同时访问导致数据不一致或竞争条件的发生。

启用 USE_MUTEXES 宏表示您希望在 FreeRTOS 中使用互斥量来保护共享资源。当任务需要访问共享资源时,它可以获取互斥量,这样其他任务就无法同时访问该资源,直到释放了互斥量为止。

互斥量在许多多任务系统中都是非常常见和重要的同步机制,特别是在需要保护关键资源或临界区的情况下。通过使用互斥量,可以确保数据的完整性和一致性,避免竞争条件和数据访问冲突的发生。

启用 USE_MUTEXES 可以提高系统的可靠性和稳定性,确保任务之间的合作和数据共享能够正常进行。但需要注意的是,互斥量的过度使用可能会导致死锁和性能下降,因此需要合理地设计和使用互斥量来避免这些问题的发生。

在配置 FreeRTOS 时,可以根据系统的实际需求和资源限制来决定是否启用 USE_MUTEXES。如果系统中存在共享资源需要保护,那么启用互斥量是一个明智的选择。

USE_RECURSIVE_MUTEXES#

USE_RECURSIVE_MUTEXES 是一个宏定义,用于指定 FreeRTOS 是否支持递归互斥量(Recursive Mutexes)。递归互斥量是一种特殊类型的互斥量,允许同一个任务多次获取同一个互斥量,而不会导致死锁。

在某些情况下,任务可能需要多次获取同一个互斥量,例如在递归调用的函数中,或者在多个层次的函数调用中需要保护共享资源。如果使用普通的互斥量,在任务多次获取同一个互斥量时会导致死锁,因为同一个任务已经持有了该互斥量,再次获取它时会一直等待直到被释放。

启用 USE_RECURSIVE_MUTEXES 宏表示您希望在 FreeRTOS 中支持递归互斥量。这样,同一个任务可以多次获取同一个互斥量,而不会导致死锁。任务可以多次释放递归互斥量,直到与之匹配的获取次数为零,这时其他任务才能获取该互斥量。

递归互斥量在某些情况下是非常有用的,特别是在需要保护共享资源的复杂递归调用或层次结构中。但需要注意的是,滥用递归互斥量可能会导致设计上的复杂性和性能下降,因此需要谨慎使用。

在配置 FreeRTOS 时,可以根据系统的实际需求和资源限制来决定是否启用 USE_RECURSIVE_MUTEXES。如果系统中存在需要在同一个任务中多次获取同一个互斥量的情况,那么启用递归互斥量是一个合理的选择。

USE_COUNTING_SEMAPHORES#

USE_COUNTING_SEMAPHORES 是一个宏定义,用于指定 FreeRTOS 是否支持计数信号量(Counting Semaphores)。计数信号量是一种同步原语,用于在多任务系统中管理资源的访问和共享。

启用 USE_COUNTING_SEMAPHORES 宏表示您希望在 FreeRTOS 中支持计数信号量。计数信号量允许多个任务同时访问同一个资源,而不会导致竞争条件或数据不一致的发生。计数信号量的值可以是任意非负整数,表示资源的可用数量。

计数信号量通常用于管理有限资源的访问,例如共享内存池、缓冲区或设备。当任务需要访问资源时,它可以通过获取计数信号量来申请资源,当资源不可用时,任务会被阻塞,直到资源可用为止。任务使用完资源后,通过释放计数信号量来释放资源,以便其他任务可以继续使用。

启用 USE_COUNTING_SEMAPHORES 可以提高系统的可靠性和稳定性,确保任务能够安全地访问和共享资源。但需要注意的是,过度使用计数信号量可能会导致竞争条件和性能下降,因此需要合理地设计和使用计数信号量来避免这些问题的发生。

在配置 FreeRTOS 时,可以根据系统的实际需求和资源限制来决定是否启用 USE_COUNTING_SEMAPHORES。如果系统中存在需要管理有限资源的情况,那么启用计数信号量是一个合理的选择。

QUEUE_REGISTRY_SIZE#

QUEUE_REGISTRY_SIZE 是一个宏定义,用于指定 FreeRTOS 中队列注册表的大小。在 FreeRTOS 中,队列注册表用于跟踪和管理系统中所有创建的队列,以便于调试和跟踪队列的使用情况。

队列注册表的大小决定了系统中可以注册的队列的最大数量。每个队列都会占用一定的注册表条目,因此 QUEUE_REGISTRY_SIZE 定义了系统中可以同时存在的队列的最大数量。

适当设置 QUEUE_REGISTRY_SIZE 对于确保系统能够正常运行和调试是非常重要的。如果系统中同时存在的队列数量超过了队列注册表的大小,可能会导致一些队列无法被正确管理和跟踪,从而影响系统的稳定性和可靠性。

一般来说,QUEUE_REGISTRY_SIZE 的值应该根据系统中实际使用的队列数量进行估计,并留有一定的余量以应对未来可能的扩展。如果系统中使用了大量的队列,那么 QUEUE_REGISTRY_SIZE 的值就需要设置得比较大;反之,如果系统中使用的队列数量较少,那么 QUEUE_REGISTRY_SIZE 的值可以设置得较小。

在配置 FreeRTOS 时,可以根据系统的实际需求和队列数量来确定 QUEUE_REGISTRY_SIZE 的值。通常建议设置一个合适的默认值,并根据系统的运行情况进行调整和优化。

USE_APPLICATION_TASK_TAG#

USE_APPLICATION_TASK_TAG 是一个宏定义,用于指定 FreeRTOS 是否启用任务标记功能(Task Tagging)。任务标记功能允许开发人员为每个任务附加一个标记,以便在调试和分析中识别和跟踪任务。

启用 USE_APPLICATION_TASK_TAG 宏表示您希望在 FreeRTOS 中启用任务标记功能。一旦启用,您可以为每个任务设置一个标记,以便在系统运行时跟踪任务的信息。任务标记可以是任何您认为有用的信息,例如任务的名称、任务的功能、任务的状态等。

任务标记功能在调试和分析大型 FreeRTOS 应用程序时非常有用。通过任务标记,您可以更容易地识别和跟踪任务,了解它们的运行状况和行为,从而更快地定位和解决问题。

在配置 FreeRTOS 时,您可以根据系统的实际需求和调试要求来决定是否启用 USE_APPLICATION_TASK_TAG。如果您需要在运行时跟踪任务,并且任务的信息对于调试和分析非常重要,那么启用任务标记功能可能是一个明智的选择。

需要注意的是,启用任务标记功能可能会增加系统的内存消耗和运行时开销,因此在资源有限的环境中需要权衡使用该功能的成本和收益。

ENABLE_BACKWARD_COMPATIBILITY#

ENABLE_BACKWARD_COMPATIBILITY 是一个宏定义,用于指定是否启用 FreeRTOS 的向后兼容性功能。向后兼容性是指新版本的 FreeRTOS 是否能够与旧版本的 FreeRTOS 兼容,以便在升级到新版本时,现有的应用程序可以继续正常运行。

启用 ENABLE_BACKWARD_COMPATIBILITY 宏表示您希望在新版本的 FreeRTOS 中启用向后兼容性功能。这意味着新版本的 FreeRTOS 将尽可能地保持与旧版本的接口和行为一致,以确保现有的应用程序可以平稳地升级到新版本,而不需要进行太多的修改和调整。

向后兼容性是非常重要的,特别是对于长期维护的嵌入式系统来说。通过保持向后兼容性,可以降低系统升级的成本和风险,减少因升级导致的问题和不稳定性。

在配置 FreeRTOS 时,您可以根据实际需求和应用程序的情况来决定是否启用 ENABLE_BACKWARD_COMPATIBILITY。如果您的应用程序依赖于旧版本的 FreeRTOS,并且需要平滑地升级到新版本,那么启用向后兼容性功能可能是一个明智的选择。

需要注意的是,启用向后兼容性功能可能会增加新版本 FreeRTOS 的体积和复杂性,因此在资源有限的环境中需要权衡使用该功能的成本和收益。

USE_PORT_OPTIMISED_TASK_SELECTION#

USE_PORT_OPTIMISED_TASK_SELECTION 是一个宏定义,用于指定 FreeRTOS 是否启用端口优化的任务选择功能。任务选择是指在多任务系统中选择下一个要执行的任务的过程。启用此宏将使用端口特定的优化来实现任务选择,以提高系统的性能和效率。

当启用 USE_PORT_OPTIMISED_TASK_SELECTION 宏时,FreeRTOS 将使用特定于硬件平台的任务选择实现,以提高任务切换的速度和效率。这种优化可能会利用硬件的特性或者对任务状态的特定存储方式,从而加速任务的切换过程。

启用端口优化的任务选择功能可以提高系统的性能和效率,特别是在高负载和高实时性要求的系统中。通过减少任务切换的开销,系统可以更快地响应各种事件和任务,提高系统的响应速度和实时性。

在配置 FreeRTOS 时,您可以根据实际硬件平台和性能需求来决定是否启用 USE_PORT_OPTIMISED_TASK_SELECTION。如果您的系统需要更高的性能和效率,并且硬件平台支持端口优化的任务选择功能,那么启用此宏可能是一个合适的选择。

需要注意的是,启用端口优化的任务选择功能可能会增加 FreeRTOS 的复杂性,并且可能会限制其在其他硬件平台上的移植性。因此,在权衡使用此功能时需要考虑这些因素。

USE_TICKLESS_IDLE#

USE_TICKLESS_IDLE 是一个宏定义,用于指定 FreeRTOS 是否启用 Tickless Idle 模式。Tickless Idle 模式是一种省电功能,可在系统空闲时让 CPU 进入低功耗模式,以节省能源并延长电池寿命。

当启用 USE_TICKLESS_IDLE 宏时,FreeRTOS 将启用 Tickless Idle 模式。在 Tickless Idle 模式下,系统会动态调整系统定时器的间隔,在任务无需处理时尽可能地延迟系统的时钟中断,以减少 CPU 的唤醒次数,并将 CPU 保持在低功耗模式下。

启用 Tickless Idle 模式可以显著降低系统的功耗,特别是在长时间空闲或低负载情况下。这对于依赖电池供电的嵌入式系统尤其重要,可以延长电池寿命,并减少充电次数。

在配置 FreeRTOS 时,您可以根据系统的实际需求和功耗优化的要求来决定是否启用 USE_TICKLESS_IDLE。如果您的系统依赖电池供电,并且需要最大限度地降低功耗以延长电池寿命,那么启用 Tickless Idle 模式可能是一个明智的选择。

需要注意的是,启用 Tickless Idle 模式可能会增加 FreeRTOS 的复杂性,并且可能会影响系统的实时性能。在启用 Tickless Idle 模式时,需要仔细测试和验证系统的实时性能,以确保满足系统的实时性要求。

USE_TASK_NOTIFICATIONS#

USE_TASK_NOTIFICATIONS 是一个宏定义,用于指定 FreeRTOS 是否启用任务通知功能。任务通知是一种轻量级的通信机制,允许任务之间进行同步和通信,而无需使用信号量或消息队列等更重量级的同步原语。

启用 USE_TASK_NOTIFICATIONS 宏表示您希望在 FreeRTOS 中启用任务通知功能。一旦启用,您可以使用任务通知来实现任务之间的同步、事件通知和等待等功能。任务通知可以用于替代信号量、事件组和消息队列等同步原语,从而提高系统的性能和效率。

任务通知是一种非常灵活和高效的通信机制,特别适用于需要高实时性和低延迟的系统。与传统的同步原语相比,任务通知具有更低的内存消耗和更快的响应时间,可以更好地满足实时性要求。

在配置 FreeRTOS 时,您可以根据系统的实际需求和性能要求来决定是否启用 USE_TASK_NOTIFICATIONS。如果您需要在任务之间进行高效的通信和同步,并且希望提高系统的性能和效率,那么启用任务通知功能可能是一个合适的选择。

需要注意的是,任务通知功能可能会增加 FreeRTOS 的复杂性,并且可能需要一些额外的学习和理解来正确地使用。在使用任务通知时,需要注意避免死锁和竞争条件等问题,以确保系统的稳定性和可靠性。 post/code/embedded/

FreeRTOS 参数配置

Selection deleted

FreeRTOS 参数配置

文档属性

FreeRTOS 参数配置

{“headline”:“FreeRTOS 参数配置”,“color”:” #00ffff ”}

2024-04-12

Lab

STM32

💻Code

添加文档属性

RECORD_STACK_HIGH_ADDRESS#

RECORD_STACK_HIGH_ADDRESS 是一个宏定义,用于指定 FreeRTOS 是否记录任务堆栈的高地址。当启用 RECORD_STACK_HIGH_ADDRESS 宏时,FreeRTOS 将在任务创建时记录任务堆栈的高地址。

任务堆栈的高地址记录可以帮助识别任务的堆栈使用情况,特别是在调试和优化任务堆栈大小时非常有用。通过记录堆栈的高地址,您可以了解任务实际使用的堆栈大小,从而更好地优化任务堆栈大小,避免堆栈溢出问题。

在启用 RECORD_STACK_HIGH_ADDRESS 宏后,您可以通过调用 uxTaskGetStackHighWaterMark() 函数来获取任务堆栈的高地址记录。这个函数会返回任务堆栈的高地址记录与任务堆栈的当前使用情况之间的差值,这就是任务堆栈的最大使用量。

UBaseType_t uxHighWaterMark;

// 获取任务堆栈的最大使用量
uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);

通过分析任务堆栈的最大使用量,您可以更好地了解任务的堆栈使用情况,并相应地调整任务堆栈的大小,以确保系统的稳定性和可靠性。

存储相关#

TOTAL_HEAP_SIZE#

TOTAL_HEAP_SIZE 是一个宏定义,用于指定 FreeRTOS 中用于动态内存分配的堆的总大小。在 FreeRTOS 中,堆用于分配任务、队列、信号量等对象所需的内存空间。

通过设置 TOTAL_HEAP_SIZE,您可以指定 FreeRTOS 可用的总内存量。FreeRTOS 将会从这个总内存池中动态分配内存,用于创建任务、队列、信号量等对象。在运行时,FreeRTOS 会根据需要从堆中分配内存,并在对象不再需要时释放内存,以便其他对象可以重复利用。

在设置 TOTAL_HEAP_SIZE 时,需要根据系统的实际需求和资源限制来确定堆的大小。如果堆的大小设置得太小,可能会导致内存分配失败或者系统性能下降;如果设置得太大,可能会浪费宝贵的内存资源。

通常情况下,可以根据系统的任务数量、队列大小、信号量数量等因素来估算堆的大小。另外,还需要考虑系统的其他内存需求,如栈空间、静态内存分配等。

在设置 TOTAL_HEAP_SIZE 时,建议留有一定的余量,以应对系统在运行时可能出现的内存需求增加的情况。同时,也可以通过监视系统的内存使用情况,根据实际情况调整堆的大小,以达到最佳的性能和稳定性。

以下是一个设置 TOTAL_HEAP_SIZE 的示例:

#define TOTAL_HEAP_SIZE (20 * 1024) // 设置堆的总大小为20KB

在这个示例中,堆的总大小被设置为 20 KB。您可以根据实际需求修改这个值,并确保系统的稳定性和性能。

Memory Management scheme#

默认 heap_4

在 FreeRTOS 中,内存管理方案取决于您选择的内存分配器。FreeRTOS 提供了几种内存分配器,可以根据您的需求和平台选择合适的内存管理方案。

  1. Heap_1: Heap_1 是 FreeRTOS 提供的最简单的内存分配器,它使用静态数组作为堆。静态数组的大小由 configTOTAL_HEAP_SIZE 宏定义确定,数组的大小在编译时就被确定。这种分配器非常适合于资源有限的嵌入式系统,它简单、轻量,并且不需要额外的外部依赖。

  2. Heap_2: Heap_2 是另一种简单的内存分配器,它也使用静态数组作为堆,但允许您通过 configAPPLICATION_ALLOCATED_HEAP 宏自定义堆的起始地址和大小。这种分配器允许您将堆放置在特定的内存区域,例如特定的 RAM 区域或者特殊的存储器设备。

  3. Heap_3: Heap_3 是 FreeRTOS 提供的动态内存分配器,它使用标准的 malloc()free() 函数来分配和释放内存。这种分配器非常适合于具有标准 C 库支持的系统,它可以充分利用标准库提供的内存管理功能,并且能够适应不同大小的内存需求。

  4. Heap_4: Heap_4 是一种更高级的内存分配器,它使用先进的分配算法来提高内存分配和释放的效率。它是一种适用于大型系统和高性能系统的内存分配方案,可以有效地管理大量的动态内存,并且具有较低的内存碎片化和内存浪费。

在选择内存管理方案时,需要考虑系统的资源限制、性能要求和实现的复杂度等因素。不同的内存分配器适用于不同的场景,您可以根据您的具体需求选择最合适的内存管理方案。

在 FreeRTOS 中,钩子函数(hook functions)是一组特殊的函数,允许用户在 FreeRTOS 内核执行关键操作时插入自定义的代码。这些钩子函数可以用于监视系统状态、调试应用程序、实现定制功能等。以下是一些与钩子函数相关的定义:

  1. vApplicationMallocFailedHook: 当 FreeRTOS 内核尝试分配内存失败时,将调用此钩子函数。用户可以在此函数中实现自定义的处理逻辑,例如记录错误、采取措施或者进行其他处理。
void vApplicationMallocFailedHook( void );
  1. vApplicationStackOverflowHook: 当任务堆栈溢出时,将调用此钩子函数。用户可以在此函数中实现自定义的堆栈溢出处理逻辑,例如记录错误、重启系统或者进行其他处理。
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
  1. vApplicationIdleHook: 当系统处于空闲状态时,将调用此钩子函数。用户可以在此函数中实现自定义的空闲处理逻辑,例如休眠处理器、执行低优先级任务等。
void vApplicationIdleHook( void );
  1. vApplicationTickHook: 每次 FreeRTOS 定时器节拍时,将调用此钩子函数。用户可以在此函数中实现自定义的定时处理逻辑,例如记录系统时间、执行周期性任务等。
void vApplicationTickHook( void );
  1. vApplicationDaemonTaskStartupHook: FreeRTOS 守护任务启动时,将调用此钩子函数。用户可以在此函数中实现自定义的守护任务启动处理逻辑。
void vApplicationDaemonTaskStartupHook( void );
  1. vApplicationDaemonTaskStartupHook: FreeRTOS 守护任务启动时,将调用此钩子函数。用户可以在此函数中实现自定义的守护任务启动处理逻辑。
void vApplicationDaemonTaskStartupHook( void );

通过实现这些钩子函数,用户可以在 FreeRTOS 内核执行关键操作时插入自定义的处理逻辑,从而更好地监视、调试和优化系统。需要根据实际需求选择合适的钩子函数,并实现相应的处理逻辑。

FreeRTOS 参数配置
https://f.undf.top/posts/post/code/embedded/freertos-参数配置/
作者
沐印
发布于
2023-04-12
许可协议
CC BY-NC-SA 4.0