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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
设备为stm32L071,rtt是github上下载的最新版4.1.1。在调试pm功能时遇到问题:
' [& N8 P9 @/ S7 y1.可以进入STOP模式,tickless使用lptim,工作正常,软件定时器可以主动唤醒。8 o, d, e3 v) t  |0 J0 B# i. d
2.当使用外部中断唤醒stop模式后,串口工作不正常,debug发现唤醒后竟然先执行了中断服务函数,然后切换到等待信号量的线程,直到idle后才会执行中的睡眠前的代码处,这时才执行恢复时钟函数。
6 u$ `! @0 n+ b! h3 B, Fpm睡眠前应该是禁用了全局中断的,只发生pending不执行ISR才对,为什么会有这种问题呢?
1 r; Z( K. L! Q& o' Y9 q( L- O2 s3 i4 R6 W& ~
static void rx_thread_entry(void *param)9 d% }4 `( p: ]. j) f
{
, ~, U/ \" }4 E3 D" gwhile(1)
2 l1 s' E8 U! T7 Y3 V{. d6 n# Z7 V- O
if (rt_sem_take(rx_sem, RT_WAITING_FOREVER) == RT_EOK)
& R- ^3 P& e) M4 m) d" m% v{
8 e$ [. }4 i- f3 {rt_pm_sleep_request(PM_BOARD_ID, PM_SLEEP_MODE_NONE);/ }; ]! t6 g& e" t
do something //此时串口异常,LOG等功能输出乱码5 t5 _1 J2 P; y
rt_thread_mdelay(5);  //执行到此处,才跳转到睡眠前位置,恢复时钟
9 C4 S8 _3 c5 d" M' D$ ~) B- Drt_thread_mdelay(5000);0 p$ h8 ?* t# D/ O
rt_pm_sleep_release(PM_BOARD_ID, PM_SLEEP_MODE_NONE);
. X/ t" N3 k2 H( V# J}
7 _7 p, Y& K, G; _, f( A+ y}% [7 `; v$ G3 J7 V0 k
}: `3 J* }* U) o
void lora_rx_irq_callback(void *parameter)4 h% D- P' j- T8 ]6 O. L
{
% M5 w* \+ F1 s9 _4 P/ y. t  vrt_sem_release(rx_sem); //先执行此行,释放信号量
( T& j: T6 b5 X+ K* t}
4 g0 K2 }1 e3 u+ Z8 `' xpm适配代码如下:
  X5 X% P& [" t0 d0 q
* F: B  \8 |* u# G) e# [" Gstatic void sleep(struct rt_pm *pm, uint8_t mode)
7 W7 {! g. d! M/ m4 `' q2 `5 D{
3 Y4 l. {. Q1 l/ j: {" kswitch (mode)2 i6 U3 t9 d* Q# y+ D# N) E* @3 x
{9 E, W  I4 P! Q2 F9 h; V8 G
case PM_SLEEP_MODE_NONE:- r; h4 N+ U4 K0 k; Q
break;
; C# ?3 e; T$ D  ]5 w$ Zcase PM_SLEEP_MODE_IDLE:5 Z& ?. W6 c( ?9 F9 a, r- w( _8 x
case PM_SLEEP_MODE_LIGHT:
# S) g1 I: E  R4 ?1 j# x) d& {6 D7 u/* Enter SLEEP Mode, Main regulator is ON /+ G% e+ i* n. A/ d7 P; |0 b( {
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);: f. d+ |- k4 S! p+ G
break;0 y* j4 M; t; h' l9 Q
case PM_SLEEP_MODE_DEEP:
3 J7 g2 W4 h1 [6 @3 \; h% V/ Disable SysTick interrupt /7 N0 P  Q, S3 A/ E$ Z, G
CLEAR_BIT(SysTick->CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk);3 R/ b$ [' C2 b/ h
/ Enable the Ultra Low Power mode and the fast wake up /
3 ^6 W! Q& p9 {2 |SET_BIT(PWR->CR, PWR_CR_ULP | PWR_CR_FWU);
5 s8 U5 N8 u  l, s# F/ Select HSI as system clock source after Wake Up from Stop mode /
& m3 r% C8 ?  R# g//__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);+ e! p) P2 N- D% a: L0 m
/ Enter STOP mode /
+ ^) Y7 Q3 y% C" r5 kHAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);3 {& _+ d4 e! f0 c$ u& a
/ Disable the Ultra Low Power mode and the fast wake up /
5 }( |7 R6 E% A! D& ]CLEAR_BIT(PWR->CR, PWR_CR_ULP | PWR_CR_FWU);; J, I  a! }7 A2 [
/ Enable SysTick interrupt /" k* ?8 n! c9 h7 D* q9 T0 v
SET_BIT(SysTick->CTRL, (rt_uint32_t)SysTick_CTRL_TICKINT_Msk);3 {. H& ~9 K2 C2 k9 o  @
/ Re-configure the system clock /
; W- A/ j% W2 R! RSystEMClock_ReConfig();
% x' O3 j3 u* g( D- V4 Ibreak;
- }* P9 T6 _! e, ocase PM_SLEEP_MODE_STANDBY:
9 R' o( \6 f3 |2 }case PM_SLEEP_MODE_SHUTDOWN:6 F8 _7 f, V0 B+ G2 |9 n
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
0 `' P8 \1 ?: g2 g( [/ Enter STANDBY mode */1 K8 E# i" e9 j% v( t
HAL_PWR_EnterSTANDBYMode();
/ z6 ~7 V  ^8 `4 S8 Tbreak;( v1 b5 i6 l8 j* H) h1 d
default:
8 E/ w0 y& K0 m  S8 k* pRT_ASSERT(0);# F; N! ]$ A9 ~) _2 j  u
break;1 u! H' f4 n2 C7 G9 v2 F5 v' v
}
9 l5 \& U. M! Y! @' y}2 z. P5 D5 d( `" }# `
# R; s$ s% [# b& s9 a

. V" Z5 y$ R, o7 f* @) W8 ?& V7 |0
' V/ s* ?* |: l9 d1 ]& z  @4 [: p) {( F

该用户从未签到

2#
发表于 2022-9-7 13:13 | 只看该作者
那说明禁用全局中断响应 没有效果! U3 R, h! k, E3 k4 n0 i7 A

该用户从未签到

3#
发表于 2022-9-7 14:19 | 只看该作者
rt_hw_interrupt_disable() 应该要实现 __disable_irq 的效果才对,可以查下相关的手册,ARM Cortex 相关的,不同的Cortex 核,可能不一样。
3 v% B! C( x+ D; j
  • TA的每日心情
    开心
    2023-6-2 15:15
  • 签到天数: 1 天

    [LV.1]初来乍到

    4#
    发表于 2022-9-7 14:36 | 只看该作者
    主要问题是中断唤醒后代码执行顺序问题。# r' [2 ]+ K2 ~2 C' F( a
    看了您的PM设计思想和代码,我理解的预期唤醒后执行顺序是:
    8 S& O1 X; ^2 h! T  C+ V( H1.外部中断Pending& `- `* e8 O9 C/ ^7 G$ T
    2.MCU唤醒,按照睡眠前代码位置继续执行sleep函数中的HAL_PWR_EnterSTOPMode()后续代码,恢复时钟,补偿systick,开启全局中断
    ; }7 J  [/ _4 c) {  \4 g) M3.执行ISR,释放信号量,通知等待信号量的线程, I7 `3 l. p; L' u7 r* z4 f8 l
    4.执行线程代码1 L5 Z+ g* A1 |4 D" q4 v0 ~
    & L9 _& `8 d6 G- s( R1 A9 M: B
    但实际加断点debug测出的执行顺序为:
    0 J* E9 Q, E1 ?7 [3 G1.外部中断Pending; Q1 j# g' h% @+ R
    2.执行ISR,释放信号量,通知等待信号量的线程$ j5 M- |: P/ l9 e
    3.执行线程代码& Z# s/ E0 E1 E! k& ^/ c* n
    4.等待idle,如延时函数,按照睡眠前代码位置继续执行sleep函数中的HAL_PWR_EnterSTOPMode()后续代码,恢复时钟,补偿systick,开启全局中断
    2 g) A, x- x) Y' }! H4 J$ I" [+ e6 ]+ [+ x
    这就导致唤醒后时钟不对,且第一个延时函数会因为tick补偿直接超时,不会产生延时效果(1s、2s、3s、5s都测过不生效),我尝试加两次延时解决了。

    该用户从未签到

    5#
    发表于 2022-9-7 14:59 | 只看该作者
    楼上说的很不错; L/ p8 l4 y. L. g+ F% a
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

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

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

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

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