| 
 
| 本帖最后由 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里的代码有潜在性的问题,看看谁能看出来。
 
 | 
 |