rt-thread低功耗休眠应用问题请教

发表在 PM2016-11-22 15:48 [复制链接] 8 3765

本屌目前使用MKL15Z128跑rt-thread系统,需要实现低功耗模式。: e" j% J1 c8 d( S! \3 N
当下简单的在idle线程中判断rt_timer_next_timeout_tick最快超时timer的tick数来休眠。
" ~  F) G1 T- D/ G2 w0 \由于此MCU自带lowpower timer,所以支持休眠计数唤醒功能。
% T& S2 d# B! [4 ]设计思想:
8 ?) j7 k/ z" |, \1.在idle线程中调用rt_timer_next_timeout_tick获取最快超时的tick,然后计算出能休眠的tick数。8 s+ g0 f1 ^- J" y; X/ v3 n
2.然后配置lowpower timer进入预定的休眠时间后唤醒MCU。
7 ]& Y9 y# Q& G5 p3.唤醒后重新配置MCU时钟
- P; R) v3 @6 t2 ?+ q: m. _' ~注意点:- r! X" c2 P2 A; W* i
1.由于mcu休眠器件无法进行OS TICK,所以需要唤醒后补偿OS TICK.
$ Z" m8 J/ T+ Y: y5 [* {  z3 E2.由于一旦唤醒后补偿OS TICK就会导致用户任务可能ready。) M& X' y: `4 m* i' h0 L& N6 G
3.任务一旦ready应该已经重新配置好时钟等寄存器内容。此时可以保证在任务前后时钟已经配置,可以先锁定调度器再休眠,配置好各项参数后再开锁。
- |* R; O+ v7 p0 E遇到的问题:
) w1 }1 r0 |1 @& |- M计算rt_timer_next_timeout_tick的tick会突然变得很大,想不通为什么。
! H% D5 @! Z% C9 |代码结构:
  1. #define RT_TICK_PER_SECOND        200
  2. rt_thread_idle_sethook(_system_sleep_entry);
  3. void rt_init_thread_entry(void* parameter)
  4. {
  5.     while (1)
  6.     {
  7.         rt_kprintf("init thread
  8. ");
  9.         rt_thread_delay(4 * RT_TICK_PER_SECOND);
  10.     }
  11. }
  12. static void _system_sleep_entry(void)
  13. {
  14.     rt_tick_t sleep_tick;
  15.     sleep_tick = rt_timer_next_timeout_tick() - rt_tick_get();
  16.     if (sleep_tick > RT_TICK_PER_SECOND)
  17.     {
  18.         rt_kprintf("sleep %u's entry
  19. ", sleep_tick);
  20.         /* Wait for debug console output finished. */
  21.         while (!(kLPSCI_TransmissionCompleteFlag & LPSCI_GetStatusFlags(UART0)))
  22.         {
  23.         }
  24.         
  25.         lptmr_int = 0;
  26.         LPTMR_SetTimerPeriod(LPTMR0, (sleep_tick * 5) - 1U);
  27.         LPTMR_StartTimer(LPTMR0);
  28.         LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
  29.         LLWU_EnableInternalModuleInterruptWakup(LLWU, 0, true);
  30.         NVIC_EnableIRQ(LLWU_IRQn);
  31.         rt_enter_critical();
  32.         SMC_PreEnterStopModes();
  33.         SMC_SetPowerModeVlps(SMC);
  34.         SMC_PostExitStopModes();
  35.         /* Power mode change. */
  36.         SMC_SetPowerModeRun(SMC);
  37.         while (kSMC_PowerStateRun != SMC_GetPowerModeState(SMC))
  38.         {
  39.         }
  40.          /* Wait for PLL lock. */
  41.         while (!(kMCG_Pll0LockFlag & CLOCK_GetStatusFlags()))
  42.         {
  43.         }
  44.         CLOCK_SetPeeMode();
  45.         rt_tick_get();
  46.         rt_tick_set(rt_tick_get() + sleep_tick);
  47.         rt_exit_critical();
  48.         rt_kprintf("sleep wakeup
  49. ");
  50.     }
  51. }
复制代码
  1.   | /
  2. - RT -     Thread Operating System
  3. / |      2.1.0 build Nov 16 2016
  4. 2006 - 2016 Copyright by rt-thread team
  5. init thread
  6. sleep 800's entry
  7. sleep wakeup
  8. sleep [color=#FF0040]4294967295[/color]'s entry
  9. init thread
  10. sleep wakeup
  11. sleep 800's entry
  12. sleep wakeup
  13. sleep 4294967295's entry
  14. init thread
  15. sleep wakeup
  16. sleep 800's entry
  17. sleep wakeup
  18. sleep 4294967295's entry
  19. init thread
  20. sleep wakeup
  21. sleep 800's entry
  22. sleep wakeup
  23. sleep 4294967295's entry
  24. init thread
  25. sleep wakeup
  26. sleep 800's entry
  27. sleep wakeup
  28. sleep 4294967295's entry
  29. init thread
  30. sleep wakeup
  31. sleep 800's entry
  32. sleep wakeup
  33. sleep 4294967295's entry
  34. init thread
  35. sleep wakeup
  36. sleep 800's entry
  37. sleep wakeup
  38. sleep 4294967295's entry
  39. init thread
  40. sleep wakeup
  41. sleep 800's entry
  42. sleep wakeup
  43. sleep 4294967295's entry
  44. init thread
  45. sleep wakeup
  46. sleep 800's entry
  47. sleep wakeup
  48. sleep 4294967295's entry
  49. init thread
复制代码
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2016-11-22 17:04:34 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

终于知道问题了,执行OS TICK补偿我是使用的rt_tick_set,这样虽然TICK计数器被更新了,但是没有触发时间片调度器,所以导致线程没有被及时的调度,从而出现rt_get_tick大于timer_timeout_tick的情况。
( l/ u& X, Z4 ^2 L0 F% g8 R现在解决办法是补偿TICK后,等待下一次OS TICK 中断来触发时间片调度,更好的办法还需要进一步研究。
使用道具 举报 回复
发表于 2016-11-22 17:09:38 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

学习了! 楼主V5!
使用道具 举报 回复
发表于 2016-11-22 17:10:39 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

关于OS tick补偿的办法,要达到产生N次调用rt_tick_increase的效果,如何实现更好?
使用道具 举报 回复
发表于 2016-11-22 17:13:18 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

对牛头哥的敬仰如同滔滔江水连绵不绝
使用道具 举报 回复
发表于 2016-11-22 17:14:38 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

目前仿照tick中断模拟N次调用。
  1.     rt_tick_set(rt_tick_get() + sleep_tick);
  2.     thread = rt_thread_self();
  3.     if (thread->remaining_tick <= sleep_tick)
  4.     {
  5.         /* change to initialized tick */
  6.         thread->remaining_tick = thread->init_tick;
  7.         /* yield */
  8.         rt_thread_yield();
  9.     }
  10.     else
  11.     {
  12.         thread->remaining_tick -= sleep_tick;
  13.     }
  14.     /* check timer */
  15.     rt_timer_check();
复制代码
使用道具 举报 回复
发表于 2016-11-23 21:42:37 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

本屌目前使用MKL15Z128跑rt-thread系统,需要实现低功耗模式。
% Z- t& \- {5 Q, @" D- @" i5 h当下简单的在idle线程中判断rt_timer_next_timeout_tick最快超时timer的tick数来休眠。
1 Q$ x' l9 i0 d+ N由于此MCU自带lowpower timer,所以支持休眠计数唤醒功能。
* D8 G% }: p8 {  M( N# P  g8 _设计思想:2 h; e7 q7 l7 q) Q
1.在idle线程中调用rt_timer_next_timeout_tick获取最快超时的tick,然后计算出能休眠的tick数。
8 I2 V9 U7 L! ^! D2.然后配置lowpower timer进入预定的休眠时间后唤醒MCU。7 B! M" W3 o1 L' h" [0 `. Z
3.唤醒后重新配置MCU时钟
- x4 L; Z2 e7 x注意点:
; x+ R: w7 q5 h7 s1 ~1.由于mcu休眠器件无法进行OS TICK,所以需要唤醒后补偿OS TICK.
* ^0 f" O8 |# N+ t6 g" Y2.由于一旦唤醒后补偿OS TICK就会导致用户任务可能ready。  X: P/ `8 F# O7 F4 E6 y
3.任务一旦ready应该已经重新配置好时钟等寄存器内容。此时可以保证在任务前后时钟已经配置,可以先锁定调度器再休眠,配置好各项参数后再开锁。3 N% @3 G6 W% t+ c/ v! ]9 R* ~
遇到的问题:3 |( r7 |6 L6 Q) n- ~) b' n  _. b1 h
计算rt_timer_next_timeout_tick的tick会突然变得很大,想不通为什么。
( Q0 E5 K0 K1 d& S% A# {; i4 L代码结构:
  1. #define RT_TICK_PER_SECOND        200
  2. rt_thread_idle_sethook(_system_sleep_entry);
  3. void rt_init_thread_entry(void* parameter)
  4. {
  5.     while (1)
  6.     {
  7.         rt_kprintf("init thread
  8. ");
  9.         rt_thread_delay(4 * RT_TICK_PER_SECOND);
  10.     }
  11. }
  12. static void _system_sleep_entry(void)
  13. {
  14.     rt_tick_t sleep_tick;
  15.     sleep_tick = rt_timer_next_timeout_tick() - rt_tick_get();
  16.     if (sleep_tick > RT_TICK_PER_SECOND)
  17.     {
  18.         rt_kprintf("sleep %u's entry
  19. ", sleep_tick);
  20.         /* Wait for debug console output finished. */
  21.         while (!(kLPSCI_TransmissionCompleteFlag & LPSCI_GetStatusFlags(UART0)))
  22.         {
  23.         }
  24.         
  25.         lptmr_int = 0;
  26.         LPTMR_SetTimerPeriod(LPTMR0, (sleep_tick * 5) - 1U);
  27.         LPTMR_StartTimer(LPTMR0);
  28.         LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
  29.         LLWU_EnableInternalModuleInterruptWakup(LLWU, 0, true);
  30.         NVIC_EnableIRQ(LLWU_IRQn);
  31.         rt_enter_critical();
  32.         SMC_PreEnterStopModes();
  33.         SMC_SetPowerModeVlps(SMC);
  34.         SMC_PostExitStopModes();
  35.         /* Power mode change. */
  36.         SMC_SetPowerModeRun(SMC);
  37.         while (kSMC_PowerStateRun != SMC_GetPowerModeState(SMC))
  38.         {
  39.         }
  40.          /* Wait for PLL lock. */
  41.         while (!(kMCG_Pll0LockFlag & CLOCK_GetStatusFlags()))
  42.         {
  43.         }
  44.         CLOCK_SetPeeMode();
  45.         rt_tick_get();
  46.         rt_tick_set(rt_tick_get() + sleep_tick);
  47.         rt_exit_critical();
  48.         rt_kprintf("sleep wakeup
  49. ");
  50.     }
  51. }
复制代码

# `& c! T% u' `8 W* b" j0 @牛头哥太牛了~ 另外,rt_enter_critical(); 是不是得用禁用中断?否则有中断唤醒其他线程后,最近超时时间发生变更的可能~
使用道具 举报 回复
发表于 2016-11-23 22:41:02 | 显示全部楼层

rt-thread低功耗休眠应用问题请教

[quote]本屌目前使用MKL15Z128跑rt-thread系统,需要实现低功耗模式。
% @% g9 |6 M! E) o6 d
, N# k+ p5 a/ p$ x2 R3 Y6 S  U; i牛头哥太牛了~ 另外,rt_enter_critical(); 是不是得用禁用中断?否则有中断唤醒其他线程后,最近超时时间发生变更的可能~
[/quote]7 `4 U$ S# g, h2 j* x

, B1 c6 S# K% w$ Z, G5 t已经考虑进去,任何唤醒源唤醒后最后都会进入MCU的wakeup中断,在wakeup中断里我做了lowpower的counter计算,再对OS TICK做补偿的。
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表