RT-Thread怎么休眠实现低功耗。

发表在 PM2017-9-1 11:23 [复制链接] 11 3098

HI各位大神,我目前有一个案子是电池供电的,需要实现低功耗。4 A0 }. ~/ {5 y, b, E* Z
选用的主控芯片是EFM32LG系列的,有低功耗定时器,我想用一个嵌入式的操作系统,我对RT-Thread也不太了解,不知道RT-Thread有没有实现空闲时休眠,在定时任务时间到达时唤醒,还有外部中断可以打断休眠再进行正常的任务调度?
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2017-9-1 14:38:29 | 显示全部楼层

RT-Thread怎么休眠实现低功耗。

可以参考bsp里面nrf52832和samd21的实现方法。
使用道具 举报 回复
发表于 2017-9-1 15:23:12 | 显示全部楼层

RT-Thread怎么休眠实现低功耗。

可以参考bsp里面nrf52832和samd21的实现方法。
好的,我先研究一下。
使用道具 举报 回复
发表于 2017-9-4 14:17:58 | 显示全部楼层

RT-Thread怎么休眠实现低功耗。

可以参考bsp里面nrf52832和samd21的实现方法。
大神你好,我看了nrf52832的代码,在idle task的钩子函数里调用_sleep_ongo( uint32_t sleep_tick )实现休眠,唤醒之后用_wakeup_tick_adjust恢复系统tick,但是如果休眠中被外部中断唤醒该怎么处理,我没找到相应的代码。是不是说外部中断唤醒也是在这里处理了?
7 r8 j; n' z  ?- U" o; A: ]4 M* C还有一种情况,就是timer_list为空的情况下,rt_timer_next_timeout_tick返回了RT_TICK_MAX,更好的处理方式是让处理器deep sleep,等待外部中断的唤醒。感觉RTT针对低功耗这块还需要加入一些标准API去处理。
使用道具 举报 回复
发表于 2017-9-5 18:20:53 | 显示全部楼层

RT-Thread怎么休眠实现低功耗。

可以参考bsp里面nrf52832和samd21的实现方法。
大神,我参考了NRF52838的方法,做了尝试,结果遇到了和你去年一样的问题,% ]# p; a' `1 p1 e
( t4 e& f% s( ?! E3 V* |
http://www.rt-thread.org/phpBB3/post25105.html; O- G- q- d* C
- v% B" n, f  U5 P1 w$ j9 B
补偿了sleep得到一个很大的值,按照你的提示一想,确实没有补偿timer_list里面的每个remaining_tick,请问是怎么解决的?
使用道具 举报 回复
发表于 2017-9-6 11:39:00 | 显示全部楼层

RT-Thread怎么休眠实现低功耗。

结合NRF和FREERTOS的例子,现在已经可以休眠了,但是休眠好像影响了TICK的长度,rt_thread_delay()的延时在使能休眠的情况下明显长很多,不知何故,具体的原因还要查查。以下是我的代码,系统时钟和休眠时钟用的都是RTC:
  1. static void _wakeup_tick_adjust(uint32_t diff)
  2. {
  3.     uint32_t level;
  4.     level = rt_hw_interrupt_disable();
  5.     rt_tick_set(rt_tick_get() + diff);
  6.     if (rt_thread_self() != RT_NULL)
  7.     {
  8.             struct rt_thread *thread;
  9.         /* check time slice */
  10.         thread = rt_thread_self();
  11.         if (thread->remaining_tick <= diff)
  12.         {
  13.             /* change to initialized tick */
  14.             thread->remaining_tick = thread->init_tick;
  15.             /* yield */
  16.             rt_thread_yield();
  17.         }
  18.         else
  19.         {
  20.             thread->remaining_tick -= diff;
  21.         }
  22.         /* check timer */
  23.         rt_timer_check();
  24.     }
  25.     rt_hw_interrupt_enable(level);
  26. }
  27. static void _sleep_ongo( uint32_t idle_tick )
  28. {
  29.   unsigned long cnt_before_sleep, cnt_afer_sleep;
  30.   unsigned long rtc_load_value, gone_tick;
  31.   bool rtcFlag;
  32. //  CORE_DECLARE_IRQ_STATE;
  33.     /* Make sure the SysTick reload value does not overflow the counter. */
  34.     if ( idle_tick >  TIMER_CAPACITY / CNT_PER_ONT_TICK )
  35.     {
  36.         idle_tick = TIMER_CAPACITY / CNT_PER_ONT_TICK;
  37.     }
  38.   /* Calculate the reload value required to wait idle_tick
  39.    * tick periods. */
  40.   rtc_load_value = (CNT_PER_ONT_TICK * idle_tick)&0xfffffe;
  41.   if (rtc_load_value > timer_compensation) {
  42.     /* Compensate for the fact that the RTC is going to be stopped
  43.      * momentarily. */
  44.     rtc_load_value -= timer_compensation;
  45.   }
  46.   /* Stop the RTC momentarily.  The time the RTC is stopped for is accounted
  47.    * for as best it can be, but using the tickless mode will inevitably result
  48.    * in some tiny drift of the time maintained by the kernel with respect to
  49.    * calendar time.  The count is latched before stopping the timer as stopping
  50.    * the timer appears to clear the count. */
  51.   cnt_before_sleep = RTC_CounterGet();
  52.   RTC_Enable(false);
  53.   /* If this function is re-entered before one complete tick period then the
  54.    * reload value might be set to take into account a partial time slice. So
  55.    * we adjust the count before sleep to take this into account.
  56.    *
  57.    * Just reading the count would be wrong, as it assumes that we are
  58.    * counting up to a full ticks worth.
  59.    */
  60.   cnt_before_sleep += (CNT_PER_ONT_TICK - RTC_CompareGet(0));
  61.   /* Enter a critical section but don't use the taskENTER_CRITICAL()
  62.    * method as that will mask interrupts that should exit sleep mode. */
  63.   //CORE_ENTER_CRITICAL();
  64.     rt_enter_critical();
  65. #if 0
  66.   /* If a context switch is pending or a task is waiting for the scheduler
  67.    * to be unsuspended then abandon the low power entry. */
  68.   if (eTaskConfirmSleepModeStatus() == eAbortSleep) {
  69.     /* Restart tick and count up to whatever was left of the current time
  70.      * slice. */
  71.     RTC_CompareSet(0, (CNT_PER_ONT_TICK - cnt_before_sleep));
  72.     RTC_Enable(true);
  73.     /* Re-enable interrupts */
  74.     CORE_EXIT_CRITICAL();
  75.   } else
  76. #endif
  77.   {
  78.     /* Adjust the reload value to take into account that the current time
  79.      * slice is already partially complete. */
  80.     rtc_load_value -= cnt_before_sleep;
  81.     RTC_CompareSet(0, rtc_load_value);
  82.     RTC_IntClear(_RTC_IFC_MASK);
  83.     //RTC_IntEnable(RTC_IF_COMP0);
  84.     /* Restart the counter */
  85.     RTC_Enable(true);
  86.     /* Sleep until something happens. save cpu status before sleep,restore when wakeup*/
  87.     EMU_EnterEM2(RT_TRUE);
  88.     /* Stop the RTC and save the counter value since stopping the RTC clears
  89.      * the counter. Again, the time the SysTick is stopped for is
  90.      * accounted for as best it can be, but using the tickless mode will
  91.      * inevitably result in some tiny drift of the time maintained by the
  92.      * kernel with respect to calendar time. */
  93.     cnt_afer_sleep = RTC_CounterGet();
  94.     RTC_Enable(false);
  95.     rtcFlag = (RTC_IntGet() & RTC_IF_COMP0) != 0;
  96.     /* Re-enable interrupts */
  97.     //CORE_EXIT_CRITICAL();
  98.     if (rtcFlag) {
  99.       /* The tick interrupt handler will already have pended the tick
  100.        * processing in the kernel.  As the pending tick will be
  101.        * processed as soon as this function exits, the tick value
  102.        * maintained by the tick is stepped forward by one less than the
  103.        * time spent waiting. */
  104.       gone_tick = idle_tick - 1UL;
  105.     } else {
  106.       /* Some other interrupt than the RTC ended the sleep, now we need to
  107.        * calculate how much time has passed since the last tick. */
  108.       cnt_afer_sleep += cnt_before_sleep;
  109.       /* Calculate how many complete ticks have passed since the last tick */
  110.       gone_tick = cnt_afer_sleep / CNT_PER_ONT_TICK;
  111.       /* The reload value is set to whatever fraction of a single tick
  112.        * period remains. */
  113.       cnt_afer_sleep -= (gone_tick * CNT_PER_ONT_TICK);
  114.       rtc_load_value = CNT_PER_ONT_TICK - cnt_afer_sleep;
  115.       RTC_IntClear(_RTC_IFC_MASK);
  116.       
  117.       /* Reset the RTC compare value to trigger at the configured tick rate */
  118.       RTC_CompareSet(0, rtc_load_value);
  119.     }
  120.     /* Start the counter */
  121.     RTC_Enable(true);
  122.     /* The tick forward by the number of tick periods that
  123.      * remained in a low power state. */
  124.     _wakeup_tick_adjust(gone_tick);
  125.    
  126.     rt_exit_critical();
  127.   }
  128. }
  129. void rt_hw_system_powersave(void)
  130. {
  131.   uint32_t idle_tick;
  132.   
  133.   idle_tick = rt_timer_next_timeout_tick() - rt_tick_get();
  134.   
  135.   if ( idle_tick >= EXPECTED_IDLE_TIME_BEFORE_SLEEP)
  136.   {
  137.     // rt_kprintf("sleep entry:%u
  138. ", rt_tick_get());
  139.     _sleep_ongo( idle_tick );
  140.   }
  141. }
复制代码
使用道具 举报 回复
发表于 2018-1-10 15:42:10 | 显示全部楼层
问题解决了吗?我想是电池供电,用的STM32L4的,但不知道如何处理这低功耗问题。
使用道具 举报 回复
发表于 2018-1-10 16:10:43 | 显示全部楼层
慢慢来,咱们这个用的人还是没那么多,前途是光明的,道路是曲折的
使用道具 举报 回复
发表于 2018-1-10 19:19:25 来自手机 | 显示全部楼层
周末深圳沙龙有低功耗的主题,不知道是否有视频,有视频的话,可能会有更多的信息和帮助吧
使用道具 举报 回复
发表于 2018-1-13 10:48:07 | 显示全部楼层
belen 发表于 2018-1-10 15:42
$ \# N7 E$ L" O. M问题解决了吗?我想是电池供电,用的STM32L4的,但不知道如何处理这低功耗问题。 ...

; U+ `  H) c& K; ^! c0 K可以休眠,但是休眠后发现tick的时间变长了
使用道具 举报 回复
发表于 2018-1-22 10:09:36 | 显示全部楼层
希望官方能出一个低功耗的教程
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

Powered by RT-Thread

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