FreeRTOSConfig.h 文件

  FreeRTOS 的配置基本是通过在 FreeRTOSConfig.h 中使用“#define” 这样的语句来定义宏定义实现的。 在 FreeRTOS 的官方 demo 中,每个工程都有一个 FreeRTOSConfig.h 文件,我们在使用的时候可以参考这个文件,甚至直接复制粘贴使用。
1、“INCLUDE_”开始的宏
  使用“INCLUDE_”开头的宏用来表示使能或除能 FreeRTOS 中相应的 API 函数, 作用就是用来配置 FreeRTOS 中的可选 API 函数的。比如当宏 INCLUDE_vTaskPrioritySet 设置为 0 的时候 表示不能 使用函数 vTaskPrioritySet() , 当设置 为 1 的时 候就表示可 以使用函 数vTaskPrioritySet()。这个功能其实就是条件编译,在文件 tasks.c 中有如下图所示的代码。

  从上 图 可 以 看 出 当 满 足 条 件 : NCLUDE_vTaskPrioritySet == 1 的 时 候 , 函 数vTaskPrioritySet()才会被编译, 注意,这里为了缩小篇幅将函数 vTaskPrioritySet()的内容进行了折叠。FreeRTOS 中的裁剪和配置就是这种用条件编译的方法来实现的,不止 FreeRTOS这么干,很多的协议栈、 RTOS 系统和 GUI 库等都是使用条件编译的方法来完成配置和裁剪的。 条件编译的好处就是节省空间,不需要的功能就不用编译,这样就可以根据实际需求来减少系统占用的 ROM 和 RAM 大小,根据自己所使用的 MCU 来调整系统消耗,降低成本。

  下面来看看“INCLUDE_”开始的都有哪些宏,它们的功能都是什么。

  (1)、 INCLUDE_xSemaphoreGetMutexHolder
  如果要使用函数 xQueueGetMutexHolder()的话宏 INCLUDE_xSemaphoreGetMutexHolder 必须定义为 1。
  (2)、 INCLUDE_xTaskAbortDelay
  如果要使用函数 xTaskAbortDelay()的话将宏 INCLUDE_xTaskAbortDelay 定义为 1。
  (3)、 INCLUDE_vTaskDelay
  如果要使用函数 vTaskDelay()的话需要将宏 INCLUDE_vTaskDelay 定义为 1。
  (4)、 INCLUDE_vTaskDelayUntil
  如果要使用函数 vTaskDelayUntil()的话需要将宏 INCLUDE_vTaskDelayUntil 定义为 1。
  (5)、 INCLUDE_vTaskDelete
  如果要使用函数 vTaskDelete()的话需要将宏 INCLUDE_vTaskDelete 定义为 1。
  (6)、 INCLUDE_xTaskGetCurrentTaskHandle
  如 果 要 使 用 函 数 xTaskGetCurentTaskHandle() 的 话 需 要 将 宏INCLUDE_xTaskGetCurrentTaskHandle 定义为 1。
  (7)、 INCLUDE_xTaskGetHandle
  如果要使用函数 xTaskGetHandle()的话需要将宏 INCLUDE_xTaskGetHandle 定义为 1。
  (8)、 INCLUDE_xTaskGetIdleTaskHandle
  如 果 要 使 用 函 数 xTaskGetIdleTaskHandle() 的 话 需 要 将 宏INCLUDE_xTaskGetIdleTaskHandle 定义为 1。
  (9)、 INCLUDE_xTaskGetSchedulerState
  如果要使用函数 xTaskGetSchedulerState()的话需要将宏 INCLUDE_xTaskGetSchedulerState定义为 1。
  (10)、 INCLUDE_uxTaskGetStackHighWaterMark
  如 果 要 使 用 函 数 uxTaskGetStackHighWaterMark() 的 话 需 要 将 宏INCLUDE_uxTaskGetStackHighWaterMark 定义为 1。
  (11)、 INCLUDE_uxTaskPriorityGet
  如果要使用函数 uxTaskPriorityGet()的话需要将宏 INCLUDE_uxTaskPriorityGet 定义为 1。
  (12)、 INCLUDE_vTaskPrioritySet
  如果要使用函数 vTaskPrioritySet()的话需要将宏 INCLUDE_vTaskPrioritySet 定义为 1。
  (13)、 INCLUDE_xTaskResumeFromISR
  如果要使用函数 xTaskResumeFromISR()的话需要将宏 INCLUDE_xTaskResumeFromISR 和INCLUDE_vTaskSuspend 都定义为 1。
  (14)、 INCLUDE_eTaskGetState
  如果要使用函数 eTaskGetState()的话需要将宏 INCLUDE_eTaskGetState 定义为 1。
  (15)、 INCLUDE_vTaskSuspend
  如 果 要 使 用 函 数 vTaskSuspend() 、 vTaskResume() 、 prvTaskIsTaskSuspended() 、xTaskResumeFromISR()的话宏 INCLUDE_vTaskSuspend 要定义为 1。
  如 果 要 使 用 函 数 xTaskResumeFromISR() 的 话 宏 INCLUDE_xTaskResumeFromISR 和INCLUDE_vTaskSuspend 都必须定义为 1。
  (16)、 INCLUDE_xTimerPendFunctionCall
  如果要使用函数 xTimerPendFunctionCall()和 xTimerPendFunctionCallFromISR()的话宏INCLUDE_xTimerPendFunctionCall 和 configUSE_TIMERS 都必须定义为 1。

