<acronym id="56cqn"></acronym>
<var id="56cqn"></var>
<big id="56cqn"></big>
    <blockquote id="56cqn"><ruby id="56cqn"></ruby></blockquote>
    <meter id="56cqn"></meter>

  1. <progress id="56cqn"><span id="56cqn"></span></progress>

    新闻中心

    EEPW首页 > 嵌入式系统 > 牛人业话 > 中断和主循环不?#23884;?系统一直休眠久睡

    中断和主循环不?#23884;?系统一直休眠久睡

    作者:寂寞君时间:2019-05-28来源:电子产品世界收藏

    你永远也唤不醒一个装睡的人,但是你可以一巴掌呼醒他。

    本文引用地址:http://www.bftj.tw/article/201905/400938.htm

    1559007449797597.jpg

    可如果一个系统休眠之后,就犹抱琵琶半遮面,千呼万唤醒不来了呢?笔者担纲开发的中控锁模块就醒不过来了。

    1

    这个问题已经折磨我整整两天了,搞得我心力憔悴。合作伙伴一天几个电话,恨不得从手机里面直?#29369;?#36807;来当面质问我:为什么唤不醒,为什么死睡?

    平时对我爱答不理的领导也一改常态,转而死死地盯着我。老实厚道的我呢,自然也十分紧张?#19968;?#24656;,因为问题十有八九确实出在我写的代码上。

    关键是这个问题出现在马上大批量供货的前夜,太不是时候了!我们给某车厂供货的中控锁模块已经走到了小批量供货阶段,前期供货20套倒是无惊无险,没发?#36136;?#20040;问题,按照流程,接下来要供货100套。

    如果阿弥陀佛的话,就再供货200套,再没有什么问题,就进入大批量供货阶段了。到?#20445;?#21512;作伙伴开始稳定盈利,领导政绩、奖金到手,不会争功只会揽过的我呢,挥一挥手?#35828;?#24149;后,深藏功与名,一切就万事大吉,只待岁月静好了。可是,恰恰在供货100套期间,忘了求菩萨保佑,结果?#32479;?#20107;了。

    一天,车厂的生产线上下线了装配了我们的中控锁模块的50辆新?#25285;?#26412;来一切顺利,在生产线上操作中控锁没什么问题,匹配学习了遥控钥匙,也能用遥控正常操作。但是到了下线后车厂人员要把新车开回仓库?#20445;?#31361;然发现有几台车用遥控钥匙、机械钥匙死活也唤醒不了了!!

    事关重大,车厂立马通知了中控锁的供货商—我们的合作伙伴,合作伙伴立马?#19994;?#20102;我们(中控锁的开发商)领导,领导立马?#19994;?#20102;我。我也立即给自己上紧了发条,进入战斗状态。

    2

    眼看到手的政绩和奖金要飞,领导心急火燎,早被晾到一边的我却颇不以为然。

    到了现在这个阶段,软件肯定没问题,有问题早就测出来了嘛,还能等到现在?肯定是中控锁的线束出了问题。

    当我把轻描淡写的分析说与领导?#20445;?#39046;导一改往日的温和,一下子急了:人家线束供了这么多年了,按你的说法,有问题早就测出来了,还能等到现在?

    岁月的风霜早已经消去了我性情中所有的刚硬和火热,只剩下如水的柔和。看到领?#25216;?#20102;,我心中起着嘀咕,脸上泛起笑容,小心翼翼地对领导言道:“要不?#20197;?#30475;一下代码,没准真是哪里出了岔子呢?”

    得到我的表态后,领导转身踱了开去,一边嘴里念叨着得跟车厂确认一下线束有没有问题,一边转过头来再次叮咛我一番:抓紧啊!看着领导?#19988;?#20999;的眼神和黑黑的眼圈,我用力地点了点头,一个猛子扎进代码的汪洋大海,迅速游至中控锁的休眠和唤醒之地。

    代码的设计思路总是简单而且正确的。中控锁进入休眠之前,设置了两个唤醒条件:①机?#21040;?#38145;信号的上升沿唤醒MCU;②定期检查遥控钥匙信号的定时器周期唤醒MCU。当出现有效的机械锁信号?#20445;?#25110;者检测?#25509;?#25928;的遥控信号?#20445;?#20013;控锁禁止这两个唤醒条件并返回正常状态。

    在具体的代码实现上,把中控锁的休眠模式处理分成了两部分:服务程序和循环体。由机械锁解锁开关信号触发,执行完ISR后?#30830;?#22238;循环体,再退出休眠模式。循环体中反复休眠和临时唤醒,在临时唤醒期间通过三级滤波机制检查是否存在有效的遥控钥匙信号。存在遥控信号?#20445;?#36825;个循环体层层地通过三级滤波后,退出休眠模式。

    逻辑上清晰,代码也很简单,我反反复复检查了几遍,没看出个子丑演卯来,就准时准点地下班回家了。

    第二天上班后,?#19968;?#27809;在工位上坐定,还没来得及平复一下自己的燥热劲头,领导就带着于我少有的笑意猫过来了。不?#20154;?#24320;口,老实巴交的我就主动汇报了检查代码后没有发?#36136;?#20040;问题的情况,no news is good news,但是此?#36125;?#30721;没有问题就是大问题啊!

    话音甫落,领导脸上还没来得及展开的笑容就凝固不动了,他张着口,默默地看着我。

    我们俩就这么站?#29275;?#19981;说话,就十分地不美好!

    城府甚深的领导终于没有说话,他不动声色地安排了一位同事搭建了中控锁的测试系统,让他反复测试休眠、唤醒的情况。

    3

    测试的方法很简单,把电流表串进中控锁的供电线上,看着电流下降到休眠电流?#27573;?#21518;,?#24756;?#20316;一下遥控钥匙,或者给一个机?#21040;?#38145;信?#29275;?#30475;能否执行解闭锁操作。

    ?#20197;?#19968;边冷眼观察着测试人员的操作,心情竟然无比地矛盾,?#35748;?#26395;他快点测出来不能正常唤醒的?#25910;希?#21448;盼着最好测试不出来问题。

    1559007483134162.jpg

    大半天下来,中控锁反反复复地正常休眠、被正常唤醒,我的心也反反复复地七上八下,百般煎熬。后来,测试人员的电话响了,我默默转身离开,同时发现自己竟然更加惶恐了!

    刚刚坐到电脑前,测试人员就大呼小叫着跑了过来:“寂寞君,问题再现了!”我就像屁股上安了个弹簧一样,一下子被凳子弹了起来,待我三步并作两步跨到测试台前?#20445;?#39046;导也已经闻声迅速赶来。

    我抓着遥控钥匙一边操作,一边注视着电流表的读数,电流一直稳定在2毫安左右。

    问题确认了,确实死活也唤不醒了。

    我又一屁股栽倒在凳子上,抬起头来,正赶上领导意味深长的目光。我抿着嘴笑了笑,刚想说点什么,测试台上测试人员的电话又嗡嗡响了起来。

    听着熟悉的手机铃声在耳边萦绕,看着手机在桌子上震动个不停,?#19968;?#24819;起测试人?#22791;?#25165;打电话时的情景,暗钝的思维再度转动起来:之前只是考虑了机?#21040;?#38145;单?#26469;?#21457;唤醒、遥控钥匙单?#26469;?#21457;唤醒的情况,没有考虑过遥控信号通过了前两级滤波而此时机?#21040;?#38145;信号突然触发执行了ISR这种罕见情况,莫非...?

    测试人?#22791;?#25165;打电话?#20445;?#30001;于手机的辐射,RF信号线上出现了若干有效的射频位,造成RF信号通过了前两级滤波,此时要在循环体的第三级滤波程序要等待200ms,判断是否是遥控按键信号。

    对于系统而言,200ms是一个不容忽视的时间段,?#28909;?#27979;试人员在这期间试图机?#21040;?#38145;,触发中断执行ISR后会发生什么呢?

    我继续扒拉开代码看进去,一丝寒意向我心头袭来。

    原来?#20197;贗SR中执行了退出休眠模式的函数-ExitSleepMode(这个函数里面会禁能唤醒条件),当ISR执行结束后回到循环体中?#20445;?#23427;会在200ms超时后进入循环体第三级滤波,当然它会发现不是有效的遥控按键信?#29275;?#20110;是再度进入休眠。

    但是这个时候已经禁能了唤醒条件,这就意味着它再也唤不醒了呀!!

    4

    人的思维真的很奇怪,本来bug明明就在眼前却视而不见,可是一旦猜到了bug的可能原因,就立马火眼金睛起来。

    为了帮助读者的理解,笔者给出了下面的?#36125;?#30721;,相信聪慧的读者也能看出问题所在。

    void interrupt Wake_ISR(void)

    {

    ...

       ExitSleepMode();//disable wakeup event

    ...

    }

    static void ConfirmRkeWakeUp(void)

    {

       __delay_ms(200);

       if(Rke is valid){

    ...

       ExitSleepMode();

    ...

       }

       else{

                 return to sleep ;

       }

    }

    再?#20040;?#23478;加深一下理解。

    假设机?#21040;?#38145;信号触发ISR?#20445;?#24490;环体正运行到RF信号的第三级滤波程序ConfirmRkeWakeUp之前,MCU会先执行ISR,在ISR中禁能唤醒条件,然后返回循环体中执行ConfirmRkeWakeUp。

    ConfirmRkeWakeUp函数延时200ms后,判断这200ms之间有没有有效的遥控钥匙信?#29275;?#26174;然这里是没有的,于是Return to sleep。

    但是,这个时候唤醒条件已经?#21796;?#33021;了(在ISR中?#21796;?#33021;了),系统就永远不会被唤醒了。

    眼尖的读者可能会纳闷,这?#27490;收?#20043;前为什么没有测试出来?

    因为按照之前的测试条件,这?#26234;?#20917;发生的几率非常小:循环体内执行ConfirmRkeWakeUp函数之前需要经过双重RF滤波,这要求中控锁的RF信号线上必须在较短的时间内存在较多的符合宽度要求的RF信号位,否则就不会执行ConfirmRkeWakeUp这个函数;平时用机械钥匙解锁?#20445;?#34429;然ISR中禁能了唤醒条件,但是由于不会执行ConfirmRkeWakeUp,ISR回到循环体之后,系统依然会退出休眠。

    平时用遥控钥匙解锁?#20445;?#26080;论期间有没有发生机?#21040;?#38145;ISR,最终都会执行ConfirmRkeWakeUp并退出休眠。

    所以,只有无效的遥控按键信号触发执行ConfirmRkeWakeUp函数时机?#21040;?#38145;信号同时有效,才会触发这?#27490;收稀?/p>

    汽车生产线上为什么测试出来这?#27490;收?#20102;呢?

    那是因为在生产线上装配了中控锁的车太多了,产线后端的中控锁模块进了休眠之后,用机械钥匙唤醒时很容易被其它车的遥控钥匙操作误触发,导致循环体执行到ConfirmRkeWakeUp上来。

    但是其它车的遥控钥匙对于本车来说是无效的,所以,根据上面的原因,?#25910;暇统?#29616;了。

    结语

    定位了?#25910;?#30340;原因之后,?#20063;唤?#21448;洋洋得意起来,‘这么高级的bug?#24613;?#25105;逮出来了!’。好似全然忘记了这个?#25910;?#23601;是我自己埋下的坑。

    事后,领导让我写总结原因?#20445;?#25105;意识到了这?#27490;收?#32972;后的深层次原因在于中断和循环体的不?#23884;裕?span style="text-indent: 2em;">中断服务程序结束后必然回到主循环体中被中断的位置;系统中,中断可能发生在主循环体的任何位置;ISR和循环体程序之间不存在执行时间的先后顺序关系,先后次序不同可能导致不同的运行结果?#25381;?#20110;ISR发生时循环体可能会执行到任何代码位置上,如果代码设计地不严谨就有可能会造成问题!

    煮熟的鸭子最终没有飞走,领导?#20013;?#24847;盈盈地踱了过来,跟我讨教?#25910;?#30340;原因。看着他那被即将到手的奖金鼓舞地有些肿胀的胸?#29275;?#25105;一边默默地念叨着‘狡兔死走狗烹,飞鸟尽良弓藏’,一边悠?#39057;?#35828;了一句总结陈?#21097;?strong>中断和主循环不?#23884;裕?#31995;统会一直休眠久睡!



    关键?#21097;? 中断 嵌入式

    评论


    相关推荐

    技术专区

    关闭
    49选7开奖历史记录