找回密码
 注册
关于网站域名变更的通知
查看: 247|回复: 4
打印 上一主题 下一主题

PM2.0外部中断唤醒后程序执行顺序异常为什么会发生这种情况呢

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-9-7 11:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
设备为stm32L071,rtt是github上下载的最新版4.1.1。在调试pm功能时遇到问题:
' O$ [& e: L' r0 [" h# A: G1.可以进入STOP模式,tickless使用lptim,工作正常,软件定时器可以主动唤醒。
% F  h9 e, T; P; D& s) a% m2.当使用外部中断唤醒stop模式后,串口工作不正常,debug发现唤醒后竟然先执行了中断服务函数,然后切换到等待信号量的线程,直到idle后才会执行中的睡眠前的代码处,这时才执行恢复时钟函数。
& F+ Z- a; y4 Q. k  fpm睡眠前应该是禁用了全局中断的,只发生pending不执行ISR才对,为什么会有这种问题呢?
& Z5 H9 |9 t: w2 h# M
1 H) |, O  S! }6 u5 Rstatic void rx_thread_entry(void *param), M/ e6 t% V' t$ V
{
" o5 `( Z' c, x1 u& hwhile(1)
( h& @; S& c( z- P: K{
7 }  B- v+ b7 k8 X" Qif (rt_sem_take(rx_sem, RT_WAITING_FOREVER) == RT_EOK)6 x# f1 f9 q; T' N
{
+ d4 @$ F: v( n; Nrt_pm_sleep_request(PM_BOARD_ID, PM_SLEEP_MODE_NONE);
$ q0 f: {5 ~+ h! w( `do something //此时串口异常,LOG等功能输出乱码/ k' p- s+ `0 z$ N
rt_thread_mdelay(5);  //执行到此处,才跳转到睡眠前位置,恢复时钟6 U; }* r' s9 W  h6 B& o' D
rt_thread_mdelay(5000);
% Z8 q. p- {6 h8 h! zrt_pm_sleep_release(PM_BOARD_ID, PM_SLEEP_MODE_NONE);
3 m* ]2 C7 A/ [( ]( b4 [; i}% p# `1 S# s- m. f$ e
}
) M% W3 }0 Y8 e" R; l  P9 p' W}
8 s) J8 y4 F$ C9 z. }void lora_rx_irq_callback(void *parameter)6 J" ?: m/ S% x/ W
{
7 ^) N$ Q5 D0 drt_sem_release(rx_sem); //先执行此行,释放信号量
: s4 e4 q0 o1 O7 O2 n$ Q}/ ~  A$ b6 G; w! w8 f' _7 H
pm适配代码如下:) ]. E8 @5 r( }# V, t& T. Q. Y2 {

& u5 j" B% d  `1 b, {static void sleep(struct rt_pm *pm, uint8_t mode)
& V* a- o0 _: _6 R, S! ^3 F. b{  ^# A- q; t' O/ q7 Y1 g/ p) m" \
switch (mode)
, T. _% b8 b. P3 `: {( V: u{$ P1 B2 J$ P( {2 T# G/ v0 H
case PM_SLEEP_MODE_NONE:9 s8 {$ U! n2 b  U+ \
break;
' m" A1 K: G9 l5 S4 Pcase PM_SLEEP_MODE_IDLE:% C& D5 [* N! a6 F/ A
case PM_SLEEP_MODE_LIGHT:" R: n* C5 T3 @7 Y. p' u
/* Enter SLEEP Mode, Main regulator is ON /
$ G3 S0 C* m+ J; {, ^HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
. N' B) }- Q- Z5 Nbreak;6 t- u* y5 y# f/ g7 j  A
case PM_SLEEP_MODE_DEEP:
/ _( \4 b. ?  s$ W9 s! m/ Disable SysTick interrupt /) g4 a" b1 Z9 _$ x
CLEAR_BIT(SysTick->CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk);
( L. x; ^4 q( c: e) W/ Enable the Ultra Low Power mode and the fast wake up /% [6 A- U9 ^6 o- o# t- l) o
SET_BIT(PWR->CR, PWR_CR_ULP | PWR_CR_FWU);
: q# k! Q$ d2 k7 N* U2 X/ Select HSI as system clock source after Wake Up from Stop mode /6 ^" m2 t, `6 e( k/ J
//__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);7 M" L3 j  }  Y; {
/ Enter STOP mode /
: y+ j4 D" e9 j$ ZHAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);4 Y/ j7 a5 J6 h( a* K, v
/ Disable the Ultra Low Power mode and the fast wake up /
0 D* m  t/ o) c" x+ LCLEAR_BIT(PWR->CR, PWR_CR_ULP | PWR_CR_FWU);6 j7 g: I0 R& `
/ Enable SysTick interrupt /9 _8 ~+ S6 s; [* F' b
SET_BIT(SysTick->CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk);2 M5 p: W% @% ^/ W8 {% e) Q
/ Re-configure the system clock /* v1 w' M5 c& d. o4 P0 _
SystEMClock_ReConfig();
0 x. \7 Q* Q) S: N' @' l0 F5 [break;
9 L4 V4 l; X) Vcase PM_SLEEP_MODE_STANDBY:  }/ q0 C3 s& J& e+ a/ P/ z
case PM_SLEEP_MODE_SHUTDOWN:
' q* H* o9 o6 L' X3 u) T__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);: Q2 Q0 {2 }; \' [4 s
/ Enter STANDBY mode */: n$ h/ B4 o% _3 n- |1 T$ |5 s. `
HAL_PWR_EnterSTANDBYMode();7 N* l/ x0 T0 z% F. [- ^
break;
9 f5 ~! S" k: X6 m. h' K, cdefault:
* k8 J2 ?9 L' u" }% e! W$ |RT_ASSERT(0);/ A: q- S$ a* I: {. _2 y7 F& e# G
break;. v4 ?$ t$ F  s* G. u8 S$ x
}- l. R$ {3 L- Y8 A4 ~
}
) C7 O8 @! X/ D" }5 R8 I3 a: c; r9 X5 B6 E" u5 x- D+ H
' D# Q$ @% [+ u: b5 Y
0; Y9 j! o) U1 l2 I

- {8 e! f2 H5 H: q) a1 p; o

该用户从未签到

2#
发表于 2022-9-7 13:13 | 只看该作者
那说明禁用全局中断响应 没有效果" u# ?8 u- Y, h! G! W8 s, f* a

该用户从未签到

3#
发表于 2022-9-7 14:19 | 只看该作者
rt_hw_interrupt_disable() 应该要实现 __disable_irq 的效果才对,可以查下相关的手册,ARM Cortex 相关的,不同的Cortex 核,可能不一样。
& e- k: {/ r7 R2 K1 S0 W
  • TA的每日心情
    开心
    2023-6-2 15:15
  • 签到天数: 1 天

    [LV.1]初来乍到

    4#
    发表于 2022-9-7 14:36 | 只看该作者
    主要问题是中断唤醒后代码执行顺序问题。" G- {% h) K( v# H9 t& @1 z+ d
    看了您的PM设计思想和代码,我理解的预期唤醒后执行顺序是:# I( V& s. h6 q( B1 y* N' ~; v
    1.外部中断Pending% x5 g  ?' g. M: y, y
    2.MCU唤醒,按照睡眠前代码位置继续执行sleep函数中的HAL_PWR_EnterSTOPMode()后续代码,恢复时钟,补偿systick,开启全局中断& S1 N& N! ^9 w! B0 R
    3.执行ISR,释放信号量,通知等待信号量的线程% L1 q  I' a$ L1 p) J- i: y  ~
    4.执行线程代码) }3 p1 m5 s% q8 E% l
    5 s1 W- L8 h% \* R/ O5 ]6 T
    但实际加断点debug测出的执行顺序为:8 I# v* m9 v1 d+ q/ n7 a
    1.外部中断Pending0 r+ f# d0 n& e; \& I
    2.执行ISR,释放信号量,通知等待信号量的线程
    # ~. o" ]; y2 U7 S' ~; M3.执行线程代码* ], P) n1 j. U) n6 q
    4.等待idle,如延时函数,按照睡眠前代码位置继续执行sleep函数中的HAL_PWR_EnterSTOPMode()后续代码,恢复时钟,补偿systick,开启全局中断
    ) P0 e5 }" B: ?! R9 E/ ~5 X' T' v- S: ^4 N
    这就导致唤醒后时钟不对,且第一个延时函数会因为tick补偿直接超时,不会产生延时效果(1s、2s、3s、5s都测过不生效),我尝试加两次延时解决了。

    该用户从未签到

    5#
    发表于 2022-9-7 14:59 | 只看该作者
    楼上说的很不错( U6 u$ Z2 `4 E1 `
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-23 16:33 , Processed in 0.156250 second(s), 23 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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