2、 “config”开始的宏
  “config”开始的宏和“INCLUDE_”开始的宏一样,都是用来完成 FreeRTOS 的配置和裁剪的。

  接下来我们就看一下这些“config”开始的宏。

  (1)、 configAPPLICATION_ALLOCATED_HEAP
  默 认 情 况 下 FreeRTOS 的 堆 内 存 是 由 编 译 器 来 分 配 的 , 将 宏configAPPLICATION_ALLOCATED_HEAP 定义为 1 的话堆内存可以由用户自行设置,堆内存在 heap_1.c、 heap_2.c、 heap_3.c、 heap_4.c 和 heap_5.c 中有定义,具体在哪个文件取决于用户的选择哪种内存管理方式。比如我们的例程选择了 heap_4.c,那么在 heap_4.c 中就有如图 3.2.1所示定义:

image

  从图 3.2.1 可以看出当宏 configAPPLICATION_ALLOCATED_HEAP 定义为 1 的话需要用户自行堆内存 ucHeap,否则的话就是编译器来分配的。
  (2)、 configASSERT
  断言,类似 C 标准库中的 assert()函数, 调试代码的时候可以检查传入的参数是否合理,FreeRTOS 内核中的关键点都会调用 configASSERT(x), 当 x 为 0 的时候说明有错误发生,使用断言的话会导致开销加大,一般在调试阶段使用。 configASSERT()需要在 FreeRTOSConfig.h 文件中定义, 如下实例:

#define configASSERT((x)) if((x)==0) vAssertCalled(__FILE_,__LINE__);    

  注意, vAssertCalled()函数需要用户自行去定义,可以是显示到 LCD 上的函数,也可以是通过串口打印出来的函数,本教程的所有例程采用如下的定义:

//断言
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)

  当参数 x 错误的时候就通过串口打印出发生错误的文件名和错误所在的行号,调试代码的可以使用断言,当调试完成以后尽量去掉断言, 防止增加开销!
  (3)、 configCHECK_FOR_STACK_OVERFLOW
  设置堆栈溢出检测,每个任务都有一个任务堆栈,如果使用函数 xTaskCreate()创建一个任务的话那么这个任务的堆栈是自动从 FreeRTOS 的堆(ucHeap)中分配的,堆栈的大小是由函数xTaskCreate()的参数 usStackDepth 来决定的。如果使用函数 xTaskCreateStatic()创建任务的话任务堆栈是由用户设置的,参数 pxStackBuffer 为任务堆栈,一般是一个数组。
  堆栈溢出是导致应用程序不稳定的主要因素, FreeRTOS 提供了两种可选的机制来帮助检测和调试堆栈溢出, 不管使用哪种机制都要设置宏 configCHECK_FOR_STACK_OVERFLOW。
  如果使能了堆栈检测功能的话,即宏 configCHECK_FOR_STACK_OVERFLOW 不为 0,那么用户必须提供一个钩子函数(回调函数),当内核检测到堆栈溢出以后就会调用这个钩子函数,此钩子函数原型如下:

void vApplicationStackOverflowHook( TaskHandle_t xTask,char * pcTaskName );

  参数 xTask 是任务句柄, pcTaskName 是任务名字,要注意的是堆栈溢出太严重的话可能会损毁这两个参数, 如果发生这种情况的话可以直接查看变量 pxCurrentTCB 来确定哪个任务发生了堆栈溢出。有些处理器可能在堆栈溢出的时候生成一个 fault 中断来提示这种错误,另外,堆栈溢出检测会增加上下文切换的开销,建议在调试的时候使用。

  configCHECK_FOR_STACK_OVERFLOW==1,使用堆栈溢出检测方法 1。
  上下文切换的时候需要保存现场,现场是保存在堆栈中的,这个时候任务堆栈使用率很可能达到最大值,方法一就是不断的检测任务堆栈指针是否指向有效空间,如果指向了无效空间的话就会调用钩子函数。 方法一的优点就是快!但是缺点就是不能检测所有的堆栈溢出。
  configCHECK_FOR_STACK_OVERFLOW==2,使用堆栈溢出检测方法 2。
  使用方法二的话在创建任务的时候会向任务堆栈填充一个已知的标记值,方法二会一直检测堆栈后面的几个 bytes(标记值)是否被改写,如果被改写的话就会调用堆栈溢出钩子函数,方法二也会使用方法一中的机制!方法二比方法一要慢一些,但是对用户而言还是很快的!方法二能检测到几乎所有的堆栈溢出, 但是也有一些情况检测不到,比如溢出值和标记值相同的时候。
  (4)、 configCPU_CLOCK_HZ
  设置 CPU 的频率。
  (5)、 configSUPPORT_DYNAMIC_ALLOCATION
  定义为 1 的话在创建 FreeRTOS 的内核对象的时候所需要的 RAM 就会从 FreeRTOS 的堆中动态的获取内存,如果定义为 0 的话所需的 RAM 就需要用户自行提供,默认情况下宏configSUPPORT_DYNAMIC_ALLOCATION 为 1。
  (6)、 configENABLE_BACKWARD_COMPATIBILITY
  FreeRTOS.h 中由一些列的#define 宏定义,这些宏定义都是一些数据类型名字,如下图 3.2.2所示:

