4075|3

750

帖子

3

TA的资源

版主

楼主
 

【LPC54100】事件驱动之动态休眠管理(二) [复制链接]

在之前的例子中,软件定时器的驱动源来自于周期固定为1mS的硬件中断。在中断中,回调软件定时器的驱动函数,产生一个软件定时器的"VSFSM_EVT_TIMER"事件,然后退出中断。事件驱动会调用轮询软件定时器的handler,执行"VSFSM_EVT_TIMER"事件,如下:

  1. // vsftimer_callback_int is called in interrupt,
  2. // simply send event to vsftimer SM
  3. void vsftimer_callback_int(void)
  4. {
  5.         vsfsm_post_evt_pending(&vsftimer.sm, VSFSM_EVT_TIMER);
  6. }

  7. static struct vsfsm_state_t *
  8. vsftimer_init_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  9. {
  10.         switch (evt)
  11.         {
  12.         case VSFSM_EVT_TIMER:
  13.         {
  14.                 uint32_t cur_tickcnt = core_interfaces.tickclk.get_count();
  15.                 struct vsftimer_timer_t timer, *ptimer = vsftimer.timerlist;
  16.                
  17.                 while (ptimer != NULL)
  18.                 {
  19.                         // save timer on stack in case event handler of the state machine
  20.                         // unregister and free the timer, beause timer on stack maintain
  21.                         // the list pointing to the next timer
  22.                         timer = *ptimer;
  23.                         if ((cur_tickcnt - timer.start_tickcnt) >= timer.interval)
  24.                         {
  25.                                 // triggered
  26.                                 ptimer->start_tickcnt = cur_tickcnt;
  27.                                 if ((timer.sm != NULL) && (timer.evt != VSFSM_EVT_INVALID))
  28.                                 {
  29.                                         vsfsm_post_evt(timer.sm, timer.evt);
  30.                                 }
  31.                         }
  32.                         ptimer = sllist_get_container(timer.list.next,
  33.                                                                                         struct vsftimer_timer_t, list);
  34.                 }
  35.                 return NULL;
  36.         }
  37.         default:
  38.                 return NULL;
  39.         }
  40. }
复制代码
在"case VSFSM_EVT_TIMER"中,会遍历vsftimer.timerlist列表中所有timer,比较它们是否超时,如果超时,便会产生该定时器期望的超时事件。




为了实现动态休眠,确保每次唤醒都是有效唤醒,需要在执行__wfi()前,找到定时器列表中会最快发生的超时定时器并获得其触发超时所需的时间,然后将该时间设置为硬件定时器触发时间即可。一个简单的处理方法是将软件定时器根据触发时间排序,代码如下:

定时器的插入处理:

  1. static void insert_timer(struct vsftimer_timer_t *timer)
  2. {
  3.         struct vsftimer_timer_t *ptimer, *ntimer;

  4.         sllist_init_node(timer->list);

  5.         if (NULL == vsftimer.timerlist)
  6.         {
  7.                 vsftimer.timerlist = timer;
  8.                 return;
  9.         }

  10.         if (vsftimer.timerlist->trigger_tick > timer->trigger_tick)
  11.         {
  12.                 sllist_insert(timer->list, vsftimer.timerlist->list);
  13.                 vsftimer.timerlist = timer;
  14.                 return;
  15.         }

  16.         ptimer = vsftimer.timerlist;
  17.         ntimer = sllist_get_container(ptimer->list.next, struct vsftimer_timer_t,
  18.                                                                         list);
  19.         while (ntimer != NULL)
  20.         {
  21.                 if (ntimer->trigger_tick > timer->trigger_tick)
  22.                 {
  23.                         break;
  24.                 }
  25.                 ptimer = ntimer;
  26.                 ntimer = sllist_get_container(ptimer->list.next,
  27.                                                                                 struct vsftimer_timer_t, list);
  28.         }

  29.         if (ntimer != NULL)
  30.         {
  31.                 sllist_insert(timer->list, ntimer->list);
  32.         }
  33.         sllist_insert(ptimer->list, timer->list);
  34. }
复制代码

"VSFSM_EVT_TIMER"事件的处理:

  1. static struct vsfsm_state_t *
  2. vsftimer_init_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  3. {
  4.         switch (evt)
  5.         {
  6.         case VSFSM_EVT_TIMER:
  7.         {
  8.                 uint32_t cur_tick = get_system_tick();
  9.                 struct vsftimer_timer_t *timer = vsftimer.timerlist;

  10.                 while (timer != NULL)
  11.                 {
  12.                         if (cur_tick >= timer->trigger_tick)
  13.                         {
  14.                                 // triggered
  15.                                 timer->trigger_tick += timer->interval;
  16.                                 vsftimer_unregister(timer);
  17.                                 if (timer->trigger_cnt > 0)
  18.                                 {
  19.                                         timer->trigger_cnt--;
  20.                                 }
  21.                                 if (timer->trigger_cnt != 0)
  22.                                 {
  23.                                         insert_timer(timer);
  24.                                 }
  25. #if VSFSM_CFG_DELAY_EN
  26.                                 else
  27.                                 {
  28.                                         timer->malloced = 0;
  29.                                 }
  30. #endif
  31.                                 if ((timer->sm != NULL) && (timer->evt != VSFSM_EVT_INVALID))
  32.                                 {
  33.                                         vsfsm_post_evt(timer->sm, timer->evt);
  34.                                 }
  35.                                 timer = vsftimer.timerlist;
  36.                                 continue;
  37.                         }
  38.                         else
  39.                         {
  40.                                 break;
  41.                         }
  42.                 }
  43.                 return NULL;
  44.         }
  45.         default:
  46.                 return NULL;
  47.         }
  48. }
