1.在 FreeRTOS 中延时函数也相对模式和绝对模式,在 FreeRTOS 中不同的模式用的函数不同,其中函数 vTaskDelay()是相对模式(相对延时函数),函数 vTaskDelayUntil()是绝对模式(绝对延时函数)。两者都会阻塞任务。具体内容可以看博客这一篇:https://www.cnblogs.com/bathwind/p/18139217
2.FreeRTOS时间片的配置方法,时间片需要使用两个配置项configTICK_RATE_HZ和configCPU_CLOCK_HZ共同配合完成,系统会根据这两个配置项来完成对systick的配置。函数vPortSetupTimerInterrupt会被函数vTaskStartScheduler调用,无需手动调用函数vPortSetupTimerInterrupt
3.
这个题信息可以具体去看这个任务切换涉及到了pendsv中断:https://www.cnblogs.com/bathwind/p/18127622
4:每 个 任 务 都 可 以 分 配 一 个 从 0~(configMAX_PRIORITIES-1) 的 优 先 级 ,如configUSE_PORT_OPTIMISED_TASK_SELECTION 设 置 为 了 1 , 那 么 宏configMAX_PRIORITIES 不能超过 32!也就是优先级不能超过 32 级。其他情况下宏configMAX_PRIORITIES 可以为任意值,但是考虑到 RAM 的消耗,宏 configMAX_PRIORITIES最好设置为一个满足应用的最小值。优先级数字越低表示任务的优先级越低,0 的优先级最低,configMAX_PRIORITIES-1 的优先级最高。空闲任务的优先级最低,为 0。FreeRTOS 调度器确保处于就绪态或运行态的高优先级的任务获取处理器使用权,换句话说就是处于就绪态的最高优先级的任务才会运行。当宏 configUSE_TIME_SLICING 定义为 1 的时候多个任务可以共用一个优先级,数量不限。
5:对于调度器开启过程的分析有助于我们了解整个系统的运行。 vTaskStartScheduler()这个函数开启任务调度器。在任务调度器中主要做以下工作。
(1)、创建空闲任务,如果使用静态内存的话使用函数 xTaskCreateStatic()来创建空闲任务,优先级为 tskIDLE_PRIORITY,宏 tskIDLE_PRIORITY 为 0,也就是说空闲任务的优先级为最低。
(2)、如果使用软件定时器的话还需要通过函数 xTimerCreateTimerTask()来创建定时器服务任务。
(3)、关闭中断,在 SVC 中断服务函数 vPortSVCHandler()中会打开中断。
(4)、变量 xSchedulerRunning 设置为 pdTRUE,表示调度器开始运行。
(5)、调用函数 xPortStartScheduler()来初始化跟调度器启动有关的硬件,比如滴答定时器、FPU 单元和 PendSV 中断等等。具体可以看任务调度器这个博客:https://www.cnblogs.com/bathwind/p/18125003
6:在FreeRTOS中,中断优先级嵌套遵循以下原则;高优先级中断可抢占低优先级中断。同级中断不可抢占。不能被立刻响应的中断会被悬挂。等待高优先级中断退出后才执行。内存是有限的,因此不能无限嵌套
7:在freertos中,如果configCHECK_FOR_STACK_OVERFLOW不为0,需要用户提供一个钩子函数,函数原型如下:
void vApplicationStackOverflowHook( TaskHandle_t xTask,char * pcTaskName );
参数 xTask 是任务句柄, pcTaskName 是任务名字,要注意的是堆栈溢出太严重的话可能会损毁这两个参数, 如果发生这种情况的话可以直接查看变量 pxCurrentTCB 来确定哪个任务发生了堆栈溢出。
configCHECK_FOR_STACK_OVERFLOW1,使用堆栈溢出检测方法 1。上下文切换的时候需要保存现场,现场是保存在堆栈中的,这个时候任务堆栈使用率很可能达到最大值,方法一就是不断的检测任务堆栈指针是否指向有效空间,如果指向了无效空间的话就会调用钩子函数。 方法一的优点就是快!但是缺点就是不能检测所有的堆栈溢出。
configCHECK_FOR_STACK_OVERFLOW2,使用堆栈溢出检测方法 2。使用方法二的话在创建任务的时候会向任务堆栈填充一个已知的标记值,方法二会一直检测堆栈后面的几个 bytes(标记值)是否被改写,如果被改写的话就会调用堆栈溢出钩子函数,方法二也会使用方法一中的机制!方法二比方法一要慢一些,但是对用户而言还是很快的!方法二能检测到几乎所有的堆栈溢出, 但是也有一些情况检测不到,比如溢出值和标记值相同的时候。
8:时间片钩子函数是使用中最常用的钩子函数之一,在使用时我们需要把configUSE_IDLE_HOOK配置成1,时间片钩子函数需要由用户来实现,FreeRTOS规定了函数的名字和参数:void vApplicationTickHook(void ) 。时间片中断可以周期性的调用该函数,该函数必须非常短小,不能大量使用堆栈,不能调用以”FromISR" 或 "FROM_ISR”结尾的API函数。
9:函数 xTaskCreate()创建一个任务的话那么这个任务的堆栈 是自动 从 FreeRTOS的堆 (ucHeap)中分配的 ,堆栈的大小是由函数xTaskCreate()的 参数 usStackDepth来决定的。
10:xTimerReset()使用定时器命令队列将“重置”命令发送到守护程序任务。xTicksToWait指定在队列已满的情况下,调用任务应保持在阻塞状态以等待计时器命令队列上的空间可用的最长时间。如果xTicksToWait为零并且计时器命令队列已满,则xTimerReset()将立即返回。如果在FreeRTOSConfig.h中将INCLUDE_vTaskSuspend设置为1,则将xTicksToWait设置为portMAX_DELAY将导致调用任务无限期地保持在阻塞状态(无超时),以等待 定时器命令队列中的可用空间。该函数有两个可能的返回值来表示成功和失败:pdPASS和pdFALSE。
11:下面是各种配置项及其含义描述
点击查看代码
#define configUSE_TIMERS 1 //为1时启用软件定时器
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器优先级
#define configTIMER_QUEUE_LENGTH 5 //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小
#define configGENERATE_RUN_TIME_STATS 0 //为1时启用运行时间统计功能
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器优先级
#define configTIMER_QUEUE_LENGTH 5 //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小
#define configGENERATE_RUN_TIME_STATS 0 //为1时启用运行时间统计功能