image

  在 V8.0.0 之前的 FreeRTOS 中会使用到这些数据类型,这些宏保证了你的代码从 V8.0.0 之前 的 版 本 升 级 到 最 新 版 本 的 时 候 不 需 要 做 出 修 改 , 默 认 情 况 下 宏configENABLE_BACKWARD_COMPATIBILITY 为 1。
  (7)、 configGENERATE_RUN_TIME_STATS
  设置为 1 开启时间统计功能, 相应的 API 函数会被编译, 为 0 时关闭时间统计功能。 如果宏 configGENERATE_RUN_TIME_STATS 为 1 的话还需要定义表 3.2.1 中的宏。

image

  (8)、 configIDLE_SHOULD_YIELD
  此宏定义了与空闲任务(idle Task)处于同等优先级的其他用户任务的行为, 当为 0 的时候空闲任务不会为其他处于同优先级的任务让出 CPU 使用权。 当为 1 的时候空闲任务就会为处于同等优先级的用户任务让出 CPU 使用权, 除非没有就绪的用户任务, 这样花费在空闲任务上的时间就会很少, 但是这种方法也带了副作用,见图 3.2.3。

image  

  图 3.2.3 中有三个用户任务: A、 B、 C,还有一个空闲任务 I,用户任务和空闲任务处于同一优先级,任务切换发生在 T0~T7 时刻。 T0~T1 之间的时间为一个时间片,从图中可以看出一开始任务 B、 C 都执行了一个完成的时间片,在 T2 时刻空闲任务 I 开始执行, I 任务运行了一段时间以后被 A 任务抢走了 CPU 使用权, A 任务运行到 T3 时刻发生任务切换, B 任务开始运行。可以看出其实任务 I 和任务 A 一起使用了一个时间片,所以任务 A 运行的时间就比其他任务少!一般建议大家关闭这个功能,毕竟空闲任务用不了多少时间,而且现在的 MCU 性能都很强!

  (9)、 configKERNEL_INTERRUPT_PRIORITY、configMAX_SYSCALL_INTERRUPT_PRIORITY、configMAX_API_CALL_INTERRUPT_PRIORITY
  这三个宏和 FreeRTOS 的中断配置有关,后面会有专门的章节来讲解!
  (10)、 configMAX_CO_ROUTINE_PRIORITIES
  设置可以分配给协程的最大优先级, 也就是协程的优先级数。设置号以后协程的优先级可以 从 0 到 configMAX_CO_ROUTINE_PRIORITIES-1 , 其 中 0 是 最 低 的 优 先 级 ,configMAX_CO_ROUTINE_PRIORITIES-1 为最高的优先级。
  (11)、 configMAX_PRIORITIES
  设置任务的优先级数量,设置好以后任务就可以使用从 0 到 configMAX_PRIORITIES-1 的优先级,其中 0 是最低优先级, configMAX_PRIORITIES-1 是最高优先级。 注意和 UCOS 的区别, UCOS 中 0 是最高优先级!
  (12)、 configMAX_TASK_NAME_LEN
  设置任务名最大长度。
  (13)、 configMINIMAL_STACK_SIZE
  设置空闲任务的最小任务堆栈大小,以字为单位,不是字节。比如在 STM32 上设置为 100的话,那么真正的堆栈大小就是 100*4=400 字节。
  (14)、 configNUM_THREAD_LOCAL_STORAGE_POINTERS
  设置每个任务的本地存储指针数组大小, 任务控制块中有本地存储数组指针,用户应用程序可以在这些本地存储中存入一些数据。
  (15)、 configQUEUE_REGISTRY_SIZE
  设置可以注册的队列和信号量的最大数量,在使用内核调试器查看信号量和队列的时候需要设置此宏,而且要先将消息队列和信号量进行注册,只有注册了的队列和信号量才会再内核调试器中看到,如果不使用内核调试器的话此宏设置为 0 即可。
  (16)、 configSUPPORT_STATIC_ALLOCATION
  当此宏定义为 1,在创建一些内核对象的时候需要用户指定 RAM,当为 0 的时候就会自使用 heap.c 中的动态内存管理函数来自动的申请 RAM。
  (17)、 configTICK_RATE_HZ
  设置 FreeRTOS 的系统时钟节拍频率,单位为 HZ,此频率就是滴答定时器的中断频率,需要使用此宏来配置滴答定时器的中断,前面在讲 delay.c 文件的时候已经说过了。 本教程中我们将此宏设置为 1000,周期就是 1ms。
  (18)、 configTIMER_QUEUE_LENGTH
  此宏是配置 FreeRTOS 软件定时器的, FreeRTOS 的软件定时器 API 函数会通过命令队列向软件定时器任务发送消息,此宏用来设置这个软件定时器的命令队列长度。
  (19)、 configTIMER_TASK_PRIORITY
  设置软件定时器任务的任务优先级。
  (20)、 configTIMER_TASK_STACK_DEPTH
  设置定时器服务任务的任务堆栈大小。
  (21)、 configTOTAL_HEAP_SIZE
  设置堆大小,如果使用了动态内存管理的话, FreeRTOS 在创建任务、信号量、队列等的时候 就 会 使 用 heap_x.c(x 为 1~5) 中 的 内 存 申 请 函 数 来 申 请 内 存 。 这 些 内 存 就 是 从 堆ucHeap[configTOTAL_HEAP_SIZE]中申请的,堆的大小由 configTOTAL_HEAP_SIZE 来定义。
  (22)、 configUSE_16_BIT_TICKS
  设置系统节拍计数器变量数据类型,系统节拍计数器变量类型为 TickType_t,当configUSE_16_BIT_TICKS 为 1 的时候 TickType_t 就是 16 位的,当 configUSE_16_BIT_TICKS为 0 的话 TickType_t 就是 32 位的。
  (23)、 configUSE_APPLICATION_TASK_TAG
  此 宏 设 置 为 1 的 话 函 数 configUSE_APPLICATION_TASK_TAGF()和xTaskCallApplicationTaskHook()就会被编译。
  (24)、 configUSE_CO_ROUTINES
  此宏为 1 的时候启用协程,协程可以节省开销,但是功能有限,现在的 MCU 性能已经非常强大了,建议关闭协程。
  (25)、 configUSE_COUNTING_SEMAPHORES
  设置为 1 的时候启用计数型信号量,相关的 API 函数会被编译。
  (26)、 configUSE_DAEMON_TASK_STARTUP_HOOK
  当宏 configUSE_TIMERS 和 configUSE_DAEMON_TASK_STARTUP_HOOK 都为 1 的时需要定义函数 vApplicationDaemonTaskStartupHook(),函数原型如下:
  void vApplicationDaemonTaskStartupHook( void )
  (27)、 configUSE_IDLE_HOOK
  为 1 时使用空闲任务钩子函数, 用户需要实现空闲任务钩子函数,函数的原型如下:
  void vApplicationIdleHook( void )
  (28)、 configUSE_MALLOC_FAILED_HOOK
  为 1 时使用内存分配失败钩子函数,用户需要实现内存分配失败钩子函数,函数原型如下;
  void vApplicationMallocFailedHook( void )
  (29)、 configUSE_MUTEXES
  为 1 时使用互斥信号量,相关的 API 函数会被编译。
  (30)、 configUSE_PORT_OPTIMISED_TASK_SELECTION
  FreeRTOS 有两种方法来选择下一个要运行的任务,一个是通用的方法,另外一个是特殊的方法, 也就是硬件方法, 使用 MCU 自带的硬件指令来实现。
  通用方法:
    ● 当宏 configUSE_PORT_OPTIMISED_TASK_SELECTION 为 0,或者硬件不支持的时候。
    ● 希望所有硬件通用的时候。
    ● 全部用 C 语言来实现,但是效率比特殊方法低。
    ● 不限制最大优先级数目的时候。
  特殊方法:
    ● 不是所有的硬件都支持。
    ● 当宏 configUSE_PORT_OPTIMISED_TASK_SELECTION 为 1 的时候。
    ● 硬件拥有特殊的指令,比如计算前导零(CLZ)指令。
    ● 比通用方法效率高。
    ● 会限制优先级数目,一般是 32 个。
  STM32 有 计 算 前 导 零 的 指 令 , 所 以 我 们 可 以 使 用 特 殊 方 法 , 即 将 宏configUSE_PORT_OPTIMISED_TASK_SELECTION 定义为 1。 计算前导零的指令在 UCOSIII 也用到了,也是用来查找下一个要运行的任务的。
  (31)、 configUSE_PREEMPTION
  为 1 时使用抢占式调度器,为 0 时使用协程。如果使用抢占式调度器的话内核会在每个时钟节拍中断中进行任务切换,当使用协程的话会在如下地方进行任务切换:
    ● 一个任务调用了函数 taskYIELD()。
    ● 一个任务调用了可以使任务进入阻塞态的 API 函数。
    ● 应用程序明确定义了在中断中执行上下文切换。
  (32)、 configUSE_QUEUE_SETS
  为 1 时启用队列集功能。
  (33)、 configUSE_RECURSIVE_MUTEXES
  为 1 时使用递归互斥信号量,相关的 API 函数会被编译。
  (34)、 configUSE_STATS_FORMATTING_FUNCTIONS
  宏 configUSE_TRACE_FACILITY 和 configUSE_STATS_FORMATTING_FUNCTIONS 都为1 的时候函数 vTaskList()和 vTaskGetRunTimeStats()会被编译。
  (35)、 configUSE_TASK_NOTIFICATIONS
  为 1 的时候使用任务通知功能, 相关的 API 函数会被编译,开启了此功能的话每个任务会多消耗 8 个字节。
  (36)、 configUSE_TICK_HOOK
  为 1 时使能时间片钩子函数,用户需要实现时间片钩子函数,函数的原型如下:

