校园网站设计与实现,科技强国从升级镜头开始,自己弄公司网站,wordpress不能实现静态化使用 RTOS 的实时应用程序可以被构建为一组独立的任务。每个任务在自己的上下文中执行#xff0c;不依赖于系统内的其他任务或 RTOS 调度器本身。在任何时间点#xff0c;应用程序中只能执行一个任务#xff0c;实时 RTOS 调度器负责决定所要执行的任务。因此#xff0c; R…使用 RTOS 的实时应用程序可以被构建为一组独立的任务。每个任务在自己的上下文中执行不依赖于系统内的其他任务或 RTOS 调度器本身。在任何时间点应用程序中只能执行一个任务实时 RTOS 调度器负责决定所要执行的任务。因此 RTOS 调度器可以在应用程序执行时重复启停每个任务将任务调入或调出。由于任务不了解 RTOS 调度器活动因此实时 RTOS 调度器负责确保任务调入时的处理器上下文寄存器值、堆栈内容等与任务调出时的处理器上下文完全相同。为实现这一点每个任务都分配有自己的堆栈。当任务调出时执行上下文被保存到该任务的堆栈中以便以后再调入相同的任务时可以准确地恢复其执行上下文。
任务状态
FreeRTOS中任务共有4中状态
运行态正在执行的任务该任务就处于运行态。如果运行 RTOS 的处理器只有一个内核 那么在任何给定时间内都只能有一个任务处于运行状态。就绪态准备就绪任务指那些能够执行它们不处于阻塞或挂起状态 但目前没有执行的任务 因为同等或更高优先级的不同任务已经处于运行状态。阻塞态如果一个任务因延时或者等待外部事件发生那么这个任务就处于阻塞态。 例如如果一个任务调用vTaskDelay()它将被阻塞被置于阻塞状态 直到延迟结束——一个时间事件。 任务也可以通过阻塞来等待队列、信号量、事件组、通知或信号量 事件。 处于阻塞状态的任务通常有一个超时期 超时后任务将被超时并被解除阻塞 即使该任务所等待的事件没有发生。“阻塞”状态下的任务不使用任何处理时间不能 被选择进入运行状态。挂起态类似暂停。与“阻塞”状态下的任务一样 “挂起”状态下的任务不能 被选择进入运行状态但处于挂起状态的任务 没有超时。 相反任务只有在分别通过 vTaskSuspend() 和 xTaskResume() API 调用明确命令时 才会进入或退出挂起状态。
任务调度
FreeRTOS一共支持三种任务调度方式
抢占式调度主要是针对优先级不同的任务每一个任务都有一个优先级优先级高的任务可以抢占优先级低的任务。时间片调度主要针对优先级相同的任务当多个任务的优先级相同时任务调度器会在每一次系统时钟节拍到的时候切换任务。协程式调度官方表示不再更新协程式调度。
“时间片” 是指调度器会在每个 tick 中断上在同等优先级任务之间进行切换 tick 中断之间的时间构成一个时间片。tick 中断是 RTOS 用来衡量时间的周期性中断。
总是运行优先级最高且可运行的任务的后果是 永远不会进入“阻塞”或 “挂起”状态的高优先级任务会让所有任意执行时长的低优先级任务永久饥饿 。这就是为什么通常最好创建事件驱动型任务的原因之一 。例如如果一个高优先级任务正在等待一个事件 那么它就不应处于该事件的循环轮询中因为如果处于轮询中它会一直运行永远不进入“阻塞”或“挂起”状态。 反之该任务应进入“阻塞” 状态来等待事件。可以使用众多 FreeRTOS 任务间通信和同步原语之一将事件发送给任务。接收到 事件后 优先级更高的任务会自动解除“阻塞”状态。高优先级任务处于“阻塞”状态时 低优先级任务会运行。
动态创建任务和删除任务
#define configSUPPORT_DYNAMIC_ALLOCATION 1上述宏定义配置为1的时候才支持动态创建。 BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,const char * const pcName,const configSTACK_DEPTH_TYPE uxStackDepth,void *pvParameters,UBaseType_t uxPriority,TaskHandle_t *pxCreatedTask);
pvTaskCode指向任务入口函数的指针即实现任务的函数名称。任务通常以无限循环的形式实现实现任务的函数绝不能阐释返回或者退出。除非返回前自行删除。pcName任务的描述性名称可以用于获取任务句柄。uxStackDepth要分配的用作任务堆栈的字数不是字节数STM32中一个字是4字节。这个堆栈会自动从FreeRTOS堆中分配。pvParameters作为参数传递给所创建任务的值。如果 pvParameters 设置为某变量的地址 则在创建的任务执行时该变量必须仍然存在 因此不能传递局部变量的地址。uxPriority创建的任务将以该指定优先级执行优先级默认上限为 (configMAX_PRIORITIES - 1)。该值越大表示优先级越高。pxCreatedTask用于将句柄传递至由 xTaskCreate() 函数创建的任务。pxCreatedTask 是可选参数 可设置为 NULL。
创建一项新任务的时候会将其添加到就绪任务列表中。
void vTaskDelete( TaskHandle_t xTask );xTask要删除的任务的句柄。如果传递 NULL会删除调用任务。
从RTOS内核管理中删除任务时要删除的任务将从所有就绪、阻塞、挂起和事件列表中移除。空闲任务负责释放由RTOS内核分配给已删除任务的内存。因此如果应用程序调用了vTaskDelete请务必确保空闲任务获取足够的微控制器处理时间。任务代码分配的内存不会自动释放应在任务删除之前手动释放。
任务的挂起和恢复
void vTaskSuspend( TaskHandle_t xTaskToSuspend );xTaskToSuspend被挂起的任务句柄。传递空句柄将导致调用任务被挂起。
挂起的任务将无法获取任何微控制器处理时间。对vTaskSuspend的调用不会累计计数若在同一任务上调用多次仍然仅需调用一次vTaskResume即可恢复挂起的任务。
void vTaskResume( TaskHandle_t xTaskToResume );BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume );
xTaskToResume待恢复任务的句柄。FromISR带FromISR后缀的函数表示只能在中断中调用。
返回
返回 pdTRUE需要进行任务上下文切换。实际应该比较了任务优先级如果恢复了优先级较高的任务则返回pdTRUE返回 pdFALSE。不需要上下文切换。
portYIELD_FROM_ISR(x)调用此函数进行任务上下文切换传入参数不为pdFALSE时就执行上下文切换函数。
注意任务挂起就是相当于暂停任务恢复就是继续执行。所以任务恢复的时候不是说在任务函数中从头开始。
其他
在FreeRTOS中PendSV和SysTick中断是设置为最低优先级的优先级值为15并且不可更改这样做的目的是保证系统任务切换时不会阻塞系统其他中断的响应。PendSV中断函数中进行任务切换SysTick中断函数中进行时基计数。中断服务函数的优先级需在FreeRTOS所管理的范围内默认设置为5~15如果使用MX配置优先级的话也只能在这个范围。在中断服务函数里边调用FreeRTOS的API函数必须使用带“FromISR”后缀的函数。
临界段代码保护
临界段也叫做临界区是指那些必须完整运行不能被打断的代码段。
适用场合如
外设需要严格按照时序初始化的外设如i2cspi等。系统系统自身需求。用户用户需求。
那么什么东西可以打断当前的程序呢有中断有系统任务调度器。其实任务调度器也是在PendSV中断函数中调用的所以如果关闭中断就没有东西可以打断程序了。
本质FreeRTOS在进入临界段代码的时候其实是关闭中断当处理完临界段代码以后再打开中断。
void taskENTER_CRITICAL( void );
void taskEXIT_CRITICAL( void );UBaseType_t taskENTER_CRITICAL_FROM_ISR( void );
void taskEXIT_CRITICAL_FROM_ISR( UBaseType_t uxSavedInterruptStatus );需要成对使用支持嵌套使用尽量保持临界段代码耗时短
任务调度器的挂起和恢复
挂起任务调度器调用此函数不需要关闭中断。
void vTaskSuspendAll( void );
BaseType_t xTaskResumeAll( void );与临界区不一样的是挂起任务调度器未关闭中断。它仅仅是防止任务之间的资源争夺中断照样可以直接响应。xTaskResumeAll仅恢复调度器不会恢复之前通过调用vTaskSuspend而挂起的任务。