UCOS的进程间通讯机制有:
1、信号量
作用:控制共享资源的使用权,标志事件的发生,使两个任务的行为进行同步
2、邮箱
它可以使一个任务或者中断的子程序向另一个任务发送一个指针型变量,该变量包含特定的消息
3、信息队列:
它可以使一个任务或者中断的子程序向另一个任务发送一个指针型变量,该变量根据情况而定、
-------------------------------------------------------------------------------------------------------------------------------------------------------------
下面主要讲三个结构体:
typedef struct os_tcb ---- 进程控制块
typedef struct os_event -- 事件控制块
typedef struct os_flag_node -- 标志事件控制块
-------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct os_tcb 这个变量就是用来每个进程都需要的一个变量,叫任务控制块。
{
OS_STK *OSTCBStkPtr; // 指向任务栈栈顶的指针 ,每个进程有自己的栈空间,在进程切换的时候会用到
这个栈空间来保存当前任务的状态 |CPSR|SPSR|R0~R12|IR|PC| (注:OS_STK就是一个整数型)
// 下面这几个变量只能在OsTaskCreateExt()中使用
#if OS_TASK_CREATE_EXT_EN > 0 //如果使用额外的任务控制块。
// 指向用户自定义的任务控制块扩展
void *OSTCBExtPtr; /* Pointer to user definable data for TCB extension */
// 指向任务栈栈底的指针
OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack */
// 栈的容量,单位是地址(可能是16bit/32bit)
INT32U OSTCBStkSize; /* Size of task stack (in number of stack elements) */
// 传递给OsTaskCreateExt()的选择项
INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */
// 任务ID
INT16U OSTCBId; /* Task ID (0..65535) */
#endif
struct os_tcb *OSTCBNext; // 下一个TCB ,TCB链表是双向链
struct os_tcb *OSTCBPrev; // 上一个TCB ,
#if OS_EVENT_EN
// 指向事件控制块的指针
OS_EVENT *OSTCBEventPtr; //一些事件的指针
#endif
// 指向传递给任务的消息的指针
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
void *OSTCBMsg; //指向信息的指针
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
// 指向事件标志节点的指针
OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */
#endif
OS_FLAGS OSTCBFlagsRdy; // 当任务等待事件标志组时, 任务进入就绪态的标志
#endif
// 任务延时等待的时间长度,单位是tick
INT16U OSTCBDly;
// 任务的状态,如:运行,等待,就绪
INT8U OSTCBStat;
// 延时等待最大时间是否已经到了
BOOLEAN OSTCBPendTO; /* Flag indicating PEND timed out (OS_TRUE == timed out) */
// 任务的优先级
INT8U OSTCBPrio;
// 在任务创建时就算好下面4个变量的值,用于加速任务进入就绪态的过程
//UCOS最大的进程数是64,由下面的两个两边的来进行定位
INT8U OSTCBX; /* Bit position in group corresponding to task priority */
INT8U OSTCBY; /* Index into ready table corresponding to task priority */
#if OS_LOWEST_PRIO <= 63
INT8U OSTCBBitX; /* Bit mask to access bit position in ready table */
INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */
#else
INT16U OSTCBBitX; /* Bit mask to access bit position in ready table */
INT16U OSTCBBitY; /* Bit mask to access bit position in ready group */
#endif
#if OS_TASK_DEL_EN > 0
// 标志该任务是否需要被删除
INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */
#endif
#if OS_TASK_PROFILE_EN > 0
INT32U OSTCBCtxSwCtr; /* Number of time the task was switched in */
INT32U OSTCBCyclesTot; /* Total number of clock cycles the task has been running */
INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption */
OS_STK *OSTCBStkBase; /* Pointer to the beginning of the task stack */
INT32U OSTCBStkUsed; /* Number of bytes used from the stack */
#endif
#if OS_TASK_NAME_SIZE > 1
// 任务名
INT8U OSTCBTaskName[OS_TASK_NAME_SIZE];
#endif
}
//关于事件的指针// 事件控制块
typedef struct os_event
{
// 事件类型: 信号量、邮箱或消息队列
INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_xxxx) */
// 指向消息或者消息队列的指针:
// 当所定义的事件是邮箱时,它指向一个消息,
// 当所定义的事件是消息队列时,它指向一个数据结构
void *OSEventPtr; /* Pointer to message or queue structure */
// 计数器(当事件是信号量时)
INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */
#if OS_LOWEST_PRIO <= 63
// 等待任务所在的组
INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
// 等待任务表
INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
#else
INT16U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */
INT16U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */
#endif
#if OS_EVENT_NAME_SIZE > 1
INT8U OSEventName[OS_EVENT_NAME_SIZE];
#endif
} OS_EVENT;
#endif
//这个结构体是用来记录标志事件的
typedef struct os_flag_node { /* Event Flag Wait List Node */
void *OSFlagNodeNext; /* Pointer to next NODE in wait list */
void *OSFlagNodePrev; /* Pointer to previous NODE in wait list */
void *OSFlagNodeTCB; /* Pointer to TCB of waiting task */
void *OSFlagNodeFlagGrp; /* Pointer to Event Flag Group */
OS_FLAGS OSFlagNodeFlags; /* Event flag to wait on */
INT8U OSFlagNodeWaitType; /* Type of wait: */
/* OS_FLAG_WAIT_AND */
/* OS_FLAG_WAIT_ALL */
/* OS_FLAG_WAIT_OR */
/* OS_FLAG_WAIT_ANY */
} OS_FLAG_NODE;
#endif
-----------------------------------------------------------------------------------------------------------------------------
就绪表:
系统就是根据最高优先级,通过就绪表快速找出那个进程可以执行。优先级的高三位就是表示组别(Y),低三位表示的是组别里面的具体任务,形成了8x8的矩阵,也就是可以管理64个任务。为了能够快速查找优先级最高的任务,就通过简立一个表来查询,
OSRdyGrp -- 用来记录第几组
OSRdyTbl[ptcb->OSTCBY] -- 记录对应组中第几个任务
他们的转换如下
-
y = OSUnMapTbl[OSRdyGrp];
-
x = OSUnMapTbl[OSRdyTbl[y]];
-
prio = (y << 3) + x;