简介
事件应该是RTOS系统最基本的通信方式了,在RTX中,事件可以与和或两种方式。
关键结构
事件太简单了,以至于都没有一个结构体,直接在任务控制块OS_TCB中加了两个字段:
U16 events; /* Event flags 当前置位的标志位 */
U16 waits; /* Wait flags 必须等待的标志位
关键实现
rt_evt_wait
等待事件函数,支持与等待和或等待,以及设定超时时间:
OS_RESULT rt_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait) {
/* Wait for one or more event flags with optional time-out. */
/* "wait_flags" identifies the flags to wait for. */
/* "timeout" is the time-out limit in system ticks (0xffff if no time-out) */
/* "and_wait" specifies the AND-ing of "wait_flags" as condition to be met */
/* to complete the wait. (OR-ing if set to 0). */
U32 block_state;
if (and_wait) {//如果是与方式等待
/* Check for AND-connected events */
if ((os_tsk.run->events & wait_flags) == wait_flags) {//如果标志位已经置位,则直接成功,返回OS_R_EVT
os_tsk.run->events &= ~wait_flags;
return (OS_R_EVT);
}
block_state = WAIT_AND;//如果标志位还没有完成,则进入等待
}
else {//如果是或方式等待
/* Check for OR-connected events */
if (os_tsk.run->events & wait_flags) {//如果标志位已经置位,则直接成功,返回OS_R_EVT
os_tsk.run->waits = os_tsk.run->events & wait_flags;
os_tsk.run->events &= ~wait_flags;
return (OS_R_EVT);
}
block_state = WAIT_OR;
}
/* Task has to wait */
os_tsk.run->waits = wait_flags;//设置状态
rt_block (timeout, (U8)block_state);//阻塞当前任务
return (OS_R_TMO);
}
rt_evt_set
指定任务来设置事件函数:
void rt_evt_set (U16 event_flags, OS_TID task_id) {
/* Set one or more event flags of a selectable task. */
P_TCB p_tcb;
p_tcb = os_active_TCB[task_id-1];
if (p_tcb == NULL) {//非法任务
return;
}
p_tcb->events |= event_flags;
event_flags = p_tcb->waits;
/* If the task is not waiting for an event, it should not be put */
/* to ready state. */
if (p_tcb->state == WAIT_AND) {//如果是与等待
/* Check for AND-connected events */
if ((p_tcb->events & event_flags) == event_flags) {//判断事件是否充足,如果是的话直接跳转到wkup标签
goto wkup;
}
}
if (p_tcb->state == WAIT_OR) {//如果是或等待
/* Check for OR-connected events */
if (p_tcb->events & event_flags) {
p_tcb->waits &= p_tcb->events;
wkup: p_tcb->events &= ~event_flags;//清除事件标志
rt_rmv_dly (p_tcb);//从延时任务链表清除该任务
p_tcb->state = READY;//状态恢复成就绪
#ifdef __CMSIS_RTOS
rt_ret_val2(p_tcb, 0x08/*osEventSignal*/, p_tcb->waits); //设置被恢复任务的返回值,如果是或等待的话,这里会把置位的标志位返回。
#else
rt_ret_val (p_tcb, OS_R_EVT);
#endif
rt_dispatch (p_tcb);//申请一次任务调度
}
}
}
rt_evt_clr
太简单,不解释:
void rt_evt_clr (U16 clear_flags, OS_TID task_id) {
/* Clear one or more event flags (identified by "clear_flags") of a */
/* selectable task (identified by "task"). */
P_TCB task = os_active_TCB[task_id-1];
if (task == NULL) {
return;
}
task->events &= ~clear_flags;//清除当前获得的标志位
}
isr_evt_set
在中断中设置事件,必须调用该函数,将处理放进队列,延迟到PendSV_Handler中断服务程序中执行:
void isr_evt_set (U16 event_flags, OS_TID task_id) {
/* Same function as "os_evt_set", but to be called by ISRs. */
P_TCB p_tcb = os_active_TCB[task_id-1];
if (p_tcb == NULL) {
return;
}
rt_psq_enq (p_tcb, event_flags);//放入队列 最大支持16级
rt_psh_req ();
}