硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3300|回复: 3
收起左侧

[μCOS-II] 停机模式低功耗疑问

[复制链接]

6

主题

5

回帖

4

积分

新手上路

积分
4
发表于 2015-10-22 17:05:17 | 显示全部楼层 |阅读模式
版主,我看了你们V4板子停机模式低功耗的例子,你们是按键中断来唤醒的,跟我的情况有点不同,可否帮我解惑一下。
现在我的情况这样子:
我有2个任务:
task 1:
{
  while(1)
{
       做事情();
        delay();
}
}
task 2:
{
  while(1)
{
      串口有数据,打印();
        delay();
}
}
  不用低功耗的时候ucos进入空闲任务的时候   经过需要延迟的时间就会切换出去运行task1或者task2,然后继续进来。
  现在我就想进入空闲任务的时候进入停机模式,然后经过需要延时的时间就退出停机模式去去执行 task1或者task2,同时,串口中断也可以唤醒停机模式,从而去处理task1,。
这样子我改如何去实现呢?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106934
QQ
发表于 2015-10-23 00:03:51 | 显示全部楼层
使用停机模式有两个小问题:
1. 滴答定时器中断也可以唤醒停机模式。
2. 退出停机模式后需要重新初始化时钟。

由于uCOS不支持tickless模式,不像RTX系统,RTX系统这两个问题都可以很好的处理。RTX是用的停机模式,FreeRTOS的是用的休眠模式。

停机模式放在空闲任务的确稍有些麻烦。由于滴答定时器会唤醒停机模式,你需要找个别的定时器替代滴答定时器功能,比如RTC时钟等,RTX是用的RTX唤醒。
回复

使用道具 举报

6

主题

5

回帖

4

积分

新手上路

积分
4
 楼主| 发表于 2015-10-27 16:15:08 | 显示全部楼层
问题经过硬汉哥的知道已经解决,我说一下我的解决方案;
首先:
进入停机模式我是用RTC的闹钟唤醒,在停机模式下面,可以用RTC自动唤醒,手册的原话是:
低功耗模式下的自动唤醒(AWU)
RTC可以在不需要依赖外部中断的情况下唤醒低功耗模式下的微控制器(自动唤醒模式)。 RTC提
供一个可编程的时间基数,用于周期性从停止或待机模式下唤醒。通过对备份区域控制寄存器
(RCC_BDCR)的RTCSEL[1:0]位的编程,三个RTC时钟源中的二个时钟源可以选作实现此功
能。
● 低功耗32.768kHz外部晶振(LSE)
该时钟源提供了一个低功耗且精确的时间基准。 (在典型情形下消耗小于1μA)
● 低功耗内部RC振荡器(LSI RC)
使用该时钟源,节省了一个32.768kHz晶振的成本。但是RC振荡器将少许增加电源消耗。
为了用RTC闹钟事件将系统从停止模式下唤醒,必须进行如下操作:
● 配置外部中断线17为上升沿触发。
● 配置RTC使其可产生RTC闹钟事件。


这里配置的时候主要  ,配置外部中断线17为上升沿触发。


然后就说一下我的停机方案。
首先,计算出休眠的时间。休眠的时间也就是说ucos在空闲任务中的时间,即OS_IdleTask();这个怎么计算呢?一开始也是很纠结这个,一直没有找到比较好的办法,然后自己就仔细地去看源码。
发现,任务中使用delay 函数的时候,其实也就是给任务的控制块OS_TCB  中的TickCtrMatch  赋值,然后就切换任务出去。这个值是什么呢?你单步debug delay  函数 的时候,你会发现最终就是把需要的
延时tick  +当前的tick赋值给这个TickCtrMatch   ,例如:p_tcb->TickCtrMatch = OSTickCtr + time;       time就是需要延时的tick      在声明的时候也说明了这个变量的含义 OS_TICK   TickCtrMatch;    /* Absolute time when task is going to be ready           */
有了这个就好办了,当我们一切换到空闲任务的时候,首先获取当前的tick   OSTimeGet(&err);   然后在查表从TCB快链表中中找出最小 的TickCtrMatch   ,这个的任务就是我们从空闲任务延时后切换出去的任务,休眠时间:sleeptime=TickCtrMatch-OSTimeGet(&err);然后从休眠状态中退出来时候,因为时间已经过去,但是ucos的当前时间是没有变的,所以,我们需要重新设置一下ucos 的当前tick  OSTimeSet(SleepTick-1,&err);   这个SleepTick就是之前的那个TickCtrMatch,这时候休眠一出来,等下下一个滴答定时器到来的时候,它就会与延时最短的那个任务快想匹配,就会自动的实现任务的切换,可能表述得 不清楚。下面我分享一下我的代码。

