本帖最后由 Simon21ic 于 2014-10-20 21:56 编辑
动态多任务实质上,是实现task类,然后实现task实例,代码中,动态分配task的资源,设置相应task的参数,并且由系统调度。大部分情况下,只有在操作系统的环境下,才能怎么使用的。
在VSF构架中,定义了完整的EDA状态机类(同样的类,可以实现为EDA构架、EDA状态机、EDA层次状态机),并且,支持子状态机。VSF构架中的PT线程,也是挂载在EDA状态机类上的线程类。所以,EDA状态机类可以动态生成,并且,PT线程类也可以动态生成。这样就很容易实现动态多线程。
一般方法为,定义好PT类的子类,并且实现相应的应用功能。在PT线程中,EDA状态机类只是一个外壳,所以简单生成一个基本的EDA状态机类就行,只需要实现init状态机,并且设置evt_handler为vsfpt_evt_handler,之后这个状态机就作为PT状态机运行了,EDA状态机实例的初始化中,会发送INIT事件,vsfpt_evt_handler会启动pt线程的thread线程,线程处理完毕后,把自己删除并且释放相应的资源(注意,释放完资源后,就不能再访问相应的线程的资源了)。
一般的应用环境,在请求-相应模型中,系统收到请求事件后,动态分配相应的资源,建立一个相应请求的PT线程,然后,作为子状态机挂载到当前EDA上去。
代码举例,使用USBCDC实现的串口命令行界面:
设备收到一个OUT数据包事件的时候,会对每个字符生成一个按键事件发送给命令行界面的事件处理器,命令行界面的事件处理器当收到回车事件后,便动态分配命令处理线程的资源,然后挂载为自己的子线程,之后任务调度器就会发送INIT等事件,执行相应的线程。简单示例代码如下:
https://github.com/versaloon/vsf/tree/master/vsf/example/vsfusbd_eda
就不多介绍代码了,能看懂的来举个手。
只是简单说一下功能:
实现的是一个IAD的USB组合设备,一个HID和一个CDC,CDC上实现了一个命令行,可以支持后台运行的命令,可以支持多个命令同时运行(前台命令只能有一个)。
下面是delayms命令的处理代码,能看出来是不是阻塞的代码?
static vsf_err_t
vsfshell_delayms_handler(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
{
struct vsfshell_handler_param_t *param =
(struct vsfshell_handler_param_t *)pt->user_data;
struct vsfshell_t *shell = param->shell;
vsfsm_pt_begin(pt);
if (param->argc != 2)
{
vsfshell_print_string(shell, "invalid format." VSFSHELL_LINEEND);
vsfshell_print_string(shell, "format: delayms MS" VSFSHELL_LINEEND);
goto handler_thread_end;
}
param->priv = MALLOC(sizeof(struct vsftimer_timer_t));
if (NULL == param->priv)
{
vsfshell_print_string(shell, "not enough resources." VSFSHELL_LINEEND);
goto handler_thread_end;
}
memset(param->priv, 0, sizeof(struct vsftimer_timer_t));
((struct vsftimer_timer_t *)param->priv)->sm = pt->sm;
((struct vsftimer_timer_t *)param->priv)->evt = VSFSM_EVT_USER_LOCAL_INSTANT;
((struct vsftimer_timer_t *)param->priv)->interval = strtoul(param->argv[1], NULL, 0);
vsftimer_register((struct vsftimer_timer_t *)param->priv);
vsfsm_pt_wfe(pt, VSFSM_EVT_USER_LOCAL_INSTANT);
vsftimer_unregister((struct vsftimer_timer_t *)param->priv);
vsfsm_pt_end(pt);
handler_thread_end:
if (param->priv != NULL)
{
FREE(param->priv);
}
vsfshell_handler_exit(pt);
return VSFERR_NONE;
}
|