[资料分享与下载] 在M0上跑事件驱动构架

[复制链接]
1274|7
 楼主| DreamofOven 发表于 2015-12-24 20:16 | 显示全部楼层 |阅读模式
初次接触非对称双核MCU,由于之前好多知识不熟悉,这三天遇到不少问题。现在终于把事件驱动在M0核上跑起来了,就发一贴简单介绍下这个事件驱动构架和这几天的5410x芯片学习所得。
关于事件驱动架构,其主要用于低功耗设计,可以很方便的进入休眠模式。一般单片机裸奔都是轮询,如:
  1. void main()
  2. {
  3.     while(1)
  4.     {
  5.         tesk1();
  6.         tesk2();
  7.         tesk3();
  8.     }
  9. }


 楼主| DreamofOven 发表于 2015-12-24 20:18 | 显示全部楼层
在这种轮询处理中,很难判断在何时休眠,该休眠多长时间,又该使用什么等级的休眠。

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

  4.                 vsf_enter_critical();
  5.                 if (!vsfsm_get_event_pending())
  6.                 {
  7.                         vsf_leave_critical();
  8.                         __WFI();
  9.                 }
  10.                 else
  11.                 {
  12.                         vsf_leave_critical();
  13.                 }
  14.         }
 楼主| 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. // 线程1
  2. // 定义一个事件状态
  3. #define EVENT_1_USER_LOCAL_SCANF                (VSFSM_EVT_USER_LOCAL + 1)
  4. static struct vsfsm_state_t *
  5. event_1_handler(struct vsfsm_t *sm, vsfsm_evt_t evt);
  6. struct vsfsm_t event_1_sm =
  7. {
  8.         {event_1_handler}, // 初始化handler
  9. };
 楼主| DreamofOven 发表于 2015-12-24 20:19 | 显示全部楼层
  1. // 用于产生间隔为5秒的周期事件定时器
  2. static struct vsftimer_timer_t event_1_timer =
  3. {
  4.         5000,        // 间隔为5秒
  5.         &event_1_sm,        // 对应状态机
  6.         EVENT_1_USER_LOCAL_SCANF, // 周期事件
  7. };

  8. struct vsfsm_state_t *
  9. event_1_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  10. {
  11.         switch (evt)
  12.         {
  13.         case VSFSM_EVT_INIT: // 初始化事件时,被默认执行
  14.                 vsftimer_register(&event_1_timer);
  15.                 break;
  16.         case EVENT_1_USER_LOCAL_SCANF: // 周期事件处理
  17.                 Board_UARTPutSTR("event 1\r\n"); // 打印出“event 1”
  18.                 print_tick();                                        // 打印出当前系统tick
  19.                 break;
  20.         default:
  21.                 break;
  22.         }
  23.       
  24.         return NULL;
  25. }

 楼主| DreamofOven 发表于 2015-12-24 20:20 | 显示全部楼层
  1. // 线程2,将线程间隔改为3秒
  2. #define EVENT_2_USER_LOCAL_SCANF                (VSFSM_EVT_USER_LOCAL + 1)
  3. static struct vsfsm_state_t *
  4. event_2_handler(struct vsfsm_t *sm, vsfsm_evt_t evt);
  5. struct vsfsm_t event_2_sm =
  6. {
  7.         {event_2_handler},
  8. };
  9. static struct vsftimer_timer_t event_2_timer =
  10. {
  11.         3000,
  12.         &event_2_sm,
  13.         EVENT_2_USER_LOCAL_SCANF,
  14. };
 楼主| DreamofOven 发表于 2015-12-24 20:21 | 显示全部楼层
  1. struct vsfsm_state_t *
  2. event_2_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  3. {
  4.         switch (evt)
  5.         {
  6.         case VSFSM_EVT_INIT:
  7.                 vsftimer_register(&event_2_timer);
  8.                 break;
  9.         case EVENT_2_USER_LOCAL_SCANF:
  10.                 Board_UARTPutSTR("event 2\r\n");
  11.                 print_tick();
  12.                 break;
  13.         default:
  14.                 break;
  15.         }
  16.       
  17.         return NULL;
  18. }


 楼主| DreamofOven 发表于 2015-12-24 20:22 | 显示全部楼层
  1. int main(void)
  2. {
  3.         // 串口初始化
  4.         board_uart_init();
  5.         // 使用utick中断唤醒
  6.         board_utick_init();
  7.       
  8.         vsftimer_init();
  9.       
  10.         Board_UARTPutSTR("START!\r\n");
  11.       
  12.         vsfsm_init(&event_1_sm);
  13.         vsfsm_init(&event_2_sm);

  14.         vsf_leave_critical();
  15.         while (1)
  16.         {
  17.                 vsfsm_poll(); // 轮询状态机

  18.                 vsf_enter_critical();
  19.                 if (!vsfsm_get_event_pending()) // 判断是否有未处理事件
  20.                 {
  21.                         vsf_leave_critical();
  22.                         __WFI();
  23.                 }
  24.                 else
  25.                 {
  26.                         vsf_leave_critical();
  27.                 }
  28.         }
  29. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

178

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部