本帖最后由 vsf 于 2018-4-5 22:25 编辑
前一章讲了,应用需求中,事件需要具备不同的优先级。比如,串口接收数据事件中,先收下数据,然后发送低优先级的GUI更新事件。GUI更新事件的处理会占用大量CPU,所以不适合在串口接收事件中直接处理。而最简事件驱动模型是不能支持事件的优先级的。
VSF中使用了事件队列来实现这个功能。简单说的话,就是实现一个低优先级的事件队列,在高优先级事件处理的过程中,发送的低优先级事件,都放到低优先级事件队列了。事件队列实质是一个事件的fifo,先产生的事件,会先进入事件队列,也会先拿出来处理。
struct event_queue_t evtq;
void event_handler(int event)
{
switch (event)
{
case EVENT_X:
process_event_x();
evtq_push(&evtq, EVENT_LOW_PRIORITY);
break;
}
}
void post_event(int event)
{
event_handler(event);
}
void X_IRQ(void)
{
post_event(EVENT_X);
}
void event_handler_low_priority(int event)
{
switch (event)
{
case EVENT_LOW_PRIORITY:
break;
}
}
void main(void)
{
enable_X_IRQ();
while (1)
{
if (evtq_has_event(&evtq))
{
int event = evtq_pop(&evtq);
event_handler_low_priority(event);
}
else
vsfhal_core_sleep();
}
}
在这个示例中,定义了一个事件队列evtq,在高优先级EVENT_X事件处理中,会把EVENT_LOW_PRIORITY低优先级事件发送到evtq里去。然后,event_handler退出,最终X_IRQ退出,由于MCU被唤醒了,继续运行main中的代码。这里main里的代码发现事件队列里有事件,就拿出事件,调用低优先级的event_handler_low_priority处理。
这里就是VSF中,实现抢占式的原理。main里运行的低优先级事件队列,可以被中断抢占。VSF中的抢占特性,其实就只是MCU的中断抢占main函数的特性而已。
另外,如果把中断里的事件处理,也看成是一个事件队列的话(事件队里的特例,事件一旦push进队列,会马上pop出来处理)。那其实具备抢占能力的是事件队列,而不是事件本身。事件队列具备抢占能力,也只是因为低优先级事件队列是在main函数中处理,这个用于实现非实时事件队列。而在低优先级中断里,处理的事件,可以抢占main中的代码,这个用于实现软实时事件队列。
|