码迷,mamicode.com
首页 > 其他好文 > 详细

【LPC54100】在M0上跑事件驱动构架(一)

时间:2015-12-03 11:15:58      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:

@20150216

初次接触非对称双核MCU,由于之前好多知识不熟悉,这三天遇到不少问题。现在终于把事件驱动在M0核上跑起来了,就发一贴简单介绍下这个事件驱动构架和这几天的5410x芯片学习所得。
关于事件驱动架构,其主要用于低功耗设计,可以很方便的进入休眠模式。一般单片机裸奔都是轮询,如:

  1. void main()
  2. {
  3.     while(1)
  4.     {
  5.         tesk1();
  6.         tesk2();
  7.         tesk3();
  8.     }
  9. }

复制代码

在这种轮询处理中,很难判断在何时休眠,该休眠多长时间,又该使用什么等级的休眠。

而事件驱动的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.         }

复制代码

VSF在程序中增加了一个事件队列,当这个事件队列为空时,即进行休眠。休眠时间由程序所配置的唤醒定时器决定,当然一些外部硬件中断也可以唤醒。如果需要使用不同的休眠等级,那也需要做一个休眠等级管理器,不同线程要求不同的休眠等级,然后由管理器决定休眠等级。当然这些细化配置会比较麻烦…

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

这次所用的是Simon的事件驱动VSF平台,代码是放在github上的,github.com/versaloon/vsf,21ic也有一些介绍帖,有兴趣自己去看。
下面把示例代码献丑一下,非常非常粗糙的,帖子里的代码额外增加了中文说明

  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. };
  10. // 用于产生间隔为5秒的周期事件定时器
  11. static struct vsftimer_timer_t event_1_timer =
  12. {
  13.         5000,        // 间隔为5秒
  14.         &event_1_sm,        // 对应状态机
  15.         EVENT_1_USER_LOCAL_SCANF, // 周期事件
  16. };
  17. struct vsfsm_state_t *
  18. event_1_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  19. {
  20.         switch (evt)
  21.         {
  22.         case VSFSM_EVT_INIT: // 初始化事件时,被默认执行
  23.                 vsftimer_register(&event_1_timer);
  24.                 break;
  25.         case EVENT_1_USER_LOCAL_SCANF: // 周期事件处理
  26.                 Board_UARTPutSTR(“event 1rn”); // 打印出“event 1”
  27.                 print_tick();                                        // 打印出当前系统tick
  28.                 break;
  29.         default:
  30.                 break;
  31.         }
  32.         return NULL;
  33. }
  34. // 线程2,将线程间隔改为3秒
  35. #define EVENT_2_USER_LOCAL_SCANF                (VSFSM_EVT_USER_LOCAL + 1)
  36. static struct vsfsm_state_t *
  37. event_2_handler(struct vsfsm_t *sm, vsfsm_evt_t evt);
  38. struct vsfsm_t event_2_sm =
  39. {
  40.         {event_2_handler},
  41. };
  42. static struct vsftimer_timer_t event_2_timer =
  43. {
  44.         3000,
  45.         &event_2_sm,
  46.         EVENT_2_USER_LOCAL_SCANF,
  47. };
  48. struct vsfsm_state_t *
  49. event_2_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  50. {
  51.         switch (evt)
  52.         {
  53.         case VSFSM_EVT_INIT:
  54.                 vsftimer_register(&event_2_timer);
  55.                 break;
  56.         case EVENT_2_USER_LOCAL_SCANF:
  57.                 Board_UARTPutSTR(“event 2rn”);
  58.                 print_tick();
  59.                 break;
  60.         default:
  61.                 break;
  62.         }
  63.         return NULL;
  64. }
  65. int main(void)
  66. {
  67.         // 串口初始化
  68.         board_uart_init();
  69.         // 使用utick中断唤醒
  70.         board_utick_init();
  71.         vsftimer_init();
  72.         Board_UARTPutSTR(“START!rn”);
  73.         vsfsm_init(&event_1_sm);
  74.         vsfsm_init(&event_2_sm);
  75.         vsf_leave_critical();
  76.         while (1)
  77.         {
  78.                 vsfsm_poll(); // 轮询状态机
  79.                 vsf_enter_critical();
  80.                 if (!vsfsm_get_event_pending()) // 判断是否有未处理事件
  81.                 {
  82.                         vsf_leave_critical();
  83.                         __WFI();
  84.                 }
  85.                 else
  86.                 {
  87.                         vsf_leave_critical();
  88.                 }
  89.         }
  90. }

复制代码

串口输出: 

技术分享

PS: 现在的vsftimer并没有做休眠时间的动态管理,而是简单粗暴的定时唤醒一次,看看有没有事件需要处理。这个功能我会在后面完善。
Simon的架构中还有很多好玩的东西,有兴趣可以去研究下。

【LPC54100】在M0上跑事件驱动构架(一)

标签:

原文地址:http://www.cnblogs.com/leop/p/5015339.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!