void  App_OS_TaskSwHook (void)
{

    OS_ERR err;
    OS_TICK sleep;
    /* 如果之前运行的是空闲任务 */
    if(OSPrioCur == (OS_CFG_PRIO_MAX - 1u))   
    {
//        Sleep(0);
    }
              

    if(OS_PrioGetHighest()==(OS_CFG_PRIO_MAX - 1u))    //这里即将切换到空闲任务,用户任务已经都被挂起或者堵塞
    {
            
        if(GetDelayMinTickFormPrio())                  //由任务优先级得到需要的延时时间
        {
            sleep=GetDelayMinTickFormPrio()-OSTimeGet(&err);   //得到需要的延时时间
            StopMode_EnterStopMode(sleep);                     //停机模式   停机sleep哥tick   注意的是RTC的频率跟ucos的滴答时钟最好一致  不会你delay()  1s   但是实际上就不是  1S  或者是5S   0.1S
            OSTimeSet(SleepTick-1,&err);                       //经过停机之后跟新当前的tick  在停机的过程中MCU是 停止工作的
        }
    }
   
}

#define PRIONUMMAX      20

OS_TCB *TcbList[256];

static OS_TICK SleepTick;

u8 Prioindex=0;                     //索引

u8 Prionum[PRIONUMMAX];             //优先级

OS_TICK GetDelayMinTickFormPrio()   //由自己定义的一个TCB块来查找最小的延时时间   Tcb块的指针一定要跟实际的Tcb对应,不然就查找不到了
{
//    CPU_DATA  i;
//    OS_TICK   min;  
    u8 i=0;
//    for (i = 0u; i < OS_PRIO_TBL_SIZE; i++)
//    {
//       if(OSPrioTbl!=(CPU_DATA)0)
//        {
//            if(min>TcbList[(u8)i]->TickCtrMatch)
//            {
//                min=TcbList[(u8)i]->TickCtrMatch;
//                SleepTick=min;
//            }
//        }
//    }
    //获得最小delay  tick
    SleepTick=TcbList[Prionum]->TickCtrMatch;            
    for(i=0;i&ltrioindex;i++)
    {
        if(SleepTick>(TcbList[Prionum]->TickCtrMatch))
        {
            SleepTick=TcbList[Prionum]->TickCtrMatch;
//            SleepTick=min;
        }
    }
    return SleepTick;
}

void  App_OS_TaskCreateHook (OS_TCB  *p_tcb)    //在任务创建的时候初始化自己定义的任务块数组以及优先级,记录下来。不过也可以操作内核的表,由于自己测试,没有操作内核的表来查找
{
    (void)&p_tcb;
    TcbList[p_tcb-&gtrio]=p_tcb;
    Prionum[Prioindex]=p_tcb-&gtrio;
    Prioindex++;
}

谢谢大家,可能有些问题,希望大家指出。现在存在的问题是用这个RTC闹钟之后,RTC的时间改如何用,如果跟外部的串口中断唤醒结合呢?大家指教指教
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106934
QQ
发表于 2015-10-28 00:41:21 | 显示全部楼层

回 飞雪飘花 的帖子

飞雪飘花:问题经过硬汉哥的知道已经解决,我说一下我的解决方案;
首先:
进入停机模式我是用RTC的闹钟唤醒,在停机模式下面,可以用RTC自动唤醒,手册的原话是:
低功耗模式下的自动唤醒(AWU)
RTC可以在不需要依赖外部中断的情况下唤醒低功耗模式下的微控制器(自动唤醒模式)。 RTC提
..... .. (2015-10-27 16:15)
感谢分享![s:151]
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-10 16:47 , Processed in 0.158389 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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