复制代码



硬件中断,及硬件定时器间隔设置函数:
  1. static uint32_t system_tick = 0;
  2. uint32_t get_system_tick(void)
  3. {
  4.         return system_tick;
  5. }
  6. void CT32B0_IRQHandler(void)
  7. {
  8.         if (Chip_TIMER_MatchPending(LPC_TIMER0, 1))
  9.         {
  10.                 Chip_TIMER_ClearMatch(LPC_TIMER0, 1);
  11.                 system_tick += LPC_TIMER0->MR[1] / (Chip_Clock_GetAsyncSyscon_ClockRate() / 1000);
  12.                 Chip_TIMER_SetMatch(LPC_TIMER0, 1, (Chip_Clock_GetAsyncSyscon_ClockRate() / 1000));
  13.                 vsftimer_callback_int();
  14.         }
  15. }
  16. void wfi_handle(void)
  17. {
  18.         __WFI();
  19. }
  20. void timer0_set_interval(uint32_t ms)
  21. {
  22.         uint32_t temp = LPC_TIMER0->MR[1] / (Chip_Clock_GetAsyncSyscon_ClockRate() / 1000);
  23.         if (ms > temp)
  24.         {
  25.                 Chip_TIMER_Disable(LPC_TIMER0);
  26.                 Chip_TIMER_SetMatch(LPC_TIMER0, 1, ((Chip_Clock_GetAsyncSyscon_ClockRate() / 1000) * ms));
  27.                 Chip_TIMER_Enable(LPC_TIMER0);
  28.         }
  29. }
复制代码


执行__wfi前,休眠时间的计算:
  1. vsf_err_t vsftimer_wfi(void)
  2. {
  3.         if ((vsftimer_wakeup_interval_set_handle == NULL) ||
  4.                 (vsftimer_wfi_handle == NULL))
  5.         {
  6.                 return VSFERR_FAIL;
  7.         }

  8.         if(vsftimer.timerlist == NULL)
  9.         {
  10.                 (*vsftimer_wakeup_interval_set_handle)(0xffff);
  11.         }
  12.         else
  13.         {
  14.                 uint32_t cur_tick = get_system_tick();
  15.                 if (vsftimer.timerlist->trigger_tick > cur_tick)
  16.                 {
  17.                         (*vsftimer_wakeup_interval_set_handle)(vsftimer.timerlist->trigger_tick - cur_tick);
  18.                 }
  19.                 else
  20.                 {
  21.                         return VSFERR_NOT_READY;
  22.                 }
  23.         }
  24.         (*vsftimer_wfi_handle)();
  25.         return VSFERR_NONE;
  26. }
复制代码


最后,无图无真相,看看效果吧。

上电后20s的功耗曲线:

最终曲线静态图:

对比下串口输出,是不是一致的呢?

  1. START!
  2. event 2
  3. Cur Tick is:     3000ms
  4. event 1
  5. Cur Tick is:     5000ms
  6. event 2
  7. Cur Tick is:     6000ms
  8. event 2
  9. Cur Tick is:     9000ms
  10. event 1
  11. Cur Tick is:    10000ms
  12. event 2
  13. Cur Tick is:    12000ms
  14. event 1
  15. Cur Tick is:    15000ms
  16. event 2
  17. Cur Tick is:    15002ms
  18. event 2
  19. Cur Tick is:    18000ms
复制代码


此帖出自NXP MCU论坛

最新回复

查功耗的是用什么工具测的?  详情 回复 发表于 2015-3-22 20:44
点赞 关注(1)
个人签名

要666

 

回复
举报

954

帖子

0

TA的资源

纯净的硅(初级)

沙发
 
楼主说的很有道理,学习了
此帖出自NXP MCU论坛
 
 
 

回复

190

帖子

10

TA的资源

一粒金砂(中级)

板凳
 
查功耗的是用什么工具测的?
此帖出自NXP MCU论坛

点评

看我之前发的帖子  详情 回复 发表于 2015-3-23 10:54
 
 
 

回复

750

帖子

3

TA的资源

版主

4
 
dvd1478 发表于 2015-3-22 20:44
查功耗的是用什么工具测的?


看我之前发的帖子

此帖出自NXP MCU论坛
 
个人签名

要666

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表