@[toc]

低功耗无法进入的问题分析

现象

  • 低功耗进入与退出前后加入打印函数.发现进入低功耗后立刻退出低功耗
  • 打印代码如下
1
2
3
4
log_i("in\r\n");
UTIL_PowerDriver.EnterStopMode( );
UTIL_PowerDriver.ExitStopMode( );
log_i("out\r\n");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pc9oa0Kw-1684999984302)(%E4%BD%8E%E5%8A%9F%E8%80%97%E6%97%A0%E6%B3%95%E7%94%9F%E6%95%88%E7%9A%84%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90.assets/image-20230524190036152.png)]

原因

  • 中断标志位挂起未清除导致低功耗进入失败

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtKg17eY-1684999984303)(%E4%BD%8E%E5%8A%9F%E8%80%97%E6%97%A0%E6%B3%95%E7%94%9F%E6%95%88%E7%9A%84%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90.assets/image-20230524190759299.png)]

分析

挂起的中断标志位查找

  • 完整的进退低功耗函数如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define UTIL_LPM_ENTER_CRITICAL_SECTION_ELP() 扩展到:
uint32_t primask_bit= __get_PRIMASK(); __disable_irq()


#define UTIL_LPM_EXIT_CRITICAL_SECTION_ELP() 扩展到:
__set_PRIMASK(primask_bit)

void UTIL_LPM_EnterLowPower( void )
{
UTIL_LPM_ENTER_CRITICAL_SECTION_ELP( );

if( StopModeDisable != UTIL_LPM_NO_BIT_SET )
{
/**
* At least one user disallows Stop Mode
* SLEEP mode is required
*/
UTIL_PowerDriver.EnterSleepMode( );
UTIL_PowerDriver.ExitSleepMode( );
}
else
{
if( OffModeDisable != UTIL_LPM_NO_BIT_SET )
{
/**
* At least one user disallows Off Mode
* STOP mode is required
*/
log_i("in\r\n");
UTIL_PowerDriver.EnterStopMode( );
UTIL_PowerDriver.ExitStopMode( );
log_i("out\r\n");
}
else
{
/**
* OFF mode is required
*/
UTIL_PowerDriver.EnterOffMode( );
UTIL_PowerDriver.ExitOffMode( );
}
}

UTIL_LPM_EXIT_CRITICAL_SECTION_ELP( );
}
  • 在进入低功耗函数前,关闭中断(实际为屏蔽中断触发,不响应中断).退出低功耗函数后恢复中断.再进入低功耗到退出低功耗期间不会有任何中断响应
  • 调用代码printf("0X%08lx\r\n", SCB->ICSR);打印中断控制和状态寄存器的值发现为0x400f000.查看数据手册得知,为SYSTICK中断标志位挂起

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EQXd4ykc-1684999984303)(%E4%BD%8E%E5%8A%9F%E8%80%97%E6%97%A0%E6%B3%95%E7%94%9F%E6%95%88%E7%9A%84%E5%8E%9F%E5%9B%A0%E5%88%86%E6%9E%90.assets/image-20230524191410324.png)]

  • 可以判断为SYSTICK中断未处理,导致标志位未清除,无法进入低功耗

SYSTICK中断触发原因

  • 在屏蔽中断响应后,没有及时进入低功耗函数,触发了SYSTICK中断.
  • 导致中断标志挂起,无法进入低功耗

解决方案

  • 进退低功耗函数过程中,尽量减少运行量.防止systick挂起中断,导致进入低功耗失败

  • 开关中断函数之间调用较少代码.可以多次开关中断,减少一次开关中间的运行量

  • 在中断内打印尽量使用原生的printf,减少调用时间