搜索
bottom↓
回复: 8

外行问嵌入式OS低功耗问题

[复制链接]

出0入0汤圆

发表于 2014-3-20 20:45:55 | 显示全部楼层 |阅读模式
单片机有低功耗模式,比如HALT,或者STANDBY模式
如果移植了FREE RTOS,那么是不是这些模式就不能进入了呢?
或者说,低功耗模式如何与OS良好协作呢? 谢谢

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-3-20 21:02:33 | 显示全部楼层
使用RTOS了也可以进入低功耗模式,但是必须有一个定时器可以唤醒MCU。
你可以在IDLE任务中使用MCU进入STANDY模式,但是需要处理一个时钟节拍,
如你进入睡眠的时间就是RTOS中延时列表中时间最长的那个,另外如果睡眠过程
中有其它的事件唤醒MCU,此时你还需要处理RTOS时钟节拍!

出0入0汤圆

发表于 2014-3-20 21:08:04 | 显示全部楼层
2楼厉害,学习了。个人觉得处理起来还是有些难度的。

出0入0汤圆

发表于 2014-3-20 21:09:01 | 显示全部楼层
2楼正解

出0入0汤圆

发表于 2014-3-20 22:07:52 | 显示全部楼层
2楼正解。

出0入0汤圆

发表于 2014-3-21 08:28:14 | 显示全部楼层
看下freertos 官方有相关文献

低功耗方面 有说怎么做的

出0入0汤圆

发表于 2014-3-21 09:09:08 | 显示全部楼层
FreeRTOS就支持低功耗模式,不能说是完美支持,还是非常不错的,RTOS中的低功耗常用的方法叫tickless模式。

去年号称超低功耗的EMF32, 公司是Energy Micro ,专门给RTX做的超低功耗绝对不是盖的,有机会可以研究研究,
不过源码没找到。

出0入0汤圆

发表于 2014-3-21 09:14:41 | 显示全部楼层
FreeRTOS的tickless模式在文件port.C里面,内容如下,看下大概的注释就懂是什么意思了。
  1. #if configUSE_TICKLESS_IDLE == 1

  2.         __weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
  3.         {
  4.         uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
  5.         TickType_t xModifiableIdleTime;

  6.                 /* Make sure the SysTick reload value does not overflow the counter. */
  7.                 if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
  8.                 {
  9.                         xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
  10.                 }

  11.                 /* Stop the SysTick momentarily.  The time the SysTick is stopped for
  12.                 is accounted for as best it can be, but using the tickless mode will
  13.                 inevitably result in some tiny drift of the time maintained by the
  14.                 kernel with respect to calendar time. */
  15.                 portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;

  16.                 /* Calculate the reload value required to wait xExpectedIdleTime
  17.                 tick periods.  -1 is used because this code will execute part way
  18.                 through one of the tick periods. */
  19.                 ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
  20.                 if( ulReloadValue > ulStoppedTimerCompensation )
  21.                 {
  22.                         ulReloadValue -= ulStoppedTimerCompensation;
  23.                 }

  24.                 /* Enter a critical section but don't use the taskENTER_CRITICAL()
  25.                 method as that will mask interrupts that should exit sleep mode. */
  26.                 __disable_irq();

  27.                 /* If a context switch is pending or a task is waiting for the scheduler
  28.                 to be unsuspended then abandon the low power entry. */
  29.                 if( eTaskConfirmSleepModeStatus() == eAbortSleep )
  30.                 {
  31.                         /* Restart from whatever is left in the count register to complete
  32.                         this tick period. */
  33.                         portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;

  34.                         /* Restart SysTick. */
  35.                         portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;

  36.                         /* Reset the reload register to the value required for normal tick
  37.                         periods. */
  38.                         portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;

  39.                         /* Re-enable interrupts - see comments above __disable_irq() call
  40.                         above. */
  41.                         __enable_irq();
  42.                 }
  43.                 else
  44.                 {
  45.                         /* Set the new reload value. */
  46.                         portNVIC_SYSTICK_LOAD_REG = ulReloadValue;

  47.                         /* Clear the SysTick count flag and set the count value back to
  48.                         zero. */
  49.                         portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;

  50.                         /* Restart SysTick. */
  51.                         portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;

  52.                         /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
  53.                         set its parameter to 0 to indicate that its implementation contains
  54.                         its own wait for interrupt or wait for event instruction, and so wfi
  55.                         should not be executed again.  However, the original expected idle
  56.                         time variable must remain unmodified, so a copy is taken. */
  57.                         xModifiableIdleTime = xExpectedIdleTime;
  58.                         configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
  59.                         if( xModifiableIdleTime > 0 )
  60.                         {
  61.                                 __dsb( portSY_FULL_READ_WRITE );
  62.                                 __wfi();
  63.                                 __isb( portSY_FULL_READ_WRITE );
  64.                         }
  65.                         configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

  66.                         /* Stop SysTick.  Again, the time the SysTick is stopped for is
  67.                         accounted for as best it can be, but using the tickless mode will
  68.                         inevitably result in some tiny drift of the time maintained by the
  69.                         kernel with respect to calendar time. */
  70.                         ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
  71.                         portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );

  72.                         /* Re-enable interrupts - see comments above __disable_irq() call
  73.                         above. */
  74.                         __enable_irq();

  75.                         if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
  76.                         {
  77.                                 uint32_t ulCalculatedLoadValue;

  78.                                 /* The tick interrupt has already executed, and the SysTick
  79.                                 count reloaded with ulReloadValue.  Reset the
  80.                                 portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
  81.                                 period. */
  82.                                 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );

  83.                                 /* Don't allow a tiny value, or values that have somehow
  84.                                 underflowed because the post sleep hook did something
  85.                                 that took too long. */
  86.                                 if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
  87.                                 {
  88.                                         ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
  89.                                 }

  90.                                 portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;

  91.                                 /* The tick interrupt handler will already have pended the tick
  92.                                 processing in the kernel.  As the pending tick will be
  93.                                 processed as soon as this function exits, the tick value
  94.                                 maintained by the tick is stepped forward by one less than the
  95.                                 time spent waiting. */
  96.                                 ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
  97.                         }
  98.                         else
  99.                         {
  100.                                 /* Something other than the tick interrupt ended the sleep.
  101.                                 Work out how long the sleep lasted rounded to complete tick
  102.                                 periods (not the ulReload value which accounted for part
  103.                                 ticks). */
  104.                                 ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;

  105.                                 /* How many complete tick periods passed while the processor
  106.                                 was waiting? */
  107.                                 ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;

  108.                                 /* The reload value is set to whatever fraction of a single tick
  109.                                 period remains. */
  110.                                 portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
  111.                         }

  112.                         /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
  113.                         again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
  114.                         value.  The critical section is used to ensure the tick interrupt
  115.                         can only execute once in the case that the reload register is near
  116.                         zero. */
  117.                         portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
  118.                         portENTER_CRITICAL();
  119.                         {
  120.                                 portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
  121.                                 vTaskStepTick( ulCompleteTickPeriods );
  122.                                 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
  123.                         }
  124.                         portEXIT_CRITICAL();
  125.                 }
  126.         }

  127. #endif /* #if configUSE_TICKLESS_IDLE */
复制代码

出0入0汤圆

 楼主| 发表于 2014-3-21 17:57:39 | 显示全部楼层
非常感谢楼上各位的回复, 既然肯定是能实现,那我就不担心了。 谢谢各位!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 07:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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