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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
设备为stm32L071,rtt是github上下载的最新版4.1.1。在调试pm功能时遇到问题:. L3 r6 ?9 W6 b
1.可以进入STOP模式,tickless使用lptim,工作正常,软件定时器可以主动唤醒。+ D* G0 ~& p; X* _0 n
2.当使用外部中断唤醒stop模式后,串口工作不正常,debug发现唤醒后竟然先执行了中断服务函数,然后切换到等待信号量的线程,直到idle后才会执行中的睡眠前的代码处,这时才执行恢复时钟函数。9 \# F  g* G/ t& Y/ t
pm睡眠前应该是禁用了全局中断的,只发生pending不执行ISR才对,为什么会有这种问题呢?; }3 [9 D' f! j  N8 Z4 J

; x5 _$ V$ v  Q) F# \- }- Wstatic void rx_thread_entry(void *param)" y, u) N" Y" s- V8 q5 i- g
{
5 G0 F8 @/ t5 u: b4 Y; Ewhile(1)$ ]3 y# t7 J7 G% {, y$ ?
{
% Z7 v% U2 D# Kif (rt_sem_take(rx_sem, RT_WAITING_FOREVER) == RT_EOK)
* k+ Z3 P, A0 T3 r2 q{
! S7 E, }0 k# m3 u+ Zrt_pm_sleep_request(PM_BOARD_ID, PM_SLEEP_MODE_NONE);& V! o0 [9 w  r7 w. w) @
do something //此时串口异常,LOG等功能输出乱码) {* g. t( R8 S4 D5 B
rt_thread_mdelay(5);  //执行到此处,才跳转到睡眠前位置,恢复时钟
5 |8 h2 h2 T2 D8 ~8 R$ [rt_thread_mdelay(5000);
( _" C5 a; H0 H, i* `4 g, i& A+ Ert_pm_sleep_release(PM_BOARD_ID, PM_SLEEP_MODE_NONE);
& c9 s& J8 }$ c, ~# E9 |5 H4 {}
' t, |5 U9 c' n}2 T: ]/ D; [, J/ c
}4 g3 ]5 ^/ A* {* l/ k7 ~0 K
void lora_rx_irq_callback(void *parameter)
% T* D5 \& J* S6 Z; D* b, K{
! T6 A: M7 c9 _% Q4 Y3 b6 @$ g& _rt_sem_release(rx_sem); //先执行此行,释放信号量& Z8 Q8 n- N: I8 H4 f# K8 O
}
- K! C& k: \  jpm适配代码如下:! F# U4 j9 M- g) e- ^. `
3 O) k: H' n4 D/ }. h' H+ m. q
static void sleep(struct rt_pm *pm, uint8_t mode)
% h) ]3 H3 h6 Z/ o6 {; E{1 j) _) k9 B$ h4 v: m5 ]8 |" s
switch (mode)0 ?; [) X* i: f
{% w6 |" g$ ^$ A( N; [* M
case PM_SLEEP_MODE_NONE:7 i7 H- l. n7 Y( _# O
break;
* C% O9 a% K" X8 j3 L+ y# Ucase PM_SLEEP_MODE_IDLE:
! S/ p7 h1 ?5 {) I- lcase PM_SLEEP_MODE_LIGHT:% j7 w$ \  w6 |8 V
/* Enter SLEEP Mode, Main regulator is ON /7 l2 p& o! i. E# A- ?) S) B
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
, R- a, M. @9 R1 t0 x* ~3 bbreak;
) U! y% [5 [1 dcase PM_SLEEP_MODE_DEEP:* b& G5 ?6 ~; S0 Y* |  _
/ Disable SysTick interrupt /  x7 c  w7 z) n- h* s7 f
CLEAR_BIT(SysTick->CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk);' `6 g0 ^* F5 a# b. z3 t
/ Enable the Ultra Low Power mode and the fast wake up /; }( y$ D9 Y6 W- u$ Z4 K+ F
SET_BIT(PWR->CR, PWR_CR_ULP | PWR_CR_FWU);
0 |& {3 ], z5 O& \! Z. X/ Select HSI as system clock source after Wake Up from Stop mode /
" U$ Y7 j" q) X//__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
3 @$ J7 s. \4 U. E5 U0 A/ Enter STOP mode /' f+ b& p; P( }7 N! h% F
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
% g2 ^+ f; w8 \7 f7 r$ \/ Disable the Ultra Low Power mode and the fast wake up /
) \) }' E1 J( [! o7 L8 D/ CCLEAR_BIT(PWR->CR, PWR_CR_ULP | PWR_CR_FWU);
1 C3 T4 |* g1 a$ Y7 V) H/ ^8 z9 v/ Enable SysTick interrupt /
7 \1 ?' w( D4 m7 Z) i# BSET_BIT(SysTick->CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk);/ B9 f" w& t% r+ X
/ Re-configure the system clock /$ s' b0 v/ `5 T# g" o: v
SystEMClock_ReConfig();+ r, @; Q% a* E
break;
% o0 k8 _8 K, m/ Jcase PM_SLEEP_MODE_STANDBY:1 P' s% O; u5 z. Y
case PM_SLEEP_MODE_SHUTDOWN:
7 ~. F- K0 @* I2 _9 K% X+ ^( O__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);& U, L- ]& l7 `+ n) g
/ Enter STANDBY mode */* P+ ^# O( j% W: ~! ~
HAL_PWR_EnterSTANDBYMode();
: {* u% H+ v- L) |3 i8 x! cbreak;. k% `5 j. i& ^
default:% T( A1 {4 u/ ^& d, s  ^# J
RT_ASSERT(0);
/ w* i+ B% U- s# u/ Q- w" Xbreak;0 i3 {4 d. e' }; g
}0 T& h  z6 a$ I6 U7 y4 P+ d
}
0 m) R, v3 x: I+ X. H" t( x; g- o
& P  A) g% x/ [1 V; V* }% e/ [$ W
7 @- B0 N5 e/ V0
4 x& A: h9 g4 ?. G  f# m, `$ @$ @
7 T/ w/ }3 d" {9 u

该用户从未签到

5#
发表于 2022-9-7 14:59 | 只看该作者
楼上说的很不错
# v, p  Z; b7 n
  • TA的每日心情
    开心
    2023-6-2 15:15
  • 签到天数: 1 天

    [LV.1]初来乍到

    4#
    发表于 2022-9-7 14:36 | 只看该作者
    主要问题是中断唤醒后代码执行顺序问题。
    6 m2 Y/ o$ e" {$ F6 e$ H看了您的PM设计思想和代码,我理解的预期唤醒后执行顺序是:
    & t, t* E3 Q& g0 L1.外部中断Pending5 y' x5 [6 U7 f5 j2 j4 p
    2.MCU唤醒,按照睡眠前代码位置继续执行sleep函数中的HAL_PWR_EnterSTOPMode()后续代码,恢复时钟,补偿systick,开启全局中断! q' o$ C; ~# S% q( N3 A: c" h+ D; _
    3.执行ISR,释放信号量,通知等待信号量的线程
    $ ~& t2 T. L! B; i8 Y/ K5 _4.执行线程代码0 \1 ^( u- h0 G" g! V
    # D1 `3 j9 x. J$ c7 P& K* l
    但实际加断点debug测出的执行顺序为:
    , h, B8 L$ g! C7 D7 F1.外部中断Pending/ B/ O/ Q$ {6 l' ]: ~
    2.执行ISR,释放信号量,通知等待信号量的线程
    / w6 |* Z  u  l8 G0 ?3.执行线程代码  @6 @1 J& J: o6 t4 I* G
    4.等待idle,如延时函数,按照睡眠前代码位置继续执行sleep函数中的HAL_PWR_EnterSTOPMode()后续代码,恢复时钟,补偿systick,开启全局中断* S0 D  V7 ~* F# j8 b$ B
    : Q) j6 o- |$ G( b
    这就导致唤醒后时钟不对,且第一个延时函数会因为tick补偿直接超时,不会产生延时效果(1s、2s、3s、5s都测过不生效),我尝试加两次延时解决了。

    该用户从未签到

    3#
    发表于 2022-9-7 14:19 | 只看该作者
    rt_hw_interrupt_disable() 应该要实现 __disable_irq 的效果才对,可以查下相关的手册,ARM Cortex 相关的,不同的Cortex 核,可能不一样。
    5 [) O$ M1 m. }) ~% n$ \# F

    该用户从未签到

    2#
    发表于 2022-9-7 13:13 | 只看该作者
    那说明禁用全局中断响应 没有效果& |2 ]: Z( J( P3 C. \9 \
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-11-23 23:29 , Processed in 0.140625 second(s), 24 queries , Gzip On.

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

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

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