本帖最后由 Simon21ic 于 2015-11-8 21:35 编辑
之前自己介绍的系统构架中,vsfsm_t实现了事件驱动的状态机构架,但是纯粹的事件驱动开发方式很麻烦。
于是,引入的PT的方式,实现线程。PT是一种共享堆栈的线程,每次被调用,需要重建对战,而且,之前堆栈里的变量不被保留。这个就是这套系统构架开发难度较高的一个原因。
现在准备引入一种新的多任务机制,这种方式类似RTOS,每个任务需要自己的独立堆栈,任务使用上下文切换的方式来切换。当然,我还是把这个使用面向对象的方式封装了一下,并且还是基于vsfsm_t的事件驱动构架。
这种方式就是利用C语言的setjmp和longjmp来实现的多任务。
上代码:static struct vsfsm_state_t *
vsfsm_ljmp_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
struct vsfsm_ljmp_t *ljmp = (struct vsfsm_ljmp_t *)sm->user_data;
jmp_buf ret;
if ((evt == VSFSM_EVT_ENTER) || (evt == VSFSM_EVT_EXIT))
{
return NULL;
}
memset(&ret, 0, sizeof(ret));
ljmp->ret = &ret;
if (!setjmp(ret))
{
if (evt == VSFSM_EVT_INIT)
{ core_interfaces.core.set_stack((uint32_t)ljmp->stack);
ljmp->thread(ljmp);
}
else
{
longjmp(ljmp->pos, evt);
}
}
return NULL;
}
vsf_err_t vsfsm_ljmp_init(struct vsfsm_t *sm, struct vsfsm_ljmp_t *ljmp)
{
sm->user_data = ljmp;
sm->init_state.evt_handler = vsfsm_ljmp_evt_handler;
ljmp->sm = sm;
return vsfsm_init(sm);
}
这个代码只是示例代码,还不是最终的实现代码。
和vsfsm_pt_evt_handler类似,vsfsm_ljmp_evt_handler是处理ljmp的事件处理函数。
这里就只是在INIT事件中,调用thread,然后其他事件里,直接longjmp跳转到对应任务的记录点。
longjmp的方式,可以简单认为是一个可以跨任务的超级goto。
当然,ljmp->thread的实现也会有一些讲究,任务如果运行到等待某个事件的时候,也需要longjmp回evt_handler。
然后,ljmp的wfe宏定义如下:
#define vsfsm_ljmp_wfe(ljmp, e) \
do {\
vsfsm_evt_t __evt = setjmp((ljmp)->pos);\
if (!__evt || (__evt != (e)))\
longjmp(*(ljmp)->ret, 0);\
} while (0)
测试的应用代码:
void ljmp_test_thread(struct vsfsm_ljmp_t *ljmp)
{
if (vsftimer_create(ljmp->sm, 100, -1, VSFSM_EVT_USER) != NULL)
{
while (1)
{
vsfsm_ljmp_wfe(ljmp, VSFSM_EVT_USER);
asm("nop");
}
}
}
说明:
未完待续。。。先看看有多少人可以自己看懂。
另外,vsfsm_ljmp_evt_handler里的代码有潜在性的问题,看看谁能看出来。
|