void vApplicationTickHook( void )  

  (37)、 configUSE_TICKLESS_IDLE
  为 1 时使能低功耗 tickless 模式。
  (38)、 configUSE_TIMERS
  为 1 时使用软件定时器,相关的 API 函数会被编译,当宏 configUSE_TIMERS 为 1 的话,那 么 宏 configTIMER_TASK_PRIORITY 、 configTIMER_QUEUE_LENGTH 和configTIMER_TASK_STACK_DEPTH 必须定义。
  (39)、 configUSE_TIME_SLICING
  默认情况下, FreeRTOS 使用抢占式调度器,这意味着调度器永远都在执行已经就绪了的最高优先级任务, 优先级相同的任务在时钟节拍中断中进行切换, 当宏 configUSE_TIME_SLICING为 0 的时候不会在时钟节拍中断中执行相同优先级任务的任务切换,默认情况下宏configUSE_TIME_SLICING 为 1。
  (40)、 configUSE_TRACE_FACILITY
  为 1 启用可视化跟踪调试, 会增加一些结构体成员和 API 函数。
  FreeRTOS 的配置文件基本就这些,还有一些其他的配置宏由于使用的比较少这里并没有列出来,这些配置具体使用到的时候在具体查看就行了。

/*
    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
    All rights reserved

    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

    This file is part of the FreeRTOS distribution.

    FreeRTOS is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License (version 2) as published by the
    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.

    ***************************************************************************
    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
    >>!   distribute a combined work that includes FreeRTOS without being   !<<
    >>!   obliged to provide the source code for proprietary components     !<<
    >>!   outside of the FreeRTOS kernel.                                   !<<
    ***************************************************************************

    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
    link: http://www.freertos.org/a00114.html

    ***************************************************************************
     *                                                                       *
     *    FreeRTOS provides completely free yet professionally developed,    *
     *    robust, strictly quality controlled, supported, and cross          *
     *    platform software that is more than just the market leader, it     *
     *    is the industry's de facto standard.                               *
     *                                                                       *
     *    Help yourself get started quickly while simultaneously helping     *
     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
     *    tutorial book, reference manual, or both:                          *
     *    http://www.FreeRTOS.org/Documentation                              *
     *                                                                       *
    ***************************************************************************

    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
    the FAQ page "My application does not run, what could be wrong?".  Have you
    defined configASSERT()?

    http://www.FreeRTOS.org/support - In return for receiving this top quality
    embedded software for free we request you assist our global community by
    participating in the support forum.

    http://www.FreeRTOS.org/training - Investing in training allows your team to
    be as productive as possible as early as possible.  Now you can receive
    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
    Ltd, and the world's leading authority on the world's leading RTOS.

    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
    compatible FAT file system, and our tiny thread aware UDP/IP stack.

    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.

    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
    licenses offer ticketed support, indemnification and commercial middleware.

    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
    engineered and independently SIL3 certified version for use in safety and
    mission critical applications that require provable dependability.
*/

