致系統(tǒng)啟動(dòng)卡死的根因與解決方案)
產(chǎn)品在客戶現(xiàn)場(chǎng)出現(xiàn)批量性“上電無反應(yīng)”返修回來一測(cè)板子本身沒壞程序卻怎么也跑不起來。最后查出來問題出在RTC初始化時(shí)對(duì)LSE32.768kHz低速外部晶振的死等上——LSE沒起振代碼就一直卡在初始化函數(shù)里后面的系統(tǒng)時(shí)鐘、外設(shè)、主循環(huán)全部癱瘓。這類“RTC with LSE blocking controller operation, boot issue”在嵌入式項(xiàng)目里非常典型尤其常見于帶RTC的低功耗產(chǎn)品、需要掉電計(jì)時(shí)的設(shè)備以及帶bootloader的升級(jí)系統(tǒng)。這篇東西我把根因、定位思路和完整的解決方案整理出來給同樣被LSE坑過的朋友一個(gè)參考。這個(gè)話題適合誰(shuí)看只要你手頭在調(diào)STM32、GD32、NXP、瑞薩這類帶獨(dú)立RTC域的MCU或者你在做低功耗產(chǎn)品、電池供電的儀表、數(shù)據(jù)記錄儀、帶日歷功能的控制器那這篇內(nèi)容值得你從頭到尾讀一遍。踩過一次這個(gè)坑之后你以后寫RTC初始化代碼會(huì)謹(jǐn)慎很多。1. 問題現(xiàn)場(chǎng)與定位過程1.1 最典型的現(xiàn)象板子像“磚”一樣毫無反應(yīng)這類故障最迷惑人的地方在于——硬件看起來完全正常。外接仿真器能識(shí)別芯片供電電壓正常復(fù)位引腳電平正常晶振兩端用示波器量也有微弱波形但程序就是不走。串口打印沒有任何輸出LED不閃按鍵無響應(yīng)。我見過最典型的現(xiàn)場(chǎng)是一批帶RTC功能的工業(yè)控制器客戶反饋“設(shè)備在倉(cāng)庫(kù)放了一晚上第二天開不了機(jī)”。剛開始懷疑是電池耗盡、電源模塊損壞、Flash程序丟失排查了一圈全排除。最后用仿真器連接點(diǎn)擊運(yùn)行發(fā)現(xiàn)程序計(jì)數(shù)寄存器PC一直停在同一個(gè)地址——一個(gè)while循環(huán)里??捶磪R編那個(gè)循環(huán)在反復(fù)檢查同一個(gè)狀態(tài)位而這個(gè)狀態(tài)位恰恰是LSE就緒標(biāo)志。這類問題的共同特征還有幾個(gè)設(shè)備首次上電偶爾能正常工作復(fù)位一次就卡死低溫和常溫表現(xiàn)不一致低溫更容易出問題拔掉備用電池再上電大概率復(fù)現(xiàn)如果帶看門狗現(xiàn)象會(huì)變成“反復(fù)復(fù)位循環(huán)”看起來像不停重啟1.2 快速定位從啟動(dòng)日志和卡死地址反推定位這個(gè)問題的速度取決于你的調(diào)試手段。我建議按以下順序排查效率最高第一連接仿真器全速運(yùn)行后暫停查看當(dāng)前PC指針停在哪個(gè)函數(shù)。如果正好停在RTC相關(guān)初始化代碼基本可以鎖定嫌疑。第二查看RCC時(shí)鐘狀態(tài)寄存器比如STM32的RCC_CSR或RCC_BDCR確認(rèn)LSERDY標(biāo)志是否置位。如果始終是0說明LSE確實(shí)沒有就緒。第三對(duì)照啟動(dòng)流程代碼檢查系統(tǒng)時(shí)鐘初始化和RTC初始化的先后順序。最常見的錯(cuò)誤配置就是——在SystemClock_Config之前就調(diào)用了RTC初始化而RTC初始化又依賴LSE。曾經(jīng)遇到一個(gè)更隱蔽的情況程序是在RTOS環(huán)境下跑的初始化任務(wù)里調(diào)了RTC結(jié)果LSE卡住導(dǎo)致整個(gè)任務(wù)調(diào)度器無法啟動(dòng)看起來像是系統(tǒng)完全崩潰。這種時(shí)候單看任務(wù)代碼很難發(fā)現(xiàn)問題必須結(jié)合硬件調(diào)試器查看當(dāng)前線程棧和PC值才能定位。1.3 確認(rèn)阻塞點(diǎn)死等LSE就緒標(biāo)志的幾種常見寫法我總結(jié)過LSE問題導(dǎo)致死機(jī)的代碼寫法基本逃不出下面三種第一種HAL庫(kù)默認(rèn)流程。HAL_RTC_Init會(huì)調(diào)用HAL_RCCEx_EnableLSE并等待LSERDY標(biāo)志HAL庫(kù)內(nèi)部有超時(shí)機(jī)制默認(rèn)超時(shí)時(shí)間比較長(zhǎng)但理論上不會(huì)無限阻塞。然而如果LSE一直沒有起振你就需要等一個(gè)非常長(zhǎng)的超時(shí)用戶體驗(yàn)上等同于卡死。第二種直接操作寄存器死等。很多工程師寫裸機(jī)代碼時(shí)喜歡簡(jiǎn)潔寫法類似RCC-BDCR | RCC_BDCR_LSEON; while((RCC-BDCR RCC_BDCR_LSERDY) 0);這行代碼就是災(zāi)難的源頭。沒有任何超時(shí)保護(hù)LSE只要不起振這里就是死循環(huán)。第三種部分低功耗庫(kù)或第三方RTOS的BSP代碼里會(huì)為了確保RTC時(shí)間有效反復(fù)重試LSE啟動(dòng)重試次數(shù)沒有上限甚至每次重試之間沒有延時(shí)導(dǎo)致芯片上電后絕大部分時(shí)間都耗在LSE等待上看起來就像卡死了。2. 根因深度解析LSE為什么起不來代碼為什么會(huì)卡死2.1 LSE起振原理和關(guān)鍵影響因素LSE是個(gè)皮爾斯振蕩器本質(zhì)上就是MCU內(nèi)部的反相放大器配合外部32.768kHz晶振和兩個(gè)負(fù)載電容形成振蕩回路。它和主晶振HSE最大的區(qū)別是工作頻率低、功耗要求極低、起振時(shí)間慢。正常情況起振時(shí)間在幾百毫秒到一秒多在低溫環(huán)境下可能需要更久甚至完全不起振。影響LSE起振的核心因素有以下幾個(gè)晶振負(fù)載電容CL匹配。32.768kHz晶振的負(fù)載電容常見標(biāo)稱值有6pF、7pF、9pF、12.5pF。MCU的LSE引腳本身有一些寄生電容PCB走線也會(huì)貢獻(xiàn)電容如果外部負(fù)載電容選得不對(duì)振蕩器的負(fù)阻余量就不夠表現(xiàn)為起振慢或不起振。晶振的等效串聯(lián)電阻ESR。大部分MCU規(guī)格書要求LSE晶振的ESR不超過70kΩ實(shí)際選型時(shí)我建議控制在50kΩ以內(nèi)。有些便宜晶振批次不同ESR離散性大同一個(gè)設(shè)計(jì)不同批次有的好有的壞這就能解釋為什么“有的板子沒問題有的板子死活起不來”。PCB布局和走線。LSE晶振應(yīng)該盡可能靠近MCU引腳兩條走線要短、要對(duì)稱避免平行長(zhǎng)走線周圍不要走高頻信號(hào)。如果晶振旁邊就是開關(guān)電源或者通信線干擾會(huì)直接導(dǎo)致起振困難。MCU內(nèi)部振蕩器驅(qū)動(dòng)能力配置。這個(gè)特別容易忽略。很多MCU尤其STM32的LSE驅(qū)動(dòng)能力是可調(diào)的有LOW、MEDIUM、HIGH幾個(gè)檔位。默認(rèn)配置可能是LOW在常溫下完全沒問題但在低溫和高ESR晶振組合下就起振不了。我習(xí)慣直接把LSE驅(qū)動(dòng)能力設(shè)到最高檔功耗多出來的那零點(diǎn)幾微安根本無所謂換來的起振可靠性是實(shí)打?qū)嵉摹?.2 阻塞式等待的隱患從MCU設(shè)計(jì)邏輯說起理解LSE阻塞的問題需要先理解MCU時(shí)鐘架構(gòu)的設(shè)計(jì)邏輯。在STM32等主流MCU上RTC模塊有兩個(gè)可用的低速時(shí)鐘源LSE外部32.768kHz晶振和LSI內(nèi)部低速RC振蕩器通常約32kHz或40kHz。LSE精度高20ppm甚至5ppmLSI精度差可能偏差百分之幾。關(guān)鍵點(diǎn)在于很多RTC應(yīng)用場(chǎng)景如日歷、定時(shí)喚醒、時(shí)間戳要求走時(shí)準(zhǔn)確所以工程師都優(yōu)先選LSE。但問題是LSI的效率高、上電即用不存在起振等待問題LSE則要經(jīng)過一個(gè)不確定時(shí)間的起振過程——可能是幾十毫秒也可能是永遠(yuǎn)。那么阻塞為什么會(huì)導(dǎo)致系統(tǒng)卡死因?yàn)镸CU的時(shí)鐘樹設(shè)計(jì)里某些外設(shè)總線或系統(tǒng)功能依賴LSE。例如在低功耗設(shè)計(jì)中LSE同時(shí)作為獨(dú)立看門狗IWDG的時(shí)鐘源或者作為RTC喚醒定時(shí)器的時(shí)鐘源。更關(guān)鍵的是LSE還經(jīng)常被配置為系統(tǒng)時(shí)鐘源之一通過MCO輸出或作為PLL輸入如果這段初始化代碼放在啟動(dòng)早期的時(shí)鐘配置階段LSE起不來后面的系統(tǒng)時(shí)鐘、Flash等待周期、外設(shè)時(shí)鐘全部無法配置整個(gè)控制器就“死”了。2.3 啟動(dòng)流程順序問題Bootloader和低功耗喚醒場(chǎng)景這個(gè)故障在帶bootloader的產(chǎn)品里還有個(gè)特殊變體bootloader里初始化了RTC用來做升級(jí)超時(shí)計(jì)時(shí)然后跳轉(zhuǎn)到App。跳轉(zhuǎn)時(shí)沒有正確關(guān)閉RTC中斷或者沒有復(fù)位RTC外設(shè)App啟動(dòng)時(shí)再次初始化RTC和bootloader的RTC狀態(tài)沖突導(dǎo)致LSE起振后又被異常配置打斷最終卡死。低功耗產(chǎn)品的場(chǎng)景則更微妙。設(shè)備從Stop模式或Standby模式喚醒后很多工程師直接在喚醒代碼里重新初始化RTC因?yàn)镾tandby模式會(huì)丟失RAM內(nèi)容和大部分外設(shè)寄存器狀態(tài)。如果喚醒瞬間電源不穩(wěn)或者LSE振蕩器還沒穩(wěn)定這個(gè)重新初始化過程就可能卡住。我曾經(jīng)踩過一個(gè)很深的坑設(shè)備在正常工作時(shí)RTC一切正常一旦拔掉主電源只靠備份電池供電運(yùn)行一段時(shí)間再重新插上主電源上電必現(xiàn)卡死。后來查清楚是VBAT域和VDD域的電壓時(shí)序問題LSE在上電瞬間供電不足起振失敗而代碼又是死等模式。3. 解決方案從軟件到硬件的完整修復(fù)路徑3.1 軟件方案一給LSE等待加超時(shí)永遠(yuǎn)不要死等這是最直接、最有效的軟件修復(fù)手段核心就是三個(gè)字加超時(shí)。不管你是用HAL庫(kù)、LL庫(kù)還是裸機(jī)寄存器操作一律給LSE等待加一個(gè)有限時(shí)間的超時(shí)判斷。HAL庫(kù)的方式大多數(shù)情況下你不需要改HAL內(nèi)部代碼只需要理解HAL_RTC_Init的時(shí)序即可但更可控的辦法是自己寫LSE啟動(dòng)邏輯uint8_t RTC_LSE_StartWithTimeout(uint32_t timeout_ms) { uint32_t tick_start GetTick(); /* 使能LSE */ RCC-BDCR | RCC_BDCR_LSEON; /* 輪詢等待就緒或超時(shí) */ while((RCC-BDCR RCC_BDCR_LSERDY) 0) { if((GetTick() - tick_start) timeout_ms) { /* 超時(shí)返回失敗 */ return 1; } } return 0; }超時(shí)時(shí)間的選擇有講究。太短比如50ms在低溫環(huán)境下可能LSE明明能起來但時(shí)間不夠?qū)е抡`判為故障太長(zhǎng)比如5秒用戶體驗(yàn)又太差。我的經(jīng)驗(yàn)值是500ms到1秒兼顧了正常起振時(shí)間和故障快速發(fā)現(xiàn)。工程實(shí)踐中我通常配合一個(gè)“首次等待長(zhǎng)、二次等待短”的策略首次上電或者從備份域掉電狀態(tài)恢復(fù)時(shí)給1秒如果是軟復(fù)位后的熱啟動(dòng)給200ms足夠。3.2 軟件方案二LSE失敗自動(dòng)降級(jí)到LSI超時(shí)跳過只是第一步更關(guān)鍵的問題是LSE起不來RTC還要不要工作對(duì)于很多產(chǎn)品來說RTC功能是核心賣點(diǎn)比如定時(shí)開關(guān)機(jī)、事件記錄時(shí)間戳、鬧鐘喚醒。這時(shí)候如果LSE失效就直接放棄RTC產(chǎn)品功能就殘廢了。所以推薦做法是LSE超時(shí)后自動(dòng)切換到LSI作為RTC時(shí)鐘源同時(shí)設(shè)置一個(gè)“RTC精度降級(jí)”標(biāo)志位后續(xù)通過串口或者上位機(jī)給用戶提示。if(RTC_LSE_StartWithTimeout(1000) 0) { /* LSE啟動(dòng)成功使用LSE */ RCC-BDCR ~RCC_BDCR_RTCSEL; RCC-BDCR | RCC_BDCR_RTCSEL_LSE; } else { /* LSE啟動(dòng)失敗降級(jí)使用LSI */ RCC-BDCR ~RCC_BDCR_RTCSEL; RCC-BDCR | RCC_BDCR_RTCSEL_LSI; /* 記錄降級(jí)標(biāo)志到備份寄存器 */ RTC_BackupRegWrite(RTC_BKP_DR0, RTC_FLAG_LSI_FALLBACK); }LSI的精度雖然不如LSE但做定時(shí)喚醒、相對(duì)計(jì)時(shí)這類對(duì)絕對(duì)時(shí)間精度要求不高的場(chǎng)景完全夠用。等系統(tǒng)跑起來后如果你有外部時(shí)間同步源比如WiFi校時(shí)、GPS校時(shí)、4G網(wǎng)絡(luò)校時(shí)還可以定期校準(zhǔn)RTC時(shí)間進(jìn)一步彌補(bǔ)LSI的精度不足。這個(gè)降級(jí)策略在電動(dòng)自行車儀表、充電樁控制器、IoT傳感器這些產(chǎn)品上實(shí)用性非常強(qiáng)。3.3 軟件方案三重排啟動(dòng)流程遵循“先主時(shí)鐘后RTC”原則很多boot卡死問題其實(shí)在設(shè)計(jì)啟動(dòng)流程時(shí)就可以完全避開。核心原則是RTC初始化絕不能放在系統(tǒng)主時(shí)鐘配置之前更不能放在任何引導(dǎo)關(guān)鍵功能如Flash、串口、看門狗之前。我推薦的啟動(dòng)順序是這樣的上電后第一件事配置系統(tǒng)時(shí)鐘樹用HSE或HSI作為系統(tǒng)時(shí)鐘源保證CPU和外設(shè)總線有可靠的時(shí)鐘。初始化必要的關(guān)鍵外設(shè)串口用于調(diào)試日志、GPIO用于狀態(tài)指示、看門狗如果需要。然后才輪到RTC初始化。此時(shí)RTC即使卡住也只會(huì)影響RTC功能本身不會(huì)拖垮整個(gè)系統(tǒng)。最后啟動(dòng)RTOS調(diào)度器或者進(jìn)入主循環(huán)。這個(gè)順序調(diào)整看起來簡(jiǎn)單但能解決一大半RTC阻塞導(dǎo)致的boot問題。你想想如果系統(tǒng)時(shí)鐘都還沒配置好串口還沒有初始化你連調(diào)試日志都打不出來排查問題全靠猜那不是自己給自己挖坑嗎。3.4 硬件排查與整改從選型和PCB層面根治軟件修復(fù)是治標(biāo)硬件整改才是治本。如果你的產(chǎn)品還在研發(fā)階段或者問題批量出現(xiàn)一定要從硬件角度做以下幾項(xiàng)檢查晶振選型確認(rèn)。查看BOM里32.768kHz晶振的規(guī)格書確認(rèn)負(fù)載電容標(biāo)稱值、ESR參數(shù)、工作溫度范圍。我在一個(gè)項(xiàng)目里遇到過晶振工作溫度上限只有60℃的料設(shè)備在夏天戶外直接罷工換工業(yè)級(jí)晶振后問題消失。PCB布局優(yōu)化。晶振盡量靠近MCU走線要粗短負(fù)載電容接地點(diǎn)要干凈晶振下方不要鋪銅周圍用地環(huán)包起來更好。這個(gè)屬于基本功但很多小批量打樣的板子布局都比較隨意出問題概率自然高。MCU的LSE驅(qū)動(dòng)能力調(diào)高。對(duì)于STM32系列寫RCC_BDCR之前先設(shè)置LSEDRV位為最高檔或者用HAL庫(kù)的HAL_RCCEx_ControlLSEDrive()函數(shù)。檢查VBAT供電電路。如果VBAT引腳串了電阻或者二極管壓降太大會(huì)導(dǎo)致備份域供電電壓不足LSE振幅不夠起振不了。VBAT供電通路要盡量低阻抗有些MCU的VBAT引腳對(duì)電壓有明確要求比如2.0V以上別讓電池電壓在正常范圍內(nèi)但到達(dá)引腳時(shí)已經(jīng)低于閾值。批量生產(chǎn)測(cè)試中加入LSE檢查。很多人不知道STM32的RTC備份寄存器可以存儲(chǔ)標(biāo)志位。生產(chǎn)線測(cè)試時(shí)燒錄程序后做一個(gè)LSE起振測(cè)試起振失敗就把板子單獨(dú)挑出來返修不要流到客戶手里。4. 實(shí)操?gòu)?fù)盤一個(gè)典型的量產(chǎn)故障排查案例4.1 場(chǎng)景還原低溫環(huán)境下批量“變磚”那是一個(gè)做冷鏈溫度記錄儀的項(xiàng)目MCU用的是STM32L4系列帶RTC功能產(chǎn)品靠一顆紐扣電池維持RTC計(jì)時(shí)??蛻舴答佉慌O(shè)備在冷庫(kù)-18℃環(huán)境下放置24小時(shí)后取出約3%的設(shè)備無法正常啟動(dòng)屏幕黑屏按鍵無反應(yīng)但測(cè)量電池電壓和供電電壓均正常。實(shí)驗(yàn)室復(fù)現(xiàn)非常困難常溫下這批設(shè)備一切正常放冰箱冷凍室24小時(shí)后再拿出來測(cè)試能復(fù)現(xiàn)大約2%的故障率。這個(gè)概率不算高但對(duì)于量產(chǎn)產(chǎn)品來說2%的返修率已經(jīng)是重大質(zhì)量事故了。4.2 排查步驟從仿真器到示波器逐級(jí)深入第一步故障板上接ST-Link仿真器發(fā)現(xiàn)PC停在LSE等待循環(huán)里。這就確認(rèn)了問題方向。第二步用示波器探頭測(cè)量LSE晶振兩腳波形。注意不要用普通10x探頭直接測(cè)量探頭電容會(huì)改變振蕩器負(fù)載導(dǎo)致停振最好用有源差分探頭或者用低電容探頭。實(shí)測(cè)發(fā)現(xiàn)晶振兩腳幾乎沒有振蕩波形只有微弱的噪聲。第三步對(duì)照電路圖檢查負(fù)載電容。發(fā)現(xiàn)設(shè)計(jì)圖紙用的是兩個(gè)6.8pF電容但BOM里實(shí)際貼片的是10pF采購(gòu)替換物料時(shí)把封裝相同的電容混用了。這個(gè)差異導(dǎo)致振蕩回路負(fù)阻余量下降常溫下勉強(qiáng)能起振低溫下一部分離散性大的晶振就罷工了。第四步讀取MCU的LSE驅(qū)動(dòng)配置寄存器發(fā)現(xiàn)固件里用的是默認(rèn)的LOW檔位沒有把驅(qū)動(dòng)能力配置調(diào)高。4.3 最終修復(fù)方案軟件硬件雙管齊下軟件方面重寫LSE啟動(dòng)邏輯增加超時(shí)判斷1000ms和LSI降級(jí)策略將LSE驅(qū)動(dòng)能力配置為HIGH檔把RTC初始化挪到系統(tǒng)時(shí)鐘配置和串口初始化之后增加故障日志記錄LSE啟動(dòng)失敗時(shí)在備份寄存器記錄錯(cuò)誤碼下次啟動(dòng)如果檢測(cè)到該錯(cuò)誤碼主動(dòng)延長(zhǎng)LSE等待時(shí)間并嘗試多次重試硬件方面更換負(fù)載電容從10pF改為規(guī)格書推薦的6.8pF嚴(yán)格統(tǒng)一BOM物料避免采購(gòu)替換增加生產(chǎn)線測(cè)試項(xiàng)通過讀取RTC時(shí)間走時(shí)精度來判斷LSE是否正常整改后的效果故障率降至0連續(xù)跟蹤三個(gè)月沒有再出現(xiàn)同類問題。這個(gè)案例帶來的最大啟示是——這類問題往往是“軟件沒有容錯(cuò)機(jī)制”和“硬件裕量不足”兩個(gè)因素疊加的結(jié)果單獨(dú)修任何一個(gè)都無法徹底解決。5. 常見問題與排查技巧速查5.1 問題場(chǎng)景速查表故障現(xiàn)象排查重點(diǎn)最可能的根因快速解決辦法上電無反應(yīng)程序不走PC停留位置LSERDY標(biāo)志LSE死等加超時(shí)跳過LSE等待反復(fù)復(fù)位循環(huán)看門狗是否在LSE等待期間超時(shí)看門狗在LSE卡住時(shí)觸發(fā)復(fù)位初始化看門狗之前確保LSE就緒或加超時(shí)冷啟動(dòng)正常復(fù)位后卡死LSE起振時(shí)間差異熱啟動(dòng)時(shí)LSE起振時(shí)間變長(zhǎng)延長(zhǎng)熱啟動(dòng)超時(shí)時(shí)間低概率批量性故障晶振參數(shù)、負(fù)載電容容差物料參數(shù)離散性或替換檢查BOM實(shí)際物料調(diào)整電容拔掉電池后卡死VBAT域狀態(tài)備份域未初始化檢測(cè)備份域復(fù)位標(biāo)志走完整RTC重新初始化流程bootloader跳轉(zhuǎn)App后卡死RTC中斷或外設(shè)狀態(tài)殘留跳轉(zhuǎn)前未正確復(fù)位RTC跳轉(zhuǎn)前關(guān)閉RTC中斷DeInit RTC外設(shè)喚醒后無法恢復(fù)喚醒代碼中RTC初始化喚醒時(shí)LSE未穩(wěn)定增加喚醒后延時(shí)再初始化RTC5.2 多年調(diào)試積累的獨(dú)家避坑經(jīng)驗(yàn)關(guān)于LSE的調(diào)試有幾個(gè)經(jīng)驗(yàn)值得單獨(dú)拎出來說晶振測(cè)量要輕手輕腳。示波器探頭直接懟到晶振引腳上很可能直接把振蕩器停振讓你誤判為“晶振沒起振”。正確做法是用探頭測(cè)量MCU的MCO引腳把LSE從MCO輸出出來再測(cè)量這樣不影響振蕩器本身。備用電池的電動(dòng)勢(shì)不等于VBAT引腳的實(shí)際電壓。很多產(chǎn)品用電池座加紐扣電池給VBAT供電電池座彈片氧化后接觸電阻可能高達(dá)幾十歐姆RTC需要的電流雖然很小但接觸電阻和電池內(nèi)阻在低溫下會(huì)增大導(dǎo)致VBAT引腳電壓低于閾值。排查時(shí)用萬用表直接量MCU引腳上的電壓不要量電池正極。批量問題優(yōu)先查物料差異。如果只有個(gè)別板子有問題多數(shù)是焊接不良、晶振本體損壞如果是一批板子集中爆發(fā)一定先查物料批次變更記錄。我見過不止一次因?yàn)椴少?gòu)替換電容、替換晶振導(dǎo)致批量性LSE問題的事情。RTC初始化代碼里永遠(yuǎn)不要寫死循環(huán)。就算你理論分析認(rèn)為L(zhǎng)SE一定會(huì)起振實(shí)際硬件總會(huì)給你“驚喜”。加一個(gè)超時(shí)失敗后至少留下日志比裸死強(qiáng)一萬倍。寫在最后的一點(diǎn)體會(huì)做嵌入式這行越是看起來簡(jiǎn)單的基礎(chǔ)功能越容易在關(guān)鍵時(shí)刻給你上一課。RTC加個(gè)LSE原理圖就那么幾根線程序就那幾行初始化代碼但它在極端條件下能把整個(gè)系統(tǒng)鎖死。我現(xiàn)在的習(xí)慣是每一段涉及硬件外設(shè)的初始化代碼都默認(rèn)“硬件可能會(huì)失敗”超時(shí)、降級(jí)、日志三件套必須配齊。這套思路幫我在后續(xù)的項(xiàng)目里規(guī)避了不止RTC這一個(gè)坑也希望對(duì)你有所啟發(fā)。