VSF的闪灯程序

[复制链接]
912|1
 楼主| vsf 发表于 2018-4-10 21:07 | 显示全部楼层 |阅读模式
VSF构架中,实现了多种任务的形式,这里以闪灯程序做一个示例。

1. 定时器回调:
  1. #include "vsf.h"
  2. #include "usrapp.h"

  3. struct usrapp_t usrapp;

  4. void usrapp_on_timer1S(void *param)
  5. {
  6.     struct usrapp_t *app = (struct usrapp_t *)param;
  7.     if (app->toggle)
  8.         vsfhal_gpio_set(0, 1 << 1);
  9.     else
  10.         vsfhal_gpio_clear(0, 1 << 1);
  11.     app->toggle = !app->toggle;
  12. }

  13. void usrapp_srt_init(struct usrapp_t *app)
  14. {
  15.     vsfhal_gpio_init(0);
  16.     vsfhal_gpio_config_pin(0, 1, GPIO_OUTPP);
  17.     usrapp_on_timer1S(app);
  18.     vsftimer_create_cb(1000, -1, usrapp_on_timer1S, app);
  19. }
这里,在软实时初始化代码里,调用vsftimer_create_cb建立一个定时器,每隔1000ms调用一次usrapp_on_timer1S。回调接口的方式,有一点需要处理,就是回调函数的运行时优先级,就是定时器模块的优先级。VSF中,很多模块都用到了回调函数,比如流模块等等。

2. 事件驱动构架:
  1. #include "vsf.h"
  2. #include "usrapp.h"

  3. struct vsfsm_state_t*
  4. usrapp_led_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt);
  5. struct usrapp_t usrapp =
  6. {
  7.     .sm.init_state.evt_handler      = usrapp_led_evt_handler,
  8.     .sm.user_data                   = &usrapp,
  9. };

  10. #define USRAPP_EVT_ON1S                 VSFSM_EVT_USER
  11. struct vsfsm_state_t*
  12. usrapp_led_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  13. {
  14.     struct usrapp_t *app = (struct usrapp_t *)sm->user_data;
  15.     switch (evt)
  16.     {
  17.     case VSFSM_EVT_INIT:
  18.         vsfhal_gpio_init(0);
  19.         vsfhal_gpio_config_pin(0, 1, GPIO_OUTPP);
  20.         vsftimer_create(sm, 1000, -1, USRAPP_EVT_ON1S);
  21.         // fall through
  22.     case USRAPP_EVT_ON1S:
  23.         if (app->toggle)
  24.             vsfhal_gpio_set(0, 1 << 1);
  25.         else
  26.             vsfhal_gpio_clear(0, 1 << 1);
  27.         app->toggle = !app->toggle;
  28.         break;
  29.     }
  30.     return NULL;
  31. }

  32. void usrapp_srt_init(struct usrapp_t *app)
  33. {
  34.     vsfsm_init(&app->sm);
  35. }
软实时初始化代码里,启动一个事件处理任务。事件处理任务里,处理初始化事件的时候,建立一个定时器,每隔1000ms发送USRAPP_EVT_ON1S事件给自己。事件驱动的方式,是最普通的VSF多任务实现方式。

3. 原状态机(msm):
  1. #include "vsf.h"
  2. #include "usrapp.h"

  3. enum
  4. {
  5.     STATE_INIT = 0,
  6.     STATE_ON,
  7.     STATE_OFF,
  8. };

  9. #define USRAPP_EVT_ON1S                 VSFSM_EVT_USER
  10. int usrapp_do_init(struct vsfsm_msm_t *msm);
  11. int usrapp_do_on(struct vsfsm_msm_t *msm);
  12. int usrapp_do_off(struct vsfsm_msm_t *msm);
  13. struct usrapp_t usrapp =
  14. {
  15.     .msm.entry_num              = dimof(usrapp.trans_tbl),
  16.     .msm.trans_tbl              = usrapp.trans_tbl,
  17.     .msm.user_data              = &usrapp,
  18.     .msm.state                  = STATE_INIT,

  19.     .trans_tbl[0]               = {STATE_INIT, VSFSM_EVT_INIT, NULL, usrapp_do_init},
  20.     .trans_tbl[1]               = {STATE_ON, USRAPP_EVT_ON1S, NULL, usrapp_do_off},
  21.     .trans_tbl[2]               = {STATE_OFF, USRAPP_EVT_ON1S, NULL, usrapp_do_on},
  22. };

  23. int usrapp_do_on(struct vsfsm_msm_t *msm)
  24. {
  25.     vsfhal_gpio_set(1, 1 << 1);
  26.     return STATE_ON;
  27. }
  28. int usrapp_do_off(struct vsfsm_msm_t *msm)
  29. {
  30.     vsfhal_gpio_clear(1, 1 << 1);
  31.     return STATE_OFF;
  32. }
  33. int usrapp_do_init(struct vsfsm_msm_t *msm)
  34. {
  35.     vsfhal_gpio_init(1);
  36.     vsfhal_gpio_config_pin(1, 1, GPIO_OUTPP);
  37.     vsftimer_create(msm->sm, 1000, -1, USRAPP_EVT_ON1S);
  38.     return usrapp_do_off(msm);
  39. }

  40. void usrapp_srt_init(struct usrapp_t *app)
  41. {
  42.     vsfsm_msm_init(&app->sm, &app->msm);
  43. }