#ifndef __FREERTOS_CONFIG_H
#define __FREERTOS_CONFIG_H


#include "stm32f10x.h"
#include "hal_usb_1_driver.h"

//针对不同的编译器调用不同的stdint.h文件,在 MDK 中,我们默认的是__CC_ARM
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif



//断言
#define vAssertCalled(char,int)         DBG_PRINTF("Error:%s,%d\r\n",char,int)        //此宏用于辅助配置宏 configASSERT( x )以通过串口打印相关信息。
#define configASSERT(x) if((x)==0)         vAssertCalled(__FILE__,__LINE__)            //此宏为 FreeRTOS 操作系统中的断言, 断言会对表达式 x 进行判断, 当 x 为假时, 断言失败, 表明程序出错, 于是使用宏 vAssertCalled(char, int)通过串口打印相关的错误信息。 断言常
                                                                                    //用于检测程序中的错误, 使用断言将增加程序的代码大小和执行时间, 因此建议在程序调试通过后将宏 configASSERT( x )进行注释, 以较少额外的开销。






/************************************************************************
                    FreeRTOS基础配置配置选项 
************************************************************************/

/** 
  * 注:在多任务管理机制上,操作系统可以分为抢占式和协作式两种。
  * 协作式调度器是任务执行完主动释放CPU后,再切换到下一个任务,任务切换的时机完全取决于正在运行的任务
  * 抢占式调度器是任务要么被高优先级的抢占,要么就是执行遇到阻塞式API来释放CPU使用权,让低优先级的任务执行
  */
#define configUSE_PREEMPTION            1  //0:RTOS使用协作式调度器(时间片) 1:RTOS使用抢占式调度器
#define configUSE_TIME_SLICING            1  //1:使能时间片调度(默认使能)      当宏设置为1时且在使用抢占式调度器时会使能时间片调度,这样当任务的优先级相同时会以时间片来切换任务


/**
  *如何找到最高优先级的就绪任务的TCB?
  *某些硬件运行FreeRTOS有两种方法选择下一个要执行的任务:通用方法和特定于硬件的方法(以下简称“特殊方法”)。
  *查找最高优先级的就绪任务
  * 
  * 通用方法:
  *      1.configUSE_PORT_OPTIMISED_TASK_SELECTION 为 0 或者硬件不支持这种特殊方法。
  *      2.可以用于所有FreeRTOS支持的硬件
  *      3.完全用C实现,效率略低于特殊方法。
  *      4.不强制要求限制最大可用优先级数目
  * 特殊方法:
  *      1.必须将configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1。
  *      2.依赖一个或多个特定架构的汇编指令(一般是类似计算前导零[CLZ]指令)。
  *      3.比通用方法更高效
  *      4.一般强制限定最大可用优先级数目为32
  * 一般是硬件计算前导零指令,如果所使用的MCU没有这些硬件指令的话此宏应该设置为0!
  */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION            1 //0:通用方法  1:特殊方法 (根据处理器优化的方法)      


