3.6 接收事件
[cpp] view plaincopyprint
/**
* This function will receive an event from event object, if the event is
* unavailable, the thread shall wait for a specified time.
*
* @param event the fast event object
* @param set the interested event set
* @param option the receive option
* @param timeout the waiting time
* @param recved the received event
*
* @return the error code
*/
rt_err_t rt_event_recv(rt_event_t event,
rt_uint32_t set,//感光趣的事件集
rt_uint8_t option,//过滤模式
rt_int32_t timeout,
rt_uint32_t *recved)
{
struct rt_thread *thread;
register rt_ubase_t level;
register rt_base_t status;
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不在ISR中使用
/* parameter check */
RT_ASSERT(event != RT_NULL);
if (set == 0)//如果不对任何事件感兴趣则直接返回
return -RT_ERROR;
/* init status */
status = -RT_ERROR;
/* get current thread */
thread = rt_thread_self();//获取当前线程
/* reset thread error */
thread->error = RT_EOK;//重置线程的err码
RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(event->parent.parent)));
/* disable interrupt */
level = rt_hw_interrupt_disable();//关中断
/* check event set */
if (option & RT_EVENT_FLAG_AND)//如果过滤选项为逻辑与
{
if ((event->set & set) == set)//判断是否已接收到所有感兴趣的事件
status = RT_EOK;
}
else if (option & RT_EVENT_FLAG_OR)//如果过滤选项为逻辑或
{
if (event->set & set)//判断是否接收到任一感兴趣的事件
status = RT_EOK;
}
if (status == RT_EOK)//如果接收事件已成功
{
/* set received event */
*recved = (event->set & set);//保存接收到的事件集到recved指向的空间
/* received event */
if (option & RT_EVENT_FLAG_CLEAR)//清除接收到的事件集
event->set &= ~set;
}
else if (timeout == 0)//如果没有接收到事件,且等待参数为0,则立即返回错误
{
/* no waiting */
thread->error = -RT_ETIMEOUT;
}
else//如果没有接收到事件,且等待参数不为0,则需要阻塞当前线程
{
/* fill thread event info */
thread->event_set = set;
thread->event_info = option;
/* put thread to suspended thread list */
rt_ipc_list_suspend(&(event->parent.suspend_thread),//挂起当前线程
thread,
event->parent.parent.flag);
/* if there is a waiting timeout, active thread timer */
if (timeout > 0)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),//设置定时器参数
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));//启动定时器
}
/* enable interrupt */
rt_hw_interrupt_enable(level);//开中断
/* do a schedule */
rt_schedule();//开始重新调度,此时当前线程才真正挂起
if (thread->error != RT_EOK)//只有两种可能才能运行到这:1 定时器超时,当前线程还是没有等到事件的到达,此时,定时器的超时回调处理函数内会将thread的error设置为-RT_ETIMOUT;2:事件到达,当前线程被唤醒,此时thread的error还是保持原值不变
{
/* return error */
return thread->error;//没有等到事件到达,则直接返回错误码
}
/* received an event, disable interrupt to protect */
level = rt_hw_interrupt_disable();//开中断,此时已等到事件的到来
/* set received event */
*recved = thread->event_set;//保存接收到的事件集到recved指向的内存
}
/* enable interrupt */
rt_hw_interrupt_enable(level);//开中断
RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(event->parent.parent)));
return thread->error;
}
/**
* This function will receive an event from event object, if the event is
* unavailable, the thread shall wait for a specified time.
*
* @param event the fast event object
* @param set the interested event set
* @param option the receive option
* @param timeout the waiting time
* @param recved the received event
*
* @return the error code
*/
rt_err_t rt_event_recv(rt_event_t event,
rt_uint32_t set,//感光趣的事件集
rt_uint8_t option,//过滤模式
rt_int32_t timeout,
rt_uint32_t *recved)
{
struct rt_thread *thread;
register rt_ubase_t level;
register rt_base_t status;
RT_DEBUG_NOT_IN_INTERRUPT;//确保此函数不在ISR中使用
/* parameter check */
RT_ASSERT(event != RT_NULL);
if (set == 0)//如果不对任何事件感兴趣则直接返回
return -RT_ERROR;
/* init status */
status = -RT_ERROR;
/* get current thread */
thread = rt_thread_self();//获取当前线程
/* reset thread error */
thread->error = RT_EOK;//重置线程的err码
RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(event->parent.parent)));
/* disable interrupt */
level = rt_hw_interrupt_disable();//关中断
/* check event set */
if (option & RT_EVENT_FLAG_AND)//如果过滤选项为逻辑与
{
if ((event->set & set) == set)//判断是否已接收到所有感兴趣的事件
status = RT_EOK;
}
else if (option & RT_EVENT_FLAG_OR)//如果过滤选项为逻辑或
{
if (event->set & set)//判断是否接收到任一感兴趣的事件
status = RT_EOK;
}
if (status == RT_EOK)//如果接收事件已成功
{
/* set received event */
*recved = (event->set & set);//保存接收到的事件集到recved指向的空间
/* received event */
if (option & RT_EVENT_FLAG_CLEAR)//清除接收到的事件集
event->set &= ~set;
}
else if (timeout == 0)//如果没有接收到事件,且等待参数为0,则立即返回错误
{
/* no waiting */
thread->error = -RT_ETIMEOUT;
}
else//如果没有接收到事件,且等待参数不为0,则需要阻塞当前线程
{
/* fill thread event info */
thread->event_set = set;
thread->event_info = option;
/* put thread to suspended thread list */
rt_ipc_list_suspend(&(event->parent.suspend_thread),//挂起当前线程
thread,
event->parent.parent.flag);
/* if there is a waiting timeout, active thread timer */
if (timeout > 0)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),//设置定时器参数
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));//启动定时器
}
/* enable interrupt */
rt_hw_interrupt_enable(level);//开中断
/* do a schedule */
rt_schedule();//开始重新调度,此时当前线程才真正挂起
if (thread->error != RT_EOK)//只有两种可能才能运行到这:1 定时器超时,当前线程还是没有等到事件的到达,此时,定时器的超时回调处理函数内会将thread的error设置为-RT_ETIMOUT;2:事件到达,当前线程被唤醒,此时thread的error还是保持原值不变
{
/* return error */
return thread->error;//没有等到事件到达,则直接返回错误码
}
/* received an event, disable interrupt to protect */
level = rt_hw_interrupt_disable();//开中断,此时已等到事件的到来
/* set received event */
*recved = thread->event_set;//保存接收到的事件集到recved指向的内存
}
/* enable interrupt */
rt_hw_interrupt_enable(level);//开中断
RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(event->parent.parent)));
return thread->error;
}
接收线程比较简单,如果接收到事件则判断它是否为它关心的事件,如果是,则保存事件,如果不是,则当没有接收到事件情况一起处理。接下来就是没有事件到达的情况,还是老规矩,先判断时间参数是否为0,如果是则直接返回超时,如果不是,则设置一定时器然后启动它,接着重新调度线程,然后根据当前线程的error值是否为RT_EOK来判断是否有新的并且符合条件的事件到达,如果不是,则返回错误码,如果是,则保存事件,最终返回OK。