买一个成品网站多少钱,开淘宝网店的全流程,网站添加悬浮二维码,同一ip 网站 权重一、操作系统进行任务切换的时机#xff1a;
采用信号量实现任务的互斥#xff1a;
二、FreeRTOS 任务切换场合
PendSV 中断的时候提到了上下文(任务)切换被触发的场合#xff1a; ● 可以执行一个系统调用 ● 系统滴答定时器(SysTick)中断。
1、执行系统调用 执行系统…一、操作系统进行任务切换的时机
采用信号量实现任务的互斥
二、FreeRTOS 任务切换场合
PendSV 中断的时候提到了上下文(任务)切换被触发的场合 ● 可以执行一个系统调用 ● 系统滴答定时器(SysTick)中断。
1、执行系统调用 执行系统调用就是执行 FreeRTOS系统提供的相关API函数比如任务切换函数 taskYIELD() FreeRTOS 有些 API 函数也会调用函数 taskYIELD()这些 API 函数都会导致任务切换这些 API 函数和任务切换函数 taskYIELD()都统称为系统调用。 2、系统滴答定时器(SysTick)中断 (1)、关闭中断 (2)、通过向中断控制和壮态寄存器 ICSR 的 bit28 写入 1 挂起 PendSV 来启动 PendSV 中断。这样就可以在 PendSV 中断服务函数中进行任务切换了。 (3)、打开中断。 三、查找下一个要运行的任务 (1)、如果调度器挂起那就不能进行任务切换。 (2)、调用函数 taskSELECT_HIGHEST_PRIORITY_TASK()获取下一个要运行的任务。 taskSELECT_HIGHEST_PRIORITY_TASK()本质上是一个宏在 tasks.c 中有定义。 FreeRTOS 中查找下一个要运行的任务有两种方法一个是通用的方法另外一个就是使用 硬件的方法这个在我们讲解 FreeRTOSCofnig.h 文件的时候就提到过了至于选择哪种方法通 过宏 configUSE_PORT_OPTIMISED_TASK_SELECTION 来决定的。当这个宏为 1 的时候就使 用硬件的方法否则的话就是使用通用的方法
四、任务的状态
在 FreeRTOS 中当一个任务就绪后会自动插入就绪列表。 任务状态和就绪列表的概念 FreeRTOS 中的任务有多种状态如就绪Ready、运行Running、阻塞Blocked和挂起Suspended。就绪状态的任务是已经准备好运行等待调度器分配 CPU 时间来执行。就绪列表是一个数据结构用于保存所有处于就绪状态的任务。 调度器会从就绪列表中选择一个任务来运行这个选择过程是基于调度算法的比如抢占式优先级调度算法它会选择优先级最高的就绪任务来运行。 任务就绪的触发机制和插入过程 当一个任务创建成功并且其状态变为就绪时例如任务创建函数xTaskCreate创建一个任务后如果任务的初始状态是就绪没有被阻塞或挂起它会被自动插入就绪列表。 另外当一个任务从阻塞状态如等待一个信号量、消息队列或者定时器超时等情况恢复到就绪状态时系统也会自动将该任务插入就绪列表。这个过程是由 FreeRTOS 的内核机制来处理的对于开发者来说是透明的。例如一个任务因为等待一个信号量而阻塞当信号量被释放后等待该信号量的任务就会从阻塞状态转换为就绪状态然后自动插入就绪列表等待调度器调度运行。 所以FreeRTOS 很好地管理了任务的状态转换和就绪列表的维护确保就绪任务能够按照调度策略有机会得到执行。
五、Freertos时间片调度
FreeRTOS 支持多个任务同时拥有一个优先级这些任务的调度是一个值得考虑的问题。在 FreeRTOS 中允许一个任务运行一个时间片(一个时钟节拍的长度)后让出 CPU 的使用权让拥有同优先级的下一个任务运行至于下一个要运行哪个任务FreeRTOS 中的这种调度方法就是时间片调度。展示了运行在同一优先级下的执行时间图在优先级 N 下有 3 个就绪的任务。 1、任务 3 正在运行。 2、这时一个时钟节拍中断(滴答定时器中断)发生任务 3 的时间片用完但是任务 3 还 没有执行完。 3、FreeRTOS 将任务切换到任务 1任务 1 是优先级 N 下的下一个就绪任务。 4、任务 1 连续运行至时间片用完。 5、任务 3 再次获取到 CPU 使用权接着运行。 6、任务 3 运行完成调用任务切换函数 portYIELD()强行进行任务切换放弃剩余的时间片 从而使优先级 N 下的下一个就绪的任务运行。 7、FreeRTOS 切换到任务 1。 8、任务 1 执行完其时间片。 要使用时间片调度的话宏 configUSE_PREEMPTION 和宏 configUSE_TIME_SLICING 必须 为 1。时间片的长度由宏 configTICK_RATE_HZ 来确定一个时间片的长度就是滴答定时器的 中断周期比如本教程中 configTICK_RATE_HZ 为 1000那么一个时间片的长度就是 1ms。时 间片调度发生在滴答定时器的中断服务函数中前面讲解滴答定时器中断服务函数的时候说了 在中断服务函数 SysTick_Handler()中会调用 FreeRTOS 的 API 函数 xPortSysTickHandler()而函 数 xPortSysTickHandler() 会 引 发 任 务 调 度 但 是 这 个 任 务 调 度 是 有 条 件 的 函 数 xPortSysTickHandler()如下 上述代码中红色部分表明只有函数 xTaskIncrementTick()的返回值不为 pdFALSE 的时候就 会进行任务调度查看函数 xTaskIncrementTick()会发现有如下条件编译语句 (1)、当宏 configUSE_PREEMPTION 和宏 configUSE_PREEMPTION 都为 1 的时候下面的 代码才会编译。所以要想使用时间片调度的话这这两个宏都必须为 1缺一不可 (2)、判断当前任务所对应的优先级下是否还有其他的任务。 (3)、如果当前任务所对应的任务优先级下还有其他的任务那么就返回 pdTRUE。 从上面的代码可以看出如果当前任务所对应的优先级下有其他的任务存在那么函数 xTaskIncrementTick() 就 会 返 回 pdTURE 由 于 函 数 返 回 值 为 pdTURE 因 此 函 数 xPortSysTickHandler()就会进行一次任务切换。
五、Freertos 查找watchdog 卡在哪个任务
在vTaskSwitchContext函数中 在taskSELECT_HIGHEST_PRIORITY_TASK()后面 点灯 uxTopReadyPriority //可以点最后一个任务切到哪里去 再配合各个中断的位置点灯
六、可重入函数
如果一个函数可以从多个任务调用或者从任务和中断调用是安全的那么这个函数就是“可重入的”。可重入函数被称为“线程安全的”因为它们可以从多个线程访问而不会有数据或逻辑操作损坏的风险。 每个任务维护自己的堆栈和自己的处理器(硬件)寄存器集。如果函数不访问存储在堆栈上或保存在寄存器中的数据以外的任何数据那么函数是可重入的并且是线程安全的。
不可重入的使用了全局变量用了static修饰保存在数据段上。每个去访问的任务访问到的都是同一份。都有可能被覆盖的风险。 数据类型参考