/** 
  * 低功耗模式的使能,假设开启低功耗的话可能会导致下载出现问题,因为程序在睡眠中,可用以下办法解决
  * 
  * 下载方法:
  *      1.将开发版正常连接好
  *      2.按住复位按键,点击下载瞬间松开复位按键
  *     
  *      1.通过跳线帽将 BOOT 0 接高电平(3.3V)
  *      2.重新上电,下载
  *    
  *         1.使用FlyMcu擦除一下芯片,然后进行下载
  *        STMISP -> 清除芯片(z)
  */
#define configUSE_TICKLESS_IDLE                    1 //1:使能低功耗tickless模式   0:保持系统节拍(tick)中断一直运行


/**
  * 写入实际的CPU内核时钟频率,也就是CPU指令执行频率,通常称为Fclk
  * Fclk为供给CPU内核的时钟信号,我们所说的cpu主频为 XX MHz,
  * 就是指的这个时钟信号,相应的,1/Fclk即为cpu时钟周期;
  */
#define configCPU_CLOCK_HZ                        (SystemCoreClock)       //此宏应设置为 CPU 的内核时钟频率, 单位为 Hz。


#define configTICK_RATE_HZ                        (( TickType_t )1000)    //此宏用于设置 FreeRTOS 系统节拍的中断频率, 单位为 Hz。1000表示1ms中断1次,RTOS系统节拍中断的频率,即系统时钟周期。即一秒中断的次数,每次中断RTOS都会进行任务调度
#define configMAX_PRIORITIES                    (32)                    //此宏用于定义系统支持的最大任务优先级数量,最大支持 256 个优先级,使用特殊方法时最多支持32个优先级,最大任务优先级数值为configMAX_PRIORITIES-1
#define configMINIMAL_STACK_SIZE                ((unsigned short)128)   //空闲任务使用的栈空间大小,以字为单位,128*4=512字节
#define configMAX_TASK_NAME_LEN                    (30)                    //任务名字字符串长度,包括'\0'
//#define configSYSTICK_CLOCK_HZ                                        //此宏应设置为 SysTick 的时钟频率, 当 SysTick 的时钟源频率与内核时钟频率不同时才可以定义, 单位为 Hz。

 
#define configUSE_16_BIT_TICKS                   0 //系统节拍计数器变量数据类型,1表示为16位无符号整形,0表示为32位无符号整形,STM32为32位          
#define configIDLE_SHOULD_YIELD                  1 //为1时在抢占调度下,同等优先级的任务可抢占空闲任务, 并延用空闲任务剩余的时间片。
#define configUSE_QUEUE_SETS                     1 //为1时启用消息队列
#define configUSE_TASK_NOTIFICATIONS             1 //为1时开启任务通知功能,默认开启,当开启任务通知功能后, 每个任务将多占用 8 字节的内存空间。
//#define configTASK_NOTIFICATION_ARRAY_ENTRIES      //此宏用于定义任务通知数组的大小。
#define configUSE_MUTEXES                        1 //为1时使能互斥信号量                           
#define configUSE_RECURSIVE_MUTEXES              1 //为1时使能递归互斥信号量    
#define configUSE_COUNTING_SEMAPHORES            1 //为1时使能计数信号量


#define configQUEUE_REGISTRY_SIZE                10 //设置可以注册的信号量和消息队列的最大个数
#define configUSE_APPLICATION_TASK_TAG             0  //设置可以注册的消息队列个数

//#define configUSE_NEWLIB_REENTRANT                //此宏用于为每个任务分配一个NewLib重入结构体,当宏configUSE_NEWLIB_REENTRANT设置为1时,FreeRTOS将为每个创建的任务的任务控制块中分配一个 NewLib 重入结构体。
//#define configENABLE_BACKWARD_COMPATIBILITY        //此宏用于兼容 FreeRTOS 老版本的 API 函数。
//#define configNUM_THREAD_LOCAL_STORAGE_POINTERS    //此宏用于在任务控制块中分配一个线程本地存储指着数组, 当此宏被定义为大于 0 时,configNUM_THREAD_LOCAL_STORAGE_POINTERS 为线程本地存储指针数组的元素个数;当宏 configNUM_THREAD_LOCAL_STORAGE_POINTERS 为 0 时, 则禁用线程本地存储指针数组。
//#define configSTACK_DEPTH_TYPE                    //此宏用于定义任务堆栈深度的数据类型, 默认为 uint16_t。
//#define configMESSAGE_BUFFER_LENGTH_TYPE            //此宏用于定义消息缓冲区中消息长度的数据类型, 默认为 size_t。










/*****************************************************************
              FreeRTOS与内存申请有关配置选项                                               
*****************************************************************/
#define configSUPPORT_DYNAMIC_ALLOCATION        1                      //0:不支持动态内存申请    1:支持动态内存申请        此宏默认设置为1
#define configSUPPORT_STATIC_ALLOCATION            0                       //0:不支持静态内存申请    1:支持静态内存申请        此宏默认设置为0,如果将 configSUPPORT_STATIC_ALLOCATION 设置为 1, 用户还需要提供两个回调函数:vApplicationGetIdleTaskMemory() 和vApplicationGetTimerTaskMemory()
    
