目录
本章基于FreeRtos V9.0.0版本分析
一、协程简介
FreeRtos中应用既可以使用任务,也可以使用协程(Co-Routine),或者两者混合使用。但是任务和协程使用不同的API函数,因此不能通过队列(信号量)将数据从任务发给协程,反之亦然。
与任务相比,协程的调度在线程中,不支持抢占调度,只能使用协作式调度,实时精度低;由于没有中断参与,协程具有占用资源少、CPU利用率高的优点。协程与定时器有点类似。
注意:任务与协程混合使用时,协程的调度可以在某个任务中。
二、协程工作机制
2.1 协程控制块结构
与任务相比较,协程控制块即可表示整个协程,不存在协程栈,也不存在上下文切换。
// 协程的回调函数(参数1:协程控制块句柄,参数2:协程ID uxIndex)
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
// 协程结构体
typedef struct corCoRoutineControlBlock
{
crCOROUTINE_CODE pxCoRoutineFunction; /*< 入口函数. */
ListItem_t xGenericListItem; /*< 协程状态条目,用于状态切换. */
ListItem_t xEventListItem; /*< 协程事项表项,用于信号等阻塞*/
UBaseType_t uxPriority; /*< 优先级. */
UBaseType_t uxIndex; /*< ID,当多个协程使用相同入口函数时,用于区分协同例程,为回调函数的第二个参数 */
uint16_t uxState; /*< 协程状态. */
} CRCB_t; /* 协同程序控制块。Note的大小必须与TCB_t的uxPriority相同. */
2.2 协程管理方式
协程的管理方式与任务管理类似,通过链表管理,链表定义如下:
/* 就绪和闭锁协程队列. --------------------*/
static List_t pxReadyCoRoutineLists[configMAX_CO_ROUTINE_PRIORITIES]; /*< 就绪链表. */
static List_t xDelayedCoRoutineList1; /*< 阻塞链表1. */
static List_t xDelayedCoRoutineList2; /*< 阻塞链表2. */
static List_t * pxDelayedCoRoutineList; /*< 指向当前阻塞链表 */
static List_t * pxOverflowDelayedCoRoutineList; /*< 指向溢出阻塞链表. */
static List_t xPendingReadyCoRoutineList; /*< 临时就绪链表,*/
链表结构和操作方式可参考《基于STM32F103ZE平台分析FreeRtos(二)——任务部分》章节。
就绪链表:链接就绪协程,根据协程插入链表的先后顺序排列,新就绪协程插入到链表尾部。
阻塞链表:连接阻塞协程,采用双链表管理,阻塞协程根据阻塞时间片大小,按照从大到小的顺序插入链表,表头指向阻塞时间最近的协程。
双链表管理方式可参考《基于STM32F103ZE平台分析FreeRtos(二)——任务部分》章节。
临时就绪链表:中断中使用,当中断需要释放阻塞协程时,为避免数据冲突,不会直接操作就绪链表,会将释放的协程先插入到临时就绪链表。在协程调度中,由调度器将临时链表中的协程移到正式就绪链表中。
2.3 协程调度方式
协程只有协作式调度,调度器在线程中循环进行,不存在上下文切换,一个协程执行完成后才能执行下一个协程,每次从协程的回调函数入口执行,每次循环执行一个协程的回调函数。
调度的原则是选择优先级最高的协程执行,如果优先级最高的协程有多个,则轮询执行这几个协程。
2.4 协程通信机制
协程支持从中断和线程中以FIFO方式操作消息队列,实现协程间的通信,操作过程与任务类似,但是不能与任务共用消息队列。
当协程与任务混合使用时,协程调度基于某个任务存在,此时协程可以通过调用任务的通信接口与任务通信,其本质还是任务间的通信。
三、协程状态及状态切换
3.1 协程状态
1、就绪( Ready):该协程在就绪链表(pxReadyCoRoutineLists[])或临时就绪链表(xPendingReadyCoRoutineList)中, 就绪的协程已经具备执行的能力,等待调度器调度。
2、运行(Running):该协程在就绪列表中,但是正在调度中执行, 调度器选择运行的永远是处于最高优先级的就绪态协程。
3、阻塞(Blocked): 如果协程正在等待消息,就会从就绪链表移除,并根据阻塞时间插入到阻塞链表中。