元状态机以数据的方式,定义了状态机。这个在VSF的应用中,从来没用到,不过在一些应用中,会使用到元状态机,比如wifi的协议栈。

4. PT协程:
  1. #include "vsf.h"
  2. #include "usrapp.h"

  3. vsf_err_t usrapp_led_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt);
  4. struct usrapp_t usrapp =
  5. {
  6.     .pt.thread                      = usrapp_led_thread,
  7.     .pt.user_data                   = &usrapp,
  8. };

  9. #define USRAPP_EVT_ON1S                 VSFSM_EVT_USER
  10. vsf_err_t usrapp_led_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
  11. {
  12.     struct usrapp_t *app = (struct usrapp_t *)pt->user_data;

  13.     vsfsm_pt_begin(pt);
  14.     vsfhal_gpio_init(0);
  15.     vsfhal_gpio_config_pin(0, 1, GPIO_OUTPP);
  16.     vsftimer_create(pt->sm, 1000, -1, USRAPP_EVT_ON1S);
  17.     while (1)
  18.     {
  19.         if (app->toggle)
  20.             vsfhal_gpio_set(0, 1 << 1);
  21.         else
  22.             vsfhal_gpio_clear(0, 1 << 1);
  23.         app->toggle = !app->toggle;
  24.         vsfsm_pt_wfe(pt, USRAPP_EVT_ON1S);
  25.     }
  26.     vsfsm_pt_end(pt);
  27.     return VSFERR_NONE;
  28. }

  29. void usrapp_srt_init(struct usrapp_t *app)
  30. {
  31.     vsfsm_pt_init(&app->sm, &app->pt);
  32. }
PT协程就是使用状态机的方式,模拟普通阻塞的代码。在VSF构架中,一般避免使用,因为占用的ram和flash资源,相对其他方式更大。不过,在一些直接把阻塞代码,转换成VSF里可以运行的代码的时候,这个就会非常方便。

5. setjmp方式:
  1. #include "vsf.h"
  2. #include "usrapp.h"

  3. void usrapp_led_thread(struct vsfsm_ljmp_t *ljmp);
  4. struct usrapp_t usrapp =
  5. {
  6.     .ljmp.thread        = usrapp_led_thread,
  7.     .ljmp.user_data     = &usrapp,
  8.     .ljmp.stack         = usrapp.stack + sizeof(usrapp.stack),
  9. };

  10. #define USRAPP_EVT_ON1S                 VSFSM_EVT_USER
  11. void usrapp_led_thread(struct vsfsm_ljmp_t *ljmp)
  12. {
  13.     struct usrapp_t *app = (struct usrapp_t *)ljmp->user_data;

  14.     vsfhal_gpio_init(0);
  15.     vsfhal_gpio_config_pin(0, 1, GPIO_OUTPP);
  16.     vsftimer_create(ljmp->sm, 1000, -1, USRAPP_EVT_ON1S);

  17.     while (1)
  18.     {
  19.         if (app->toggle)
  20.             vsfhal_gpio_set(0, 1 << 1);
  21.         else
  22.             vsfhal_gpio_clear(0, 1 << 1);
  23.         app->toggle = !app->toggle;
  24.         vsfsm_ljmp_wfe(ljmp, USRAPP_EVT_ON1S);
  25.     }
  26. }

  27. void usrapp_srt_init(struct usrapp_t *app)
  28. {
  29.     vsfsm_ljmp_init(&app->sm, &app->ljmp);
  30. }
setjmp是标准的C库中的组件,一般用于实现类似try...exception...的功能,也可以用于实现一个独立堆栈的协程(PT协程是共享堆栈)。这个和PT比较的话,需要设置独立的堆栈,但是,没有PT协程重建堆栈的过程,性能会高很多。不过,在实际VSF的应用中,也没用到过这种方式。
vsf

27

主题

60

帖子

6

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