#define configTOTAL_HEAP_SIZE                    ((size_t)(36*1024))    //系统所有堆的大小,即总共有多少堆.此宏用于定义用于 FreeRTOS 动态内存管理的内存大小, 即 FreeRTOS 的内存堆, 单位为Byte。
//#define configAPPLICATION_ALLOCATED_HEAP                                //此宏用于自定义 FreeRTOS 的内存堆,当宏设置为1时,用户需要自行创建 FreeRTOS 的内存堆,否则 FreeRTOS 的内存堆将由编译器进行分配。利用此宏定义,可以使用 FreeRTOS 动态管理外扩内存。
//#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP                        //此宏用于自定义动态创建和删除任务时, 任务栈内存的申请与释放函数 pvPortMallocStack()和 vPortFreeStack(), 当宏 configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 设置为 1 是,用户需提供 pvPortMallocStack()和 vPortFreeStack()函数。









/***************************************************************
             FreeRTOS与钩子函数有关的配置选项                                            
**************************************************************/
/** 
  * 
  * 空闲任务钩子是一个函数,这个函数由用户来实现,
  * FreeRTOS规定了函数的名字和参数:void vApplicationIdleHook(void ),这个函数在每个空闲任务周期都会被调用。
  * 对于已经删除的RTOS任务,空闲任务可以释放分配给它们的堆栈内存。
  * 因此必须保证空闲任务可以被CPU执行
  * 使用空闲钩子函数设置CPU进入省电模式是很常见的
  * 会引起空闲任务阻塞的API函数不能调用
  */
#define configUSE_IDLE_HOOK                        0 //1:使能空闲任务钩子函数(Idle Hook类似于回调函数,用户需自定义相关钩子函数)   0:不使能空闲任务钩子函数

/** 
  * 时间片钩子是一个函数,这个函数由用户来实现,
  * FreeRTOS规定了函数的名字和参数:void vApplicationTickHook(void )
  * 时间片中断可以周期性的调用
  * 函数必须非常短小,不能大量使用堆栈,
  * 不能调用以”FromISR" 或 "FROM_ISR”结尾的API函数
  */
/*xTaskIncrementTick函数是在xPortSysTickHandler中断函数中被调用的。因此,vApplicationTickHook()函数执行的时间必须很短才行*/
#define configUSE_TICK_HOOK                        0 //1:使能使用系统时钟节拍中断钩子函数(Tick Hook)   0:不使能使用系统时钟节拍中断钩子函数


#define configUSE_MALLOC_FAILED_HOOK            0 //1:使能动态内存申请失败钩子函数,用户需自定义相关钩子函数  0:不使能使用动态内存分配失败钩子函数。

/**
  * 大于0时启用堆栈溢出检测功能,如果使用此功能,用户必须提供一个栈溢出钩子函数,如果使用的话此值可以为1或者2,因为有两种栈溢出检测方法 
  */
#define configCHECK_FOR_STACK_OVERFLOW            0   //此宏用于使能栈溢出检测, 当宏 configCHECK_FOR_STACK_OVERFLOW 设置为 1 时,使用栈溢出检测方法一; 当宏 configCHECK_FOR_STACK_OVERFLOW 设置为 2 时, 栈溢出检测方法二; 当宏 configCHECK_FOR_STACK_OVERFLOW 设置为 0 时, 不使能栈溢出检测。

//#define configUSE_DAEMON_TASK_STARTUP_HOOK        //此宏用于使能使用定时器服务任务首次执行前的钩子函数,当设置为1时,使能使用定时器服务任务首次执行前的钩子函数, 此时用户需定义定时器服务任务首次执行的相关钩子函数; 当宏设置为 0 时, 则不使能使用定时器服务任务首次执行前的钩子函数。









/********************************************************************
          FreeRTOS与运行时间和任务状态收集有关的配置选项   
**********************************************************************/
#define configGENERATE_RUN_TIME_STATS            0 //为1时启用运行时间统计功能,此时用户需要提供两个函数, 一个是用于配置任务运行时间统计功能的函数 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(), 一般是完成定时器的初始化, 另一个函数是 portGET_RUN_TIME_COUNTER_VALUE(), 该函数用于获取定时器的计时值; 当宏 configGENERATE_RUN_TIME_STATS 设置为 0 时, 则不使能任务运行时间统计功能。     
#define configUSE_TRACE_FACILITY                0 //为1时启用可视化跟踪调试,为0时则不使能可视化跟踪调试


/** 与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
  * prvWriteNameToBuffer()
  * vTaskList(),
  * vTaskGetRunTimeStats()
  */
#define configUSE_STATS_FORMATTING_FUNCTIONS    1                       
                                                                        







/********************************************************************
                FreeRTOS与协程有关的配置选项                                                
*********************************************************************/
#define configUSE_CO_ROUTINES                     0       //为1时启用协程,启用协程以后必须添加文件croutine.c ,为0时则不启用协程       
#define configMAX_CO_ROUTINE_PRIORITIES         (2)     //此宏用于设置协程的最大任务优先级数量,协程的最大任务优先级数值为configMAX_CO_ROUTINE_PRIORITIES-1。 








/***********************************************************************
                FreeRTOS与软件定时器有关的配置选项      
**********************************************************************/

