打印
[资料分享与下载]

在M0上跑事件驱动构架

[复制链接]
957|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
DreamofOven|  楼主 | 2015-12-24 20:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
初次接触非对称双核MCU,由于之前好多知识不熟悉,这三天遇到不少问题。现在终于把事件驱动在M0核上跑起来了,就发一贴简单介绍下这个事件驱动构架和这几天的5410x芯片学习所得。
关于事件驱动架构,其主要用于低功耗设计,可以很方便的进入休眠模式。一般单片机裸奔都是轮询,如:
void main()
{
    while(1)
    {
        tesk1();
        tesk2();
        tesk3();
    }
}


相关帖子

沙发
DreamofOven|  楼主 | 2015-12-24 20:18 | 只看该作者
在这种轮询处理中,很难判断在何时休眠,该休眠多长时间,又该使用什么等级的休眠。

而事件驱动的main函数如下(以VSF为例):
 while (1)
        {
                vsfsm_poll();

                vsf_enter_critical();
                if (!vsfsm_get_event_pending())
                {
                        vsf_leave_critical();
                        __WFI();
                }
                else
                {
                        vsf_leave_critical();
                }
        }

使用特权

评论回复
板凳
DreamofOven|  楼主 | 2015-12-24 20:18 | 只看该作者
VSF在程序中增加了一个事件队列,当这个事件队列为空时,即进行休眠。休眠时间由程序所配置的唤醒定时器决定,当然一些外部硬件中断也可以唤醒。如果需要使用不同的休眠等级,那也需要做一个休眠等级管理器,不同线程要求不同的休眠等级,然后由管理器决定休眠等级。当然这些细化配置会比较麻烦...

其实,事件驱动能干的,在RTOS中都能干,很多事情RTOS可以干的更好,更舒服。但是,事件驱动有一个最大的优点:省RAM,在很多低功耗MCU中,RAM一般比较小,RTOS虽然都能裁剪,但是每个任务所分配的堆栈不能裁剪,当任务一多,ram分配也挺烦心。而事件驱动归根到底还是裸奔,只是将线程(一个函数指针加一个事件状态)放在队列中进行管理,逐个调用而已。每个线程只花费十几个字节RAM。

这次所用的是Simon的事件驱动VSF平台,代码是放在github上的,github.com/versaloon/vsf,21ic也有一些介绍帖,有兴趣自己去看。

使用特权

评论回复
地板
DreamofOven|  楼主 | 2015-12-24 20:19 | 只看该作者
下面把示例代码献丑一下,非常非常粗糙的,帖子里的代码额外增加了中文说明
// 线程1
// 定义一个事件状态
#define EVENT_1_USER_LOCAL_SCANF                (VSFSM_EVT_USER_LOCAL + 1)
static struct vsfsm_state_t *
event_1_handler(struct vsfsm_t *sm, vsfsm_evt_t evt);
struct vsfsm_t event_1_sm =
{
        {event_1_handler}, // 初始化handler
};

使用特权

评论回复
5
DreamofOven|  楼主 | 2015-12-24 20:19 | 只看该作者
// 用于产生间隔为5秒的周期事件定时器
static struct vsftimer_timer_t event_1_timer =
{
        5000,        // 间隔为5秒
        &event_1_sm,        // 对应状态机
        EVENT_1_USER_LOCAL_SCANF, // 周期事件
};

struct vsfsm_state_t *
event_1_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
        switch (evt)
        {
        case VSFSM_EVT_INIT: // 初始化事件时,被默认执行
                vsftimer_register(&event_1_timer);
                break;
        case EVENT_1_USER_LOCAL_SCANF: // 周期事件处理
                Board_UARTPutSTR("event 1\r\n"); // 打印出“event 1”
                print_tick();                                        // 打印出当前系统tick
                break;
        default:
                break;
        }
      
        return NULL;
}

使用特权

评论回复
6
DreamofOven|  楼主 | 2015-12-24 20:20 | 只看该作者
// 线程2,将线程间隔改为3秒
#define EVENT_2_USER_LOCAL_SCANF                (VSFSM_EVT_USER_LOCAL + 1)
static struct vsfsm_state_t *
event_2_handler(struct vsfsm_t *sm, vsfsm_evt_t evt);
struct vsfsm_t event_2_sm =
{
        {event_2_handler},
};
static struct vsftimer_timer_t event_2_timer =
{
        3000,
        &event_2_sm,
        EVENT_2_USER_LOCAL_SCANF,
};

使用特权

评论回复
7
DreamofOven|  楼主 | 2015-12-24 20:21 | 只看该作者
struct vsfsm_state_t *
event_2_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
        switch (evt)
        {
        case VSFSM_EVT_INIT:
                vsftimer_register(&event_2_timer);
                break;
        case EVENT_2_USER_LOCAL_SCANF:
                Board_UARTPutSTR("event 2\r\n");
                print_tick();
                break;
        default:
                break;
        }
      
        return NULL;
}


使用特权

评论回复
8
DreamofOven|  楼主 | 2015-12-24 20:22 | 只看该作者
int main(void)
{
        // 串口初始化
        board_uart_init();
        // 使用utick中断唤醒
        board_utick_init();
      
        vsftimer_init();
      
        Board_UARTPutSTR("START!\r\n");
      
        vsfsm_init(&event_1_sm);
        vsfsm_init(&event_2_sm);

        vsf_leave_critical();
        while (1)
        {
                vsfsm_poll(); // 轮询状态机

                vsf_enter_critical();
                if (!vsfsm_get_event_pending()) // 判断是否有未处理事件
                {
                        vsf_leave_critical();
                        __WFI();
                }
                else
                {
                        vsf_leave_critical();
                }
        }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

178

帖子

0

粉丝