硬汉嵌入式论坛

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

[FreeRTOS] Tickless停机模式疑问

[复制链接]

10

主题

140

回帖

170

积分

初级会员

积分
170
发表于 2016-10-25 14:17:14 | 显示全部楼层 |阅读模式
以下是教程的例子:
#define configPRE_SLEEP_PROCESSING(x)  OS_PreSleepProcessing(x)
#define configPOST_SLEEP_PROCESSING(x) OS_PostSleepProcessing(x)

void OS_PreSleepProcessing(uint32_t vParameters)
{
    (void)vParameters;

    /* 用户可以考虑在此处加入关闭外设时钟来进一步降低功耗 */
    vParameters = 0;
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}

void OS_PostSleepProcessing(uint32_t vParameters)
{
    /* 如果前面关闭了外设时钟,需要在这里恢复 */
    /*
      1、当一个中断或唤醒事件导致退出停止模式时,HSI RC振荡器被选为系统时钟。
      2、退出低功耗的停机模式后,需要重新配置使用HSE。        
    */
    RCC_HSEConfig(RCC_HSE_ON);
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET){}

    RCC_PLLCmd(ENABLE);
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    while (RCC_GetSYSCLKSource() != 0x08){}
}

以下为port.c中的代码:

xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 )
{
    __dsb( portSY_FULL_READ_WRITE );
    __wfi();
    __isb( portSY_FULL_READ_WRITE );
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

个人认为代码的意思应当是修改 xModifiableIdleTime 为 0,然后再判断是否大于0才会执行下面的__wfi()代码。
但 xModifiableIdleTime 以这种方式传入之后根本没有办法修改为0,它的值始终和xExpectedIdleTime一样。这样下面的__wfi()永远都会被执行到。

难道代码不应该如下这样调用吗?
configPRE_SLEEP_PROCESSING( &xModifiableIdleTime );


void OS_PreSleepProcessing(uint32_t *vParameters)
{
    (void)vParameters;

    /* 用户可以考虑在此处加入关闭外设时钟来进一步降低功耗 */
    *vParameters = 0;
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}
或者这样:
#define configPRE_SLEEP_PROCESSING(x)   do{OS_PreSleepProcessing(x); x=0;}while(0)

void OS_PreSleepProcessing(uint32_t vParameters)
{
    (void)vParameters;
    /* 用户可以考虑在此处加入关闭外设时钟来进一步降低功耗 */
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}
感觉教程讲的不是很清楚,FreeRTOS官网的资料和教程差不多。不知道我这样理解对不对,还望答复,十分感谢!

另:
1、为什么用PWR_STOPEntry_WFE,而不是PWR_STOPEntry_WFI
2、如何退出停机模式?使用外部中断?

只找到以下文章,由于没有账号,无法看全,感觉他也没有最终实现。
http://www.amobbs.com/thread-5633496-1-1.html
回复

使用道具 举报

10

主题

140

回帖

170

积分

初级会员

积分
170
 楼主| 发表于 2016-10-26 16:34:18 | 显示全部楼层
[s:126]
回复

使用道具 举报

1

主题

6

回帖

1

积分

新手上路

积分
1
发表于 2016-10-26 21:32:55 | 显示全部楼层

回 lvehe 的帖子

lvehe:[s:126]  (2016-10-26 16:34) 
正好没事,研究了下你说的问题,先假设教程没有错误(应该也不会出错的。。),说下我的理解。。

------------
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );  // 代码执行到这里,调用下面函数

void OS_PreSleepProcessing(uint32_t vParameters)
{
    (void)vParameters;

    /* 用户可以考虑在此处加入关闭外设时钟来进一步降低功耗 */
    vParameters = 0;
    // 调用该函数后,系统即正式进入停机模式
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}
------------
// 某个事件或中断导致系统被唤醒,即退出停机模式,那么系统应该从进入停机模式的地方继续执行,也就是如下代码。 xModifiableIdleTime 表示在停机之前的空闲时间,这个判断分支执行的代码意思是指在进入停机模式之前,该任务还有剩余时间,即>0,那么就做一次内存和CPU同步,并等待中断唤醒。。 从这个意义上看,xExpectedIdleTime这个值是不能被修改的。。
if( xModifiableIdleTime > 0 )
{
    __dsb( portSY_FULL_READ_WRITE );    // 数据同步,刷新缓存,保持内存一致性
    __wfi();                // 使CPU进入idle状态,等待中断时间唤醒                                                         
    __isb( portSY_FULL_READ_WRITE );  // 指令同步, 这三条语句的实际执行意义还不确定
}

关于wfi与wfe的区别,搜了下,可以看看这。。http://www.wowotech.net/armv8a_arch/wfe_wfi.html

=============
以上,仅供参考。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-15 13:29 , Processed in 0.238966 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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