#define configUSE_TIMERS                        1                              //为1时启用软件定时器,为0时则不启用软件定时器功能。                       
#define configTIMER_TASK_PRIORITY                (configMAX_PRIORITIES-1)       //此宏用于设置软件定时器处理任务的优先级,当启用软件定时器功能时, 系统会创建一个用于处理软件定时器的软件定时器处理任务。 
#define configTIMER_QUEUE_LENGTH                10                             //此宏用于定义软件定时器队列的长度, 软件定时器的开启、 停止与销毁等操作都是通过队列实现的。                 
#define configTIMER_TASK_STACK_DEPTH            (configMINIMAL_STACK_SIZE*2)   //此宏用于设置软件定时器处理任务的栈空间大小, 当启用软件定时器功能时, 系统会创建一个用于处理软件定时器的软件定时器处理任务。









/************************************************************
            FreeRTOS可选函数配置选项,即条件编译                                                    
************************************************************/
//必须将对应得宏置1才能使用对应得函数
#define INCLUDE_xTaskGetSchedulerState           1       //获取任务调度器状态                    
#define INCLUDE_vTaskPrioritySet                 1        //设置任务优先级
#define INCLUDE_uxTaskPriorityGet                 1        //获取任务优先级
#define INCLUDE_vTaskDelete                         1        //删除任务
#define INCLUDE_vTaskCleanUpResources             1
#define INCLUDE_vTaskSuspend                     1        //挂起任务
#define INCLUDE_vTaskDelayUntil                     1        //任务绝对延时
#define INCLUDE_vTaskDelay                         1        //任务延时
#define INCLUDE_eTaskGetState                     1        //获取任务状态
#define INCLUDE_xTimerPendFunctionCall             1        //将函数的执行挂到定时器服务任务
//#define INCLUDE_xTaskGetCurrentTaskHandle       1        //获取当前任务的任务句柄
//#define INCLUDE_uxTaskGetStackHighWaterMark     0        //获取任务堆栈历史剩余最小值
//#define INCLUDE_xTaskGetIdleTaskHandle          0        //获取空闲任务的任务句柄
//#define INCLUDE_xResumeFromISR                  0        //恢复在中断中挂起的任务
//#define INCLUDE_xEventGroupSetBitFromISR        0        //在中断中设置事件标志位
//#define INCLUDE_xTaskAbortDelay                 0        //中断任务延时
//#define INCLUDE_xTaskGetHandle                  0        //通过任务名获取任务句柄
//#define INCLUDE_xTaskResumeFromISR              0        //恢复在中断中挂起的任务








/******************************************************************
            FreeRTOS与中断有关的配置选项                                                 
******************************************************************/
#ifdef __NVIC_PRIO_BITS
    #define configPRIO_BITS               __NVIC_PRIO_BITS     //此宏应定义为 MCU 的 8 位优先级配置寄存器实际使用的位数。
#else 
    #define configPRIO_BITS               4                    //此宏应定义为 MCU 的 8 位优先级配置寄存器实际使用的位数,使用4位作为中断优先级
#endif



#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY            15     //设置MCU中断的最低优先级,数值越大,优先级越低, 对于 STM32,在使用 FreeRTOS 时,建议将中断优先级分组设置为组 4, 此时中断的最低优先级为 15。 此宏定义用于辅助配置宏configKERNEL_INTERRUPT_PRIORITY。
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5      //此宏定义用于设置 FreeRTOS可管理的最高中断优先级, 当中断的优先级数值小于此宏定义时,此中断不受 FreeRTOS 管理。此宏定义用于辅助配置宏 configMAX_SYSCALL_INTERRUPT_PRIORITY。

#define configKERNEL_INTERRUPT_PRIORITY                 (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )        //此宏应定义为 MCU 的最低中断优先等级在中断优先级配置寄存器中的值, 对于 STM32,即宏 configLIBRARY_LOWEST_INTERRUPT_PRIORITY 偏移 4bit 的值。
#define configMAX_SYSCALL_INTERRUPT_PRIORITY             (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )   //用来配置中断屏蔽寄存器 BASEPRI 的值, 高四位有效,此宏应定义为 FreeRTOS 可管理中断的最高优先等级在中断优先级配置寄存器中的值, 对于 STM32, 即宏 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 偏移 4bit 的值。
//#define configMAX_API_CALL_INTERRUPT_PRIORITY            //此宏为宏 configMAX_SYSCALL_INTERRUPT_PRIORITY 的新名称, 只被用在 FreeRTOS官方一些新的移植当中, 此宏与宏 configMAX_SYSCALL_INTERRUPT_PRIORITY 是等价的









/****************************************************************
            FreeRTOS与中断服务函数有关的配置选项                         
****************************************************************/
#define xPortPendSVHandler     PendSV_Handler        //这两个宏为PendSV和SVC的中断服务函数,主要用于FreeRTOS操作系统的任务切换,有关 FreeRTOS 操作系统中任务切换的相关内容
#define vPortSVCHandler     SVC_Handler                
//#define xPortSysTickHandler SysTick_Handler


/*以下为使用Percepio Tracealyzer需要的东西,不需要时将configUSE_TRACE_FACILITY定义为0*/
#if ( configUSE_TRACE_FACILITY == 1 )
    #include "trcRecorder.h"
    #define INCLUDE_xTaskGetCurrentTaskHandle               1   // 启用一个可选函数(该函数被 Trace源码使用,默认该值为0 表示不用)
#endif





#endif

 

posted @ 2024-08-14 16:35  孤情剑客  阅读(689)  评论(0)    收藏  举报