試口鎖死排查:DA認(rèn)證成功卻無(wú)法調(diào)試的根因與恢復(fù))
STM32 的調(diào)試口被鎖死而且是在燒錄 provisioning 工程之后這種問(wèn)題我遇到過(guò)不止一次。最近有個(gè)朋友在 NUCLEO-H533RE 開發(fā)板上跑 H523 的 provisioning 項(xiàng)目遇到了一個(gè)特別典型的情況DADebug Authentication流程顯示成功但代碼跑起來(lái)之后ST-LINK 完全連不上芯片調(diào)試口徹底丟失。這個(gè)現(xiàn)象很迷惑因?yàn)?provisioning 成功后理論上應(yīng)該處于“可調(diào)試”狀態(tài)結(jié)果反而被鎖住了。我先把結(jié)論放在前面這個(gè)問(wèn)題十有八九不是 DA 流程本身失敗而是 provisioning 過(guò)程中把 debug 權(quán)限配置成了受限模式或者 DA 燒錄完成后芯片進(jìn)入了錯(cuò)誤的生命周期狀態(tài)。H523 和 H533 同屬 STM32H5 系列安全架構(gòu)完全一致所以用 NUCLEO-H533RE 的 provisioning 參考工程去調(diào)試 H523 芯片硬件上沒問(wèn)題但配置上的坑一個(gè)都不會(huì)少。這篇文章我打算從 H5 系列的安全生命周期講起把 DA 流程到底做了什么、為什么“成功”了卻拿不回調(diào)試權(quán)限、以及怎么一步步排查和恢復(fù)完整梳理一遍。如果你也正在用 H5 系列做安全啟動(dòng)或者代碼保護(hù)這篇內(nèi)容應(yīng)該能幫你少走不少?gòu)澛贰?. 整體設(shè)計(jì)與思路拆解H5 系列安全體系與 provisioning 的關(guān)系1.1 為什么 H523 和 H533 可以共用 provisioning 工程很多人在看到 NUCLEO-H533RE 的 provisioning 示例工程時(shí)會(huì)有個(gè)疑問(wèn)我用的芯片明明是 H523為什么參考工程是 H533 的這兩個(gè)型號(hào)能通用嗎答案是能通用但要注意邊界。H523 和 H533 同屬 STM32H5 系列都基于 Cortex-M33 內(nèi)核都集成了 RDPRead Protection、HDPHardware Diversification Protection、Secure Storage 等安全特性最關(guān)鍵的是它們共享同一套 TrustZone 架構(gòu)和 DA 流程。ST 官方在 NUCLEO-H533RE 板卡的示例工程中實(shí)際上已經(jīng)把 H5 系列共用的安全框架都包含了所以用它來(lái)做 H523 的 provisioning 參考在代碼層面基本沒有障礙。但這里有個(gè)容易被忽略的點(diǎn)H523 和 H533 在某些安全特性上并不完全一致比如 Flash 容量和 OBKOption Bytes Key的配置細(xì)節(jié)可能有差異。這意味著 provisioning 工程生成的配置數(shù)據(jù)不能無(wú)腦直接燒到 H523 里需要針對(duì)芯片型號(hào)重新生成和校準(zhǔn)。很多人在這一步跳過(guò)了 check直接用 H533 的配置去燒 H523最后出問(wèn)題也就不奇怪了。1.2 Debug Authentication 到底在做什么DA 的全稱是 Debug Authentication是 H5 系列用于管理調(diào)試權(quán)限的核心機(jī)制。它的作用可以理解成一把“安全鑰匙”芯片在出廠時(shí)處于開放狀態(tài)任何人都可以通過(guò)調(diào)試器讀寫 Flash但當(dāng)你啟用了 RDP讀保護(hù)或 TrustZone 后芯片會(huì)進(jìn)入受限狀態(tài)此時(shí)普通的調(diào)試器連接就會(huì)被拒絕只有擁有正確證書和密鑰的設(shè)備才能通過(guò) DA 協(xié)議重新打開或關(guān)閉調(diào)試口。從技術(shù)原理上講DA 基于一組由 ST 提供的根密鑰和證書鏈。provisioning 工程做的事情就是把這組密鑰、證書以及相關(guān)的配置數(shù)據(jù)燒錄到芯片的 OTPOne-Time Programmable區(qū)域同時(shí)設(shè)置生命周期狀態(tài)。燒錄完成后芯片會(huì)根據(jù)配置決定是否允許調(diào)試器訪問(wèn)。這里有個(gè)非常關(guān)鍵的概念DA 成功不代表調(diào)試口一定打開。DA 成功只代表“認(rèn)證和授權(quán)過(guò)程完成了”但授權(quán)的結(jié)果是什么取決于你在 provisioning 工程里配置的 debug 權(quán)限。如果你把權(quán)限配置成了 Disabled那么 DA 認(rèn)證成功之后芯片依然不會(huì)開放調(diào)試口。這就是標(biāo)題里說(shuō)的“DA reports success but cannot regain debug access”的核心原因。1.3 為什么“成功”卻失去調(diào)試能力結(jié)合我實(shí)際排查過(guò)的情況這個(gè)問(wèn)題通常不是單一原因?qū)е碌亩嵌鄠€(gè)因素疊加。第一個(gè)因素是生命周期狀態(tài)的改變。STM32H5 芯片的生命周期包括 STATE_OPEN、STATE_CLOSED、STATE_LOCKED 等幾個(gè)狀態(tài)。正常情況下DA 流程應(yīng)該讓芯片在 CLOSED 和 OPEN 之間切換而如果 provisioning 過(guò)程中把生命周期設(shè)置成了 LOCKED那么這個(gè)狀態(tài)是單向不可逆的芯片會(huì)永久鎖定調(diào)試口就再也回不來(lái)了。第二個(gè)因素是 RDP 等級(jí)配置錯(cuò)誤。RDP 分為 Level 0無(wú)保護(hù)、Level 1禁止外部調(diào)試但允許 DA 回歸和 Level 2永久保護(hù)。如果 provisioning 工程把 RDP 等級(jí)設(shè)置成了 Level 2那就等于放棄了所有后續(xù)調(diào)試的可能性。第三個(gè)因素也是很多人容易忽略的DA 證書和密鑰配置不匹配。NUCLEO-H533RE 的工程默認(rèn)使用 ST 官方開發(fā)板自帶的調(diào)試證書而如果你手上的是第三方核心板或者自己畫的板子芯片里的根密鑰和工程里預(yù)置的證書可能對(duì)不上。這種情況下 DA 流程可能“假成功”——通訊正常、握手正常但最終因?yàn)槊荑€不匹配授權(quán)結(jié)果無(wú)法生效調(diào)試口依舊鎖死。2. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)provisioning 工程的關(guān)鍵配置拆解2.1 工程結(jié)構(gòu)到底哪些文件在控制安全狀態(tài)在 NUCLEO-H533RE 的 provisioning 示例工程里你會(huì)看到一堆與安全配置相關(guān)的源文件和腳本。初次接觸的人很容易迷失在這些文件里不知道哪個(gè)才是控制最終安全狀態(tài)的關(guān)鍵。我這里幫你把核心的部分梳理清楚。首先是DA/目錄這里面存放的是 Debug Authentication 相關(guān)的證書、密鑰和配置文件。具體來(lái)說(shuō)里面有 ST 提供的根證書、開發(fā)板的設(shè)備證書以及用于生成 DA 配置的腳本。這個(gè)目錄是整個(gè) provisioning 流程的“身份證”它決定了你的 DA 流程能不能被芯片認(rèn)可。其次是RDP/相關(guān)的配置這些配置決定了讀保護(hù)等級(jí)。你可以通過(guò)修改這個(gè)配置來(lái)設(shè)定 RDP Level 0 還是 Level 1。在實(shí)際操作中我不建議在初學(xué)階段嘗試 RDP Level 2因?yàn)橐坏M(jìn)去芯片就永久鎖死了。再往下是OptionBytes配置文件這個(gè)文件控制了很多硬件層面的行為包括看門狗配置、BORBrown-Out Reset等級(jí)、以及最重要的 Debug 權(quán)限配置。你可能想不到很多“DA 成功但失去調(diào)試口”的問(wèn)題根源就在這個(gè)文件的某個(gè)位域上。還有一個(gè)非常隱蔽的配置是boot lock。在 H5 系列中你可以給 boot 區(qū)加鎖這樣即使通過(guò)調(diào)試口成功連接也無(wú)法讀取或改寫 boot 區(qū)的代碼。如果你在 provisioning 工程里意外啟用了 boot lock又會(huì)多一個(gè)“能連上但沒權(quán)限”的坑。2.2 實(shí)操修改 provisioning 工程前的準(zhǔn)備工作在動(dòng)手改任何配置之前我強(qiáng)烈建議你先做兩件事第一備份當(dāng)前能用的燒錄配置。用 STM32CubeProgrammer 連接開發(fā)板導(dǎo)出當(dāng)前的 Option Bytes 和 RDP 狀態(tài)保留一份“健康狀態(tài)”的快照。萬(wàn)一后面改出了問(wèn)題這可能是唯一的恢復(fù)線索。第二確認(rèn)芯片型號(hào)和板卡版本。H523 和 H533 雖然是同系列但引腳和 Flash 大小有差異這會(huì)影響 provisioning 腳本自動(dòng)生成的地址映射。請(qǐng)仔細(xì)閱讀工程的 README確認(rèn)你使用的是匹配的型號(hào)定義STM32H523xx而不是STM32H533xx。準(zhǔn)備完成后下一步是檢查 DA 配置文件中的證書鏈?zhǔn)欠衽c你的板卡匹配。提示NUCLEO 開發(fā)板出廠時(shí)ST 會(huì)在 OTP 區(qū)域?qū)懭肱c該板卡匹配的調(diào)試證書。如果你使用的是原裝 NUCLEO-H533RE 板卡直接用工程默認(rèn)配置一般沒問(wèn)題。但如果你的板卡是二手的或者之前被別人燒錄過(guò)其他密鑰證書鏈可能已經(jīng)不匹配了。怎么確認(rèn)呢你可以用 STM32CubeProgrammer 連接板卡在 OBOption Bytes頁(yè)面查看 Debug Authentication 相關(guān)的狀態(tài)。正常情況下未 provisioning 的板卡會(huì)顯示 “No DA config” 或類似的提示。如果顯示已有配置說(shuō)明板卡已經(jīng)不是出廠狀態(tài)建議優(yōu)先恢復(fù)出廠配置。2.3 實(shí)操provisioning 流程的完整步驟這里我把一個(gè)標(biāo)準(zhǔn)的 provisioning 流程走一遍并指出每個(gè)步驟的易錯(cuò)點(diǎn)。第一步編譯 provisioning 工程。在 STM32CubeIDE 中打開工程確認(rèn)編譯宏定義中含有STM32H523xx或STM32H533xx取決于你的芯片。編譯時(shí)注意看輸出如果有任何關(guān)于 DA 配置或證書路徑的警告不要忽略。第二步用 STM32CubeProgrammer 連接板卡先做一次全擦除Full Flash Erase。這一步是為了清除可能殘留的舊配置。命令大致如下STM32_Programmer_CLI -c portSWD modeHOTPLUG -e all第三步燒錄 provisioning 所需的初始固件。這個(gè)固件通常由工程中預(yù)編譯好的.elf或.hex文件提供它會(huì)在芯片上電后自動(dòng)執(zhí)行 DA 配置流程。燒錄命令示例STM32_Programmer_CLI -c portSWD modeHOTPLUG -w provisioning.hex -v第四步斷電并重新上電。這一步非常關(guān)鍵因?yàn)?provisioning 流程一般在上電后的 boot 階段執(zhí)行。如果執(zhí)行成功串口或調(diào)試日志中會(huì)輸出類似 “Provisioning done” 的信息。第五步用 STM32CubeProgrammer 的 DA 連接模式重新連接板卡STM32_Programmer_CLI -c portSWD modeHOTPLUG da./DA/config/DA_config.json如果一切正常命令行會(huì)輸出認(rèn)證成功的日志并且芯片恢復(fù)可調(diào)試狀態(tài)。但如果你遇到的是“DA 成功但無(wú)法調(diào)試”問(wèn)題就出在第四步和第五步之間。下面我會(huì)專門展開講排查方法。2.4 Provisioning 常見配置誤區(qū)根據(jù)我之前幫人解決這類問(wèn)題的經(jīng)驗(yàn)有幾個(gè)配置誤區(qū)出現(xiàn)的頻率特別高第一個(gè)是 RDP 等級(jí)被誤設(shè)為 Level 2。在 STM32CubeProgrammer 的界面里RDP 等級(jí)的修改非常容易操作但如果你只是點(diǎn)了一下下拉框選成了 Level 2 并 Apply芯片就永久保護(hù)了沒有任何后悔的余地。這一點(diǎn)請(qǐng)務(wù)必警惕。第二個(gè)是 DA 配置中選擇的 debug 權(quán)限錯(cuò)誤。在 DA 配置文件中有一項(xiàng)專門控制認(rèn)證后授予的調(diào)試權(quán)限通常有Full debug、Restricted debug和No debug三個(gè)選項(xiàng)。如果你選了 Restricted 或 No debug即使 DA 認(rèn)證成功調(diào)試器也無(wú)法讀取 Flash 內(nèi)容只能執(zhí)行有限的命令。第三個(gè)是 provisioning 工程里默認(rèn)啟用了SECBOOT安全啟動(dòng)。在 H5 系列中SECBOOT 默認(rèn)是開啟的它會(huì)強(qiáng)制校驗(yàn)啟動(dòng)代碼的簽名。如果你后續(xù)要燒錄自己的應(yīng)用程序而程序沒有經(jīng)過(guò)簽名芯片就會(huì)一直卡在啟動(dòng)校驗(yàn)階段表現(xiàn)為“能連接但程序不跑”。這雖然不完全是調(diào)試口丟失但很容易被誤判為“芯片掛了”。3. 實(shí)操過(guò)程與核心環(huán)節(jié)實(shí)現(xiàn)從鎖死狀態(tài)到恢復(fù)調(diào)試口的完整記錄3.1 現(xiàn)場(chǎng)現(xiàn)象記錄與初步判斷我手上這塊板子的現(xiàn)象是這樣的provisioning 完成后串口日志顯示 DA 流程成功然后我嘗試用 STM32CubeProgrammer 以 SWD 方式連接結(jié)果報(bào)錯(cuò)Error: Connection error或ST-LINK error。重新上電后再試依然連不上。用示波器抓 SWDIO 引腳波形發(fā)現(xiàn)芯片在收到連接請(qǐng)求后完全沒有響應(yīng)這說(shuō)明芯片內(nèi)部的調(diào)試端口已經(jīng)不再響應(yīng)外部請(qǐng)求。遇到這種情況先別急著判斷“芯片廢了”。按照我的經(jīng)驗(yàn)第一步先確認(rèn)芯片是否還在正常運(yùn)行。方法很簡(jiǎn)單看板載 LED 或者串口輸出。如果芯片主程序還在跑說(shuō)明 CPU 沒有死只是調(diào)試口被關(guān)了。如果連程序都不跑那可能是啟動(dòng)流程卡死了問(wèn)題可能出在 SECBOOT 或 Option Bytes。我這次遇到的情況是主程序還在跑串口持續(xù)輸出日志但調(diào)試口連不上??梢曰炬i定問(wèn)題在 Debug 權(quán)限配置而不是芯片硬件損壞。3.2 恢復(fù)嘗試一使用 DA 重新開放調(diào)試口既然 DA 流程報(bào)告成功那第一反應(yīng)自然是再用 DA 連一次看看能不能把調(diào)試口重新打開。這里需要用到 DA 配置文件。在 NUCLEO-H533RE 的 provisioning 工程中DA/目錄下會(huì)生成一個(gè)類似DA_config.json的文件里面包含了證書路徑、密鑰路徑和權(quán)限設(shè)置。用命令行連接時(shí)命令是這樣的STM32_Programmer_CLI -c portSWD da./DA/config/DA_config.json如果配置正確你會(huì)看到類似下面的輸出Successful DA authentication Debug access granted這說(shuō)明 DA 認(rèn)證通過(guò)調(diào)試權(quán)限被重新授予。但在我這次的現(xiàn)象中即便出現(xiàn)了認(rèn)證成功SWD 連接依然失敗或者只能連接到但立刻斷開。這時(shí)候你要小心不要讓“認(rèn)證成功”的假象誤導(dǎo)判斷。DA 認(rèn)證成功只能說(shuō)明證書和密鑰匹配不代表芯片的調(diào)試端口真正打開了。如果配置文件中把調(diào)試權(quán)限設(shè)成了 No debug那么認(rèn)證的結(jié)果就是“認(rèn)證成功但拒絕調(diào)試”。3.3 恢復(fù)嘗試二檢查并修正 Debug 權(quán)限配置如果配置文件中確實(shí)存在調(diào)試權(quán)限設(shè)置錯(cuò)誤那么正確的做法是修改 DA 配置文件把調(diào)試權(quán)限改回 Full debug然后重新執(zhí)行 DA。具體來(lái)說(shuō)在DA_config.json或者腳本中會(huì)有一項(xiàng)類似debug_authorization的字段值通常是full、restricted或none。如果你之前設(shè)置的是restricted或none改成full再試一次STM32_Programmer_CLI -c portSWD da./DA/config/DA_config_new.json從實(shí)操經(jīng)驗(yàn)看如果 provisioning 后立刻發(fā)現(xiàn)調(diào)試口異常這一步是最有可能解決問(wèn)題的。但如果你和我一樣是在 provisioning 完成后的第 N 次上電才發(fā)現(xiàn)的那可能還要處理下面這個(gè)更麻煩的情況。3.4 恢復(fù)嘗試三回到初始狀態(tài)的“救急方案”如果 DA 配置無(wú)法重新打開調(diào)試口另一種常用的恢復(fù)路徑是利用 H5 系列支持的回歸流程Regression。但這里有個(gè)前提芯片的 RDP 等級(jí)必須不是 Level 2?;貧w流程的思路很簡(jiǎn)單通過(guò) DA 認(rèn)證后把芯片的 RDP 等級(jí)降回 Level 0同時(shí)清除所有安全配置。在 STM32CubeProgrammer 中有一個(gè)專門的三級(jí)回歸按鈕或者在腳本命令中執(zhí)行STM32_Programmer_CLI -c portSWD da./DA/config/DA_config.json obRDP0這個(gè)命令的意思是在通過(guò) DA 認(rèn)證后強(qiáng)制把讀保護(hù)等級(jí)降到 Level 0。如果成功芯片會(huì)進(jìn)入全擦除狀態(tài)之后你可以重新燒錄代碼一切歸零。注意這個(gè)操作會(huì)擦除所有 Flash 內(nèi)容包括 provisioning 配置、密鑰、證書等。所以一旦做了回歸之前的 DA 配置就沒了需要重新 provisioning。如果你的目的只是恢復(fù)開發(fā)能力那么這是最徹底的方案。但如果芯片的 RDP 等級(jí)已經(jīng)是 Level 2或者生命周期狀態(tài)已經(jīng)進(jìn)入了 LOCKED那么回歸流程基本無(wú)法執(zhí)行。這種情況下只能更換芯片。3.5 實(shí)操記錄本次問(wèn)題最終如何解決回到我這次的案例。通過(guò)逐項(xiàng)排查最終定位到問(wèn)題出在Option Bytes中的 Debug 權(quán)限位。provisioning 工程在燒錄時(shí)默認(rèn)把調(diào)試權(quán)限配置成了 restricted導(dǎo)致 DA 認(rèn)證通過(guò)后只能獲得受限調(diào)試權(quán)限無(wú)法讀寫 Flash。解決方法是修改 provisioning 工程中控制 Option Bytes 的配置文件將調(diào)試權(quán)限改為 full重新編譯并再次執(zhí)行 provisioning。之后 STM32CubeProgrammer 成功連接燒錄恢復(fù)正常。多說(shuō)一句如果你不想重新走一遍 provisioning 流程還有一個(gè)臨時(shí)繞過(guò)方案在發(fā)現(xiàn) DA 成功但連不上調(diào)試口時(shí)立刻按住板子上的 NRST 復(fù)位鍵在復(fù)位瞬間嘗試連接 SWD。在某些情況下芯片啟動(dòng)早期調(diào)試口還處于開放狀態(tài)可以利用這個(gè)時(shí)間窗口執(zhí)行回歸命令。這個(gè)技巧的成功率取決于芯片啟動(dòng)速度和復(fù)位時(shí)序不是每次都能成功但值得一試。4. 常見問(wèn)題與排查技巧實(shí)錄我踩過(guò)的那些坑和對(duì)應(yīng)解法4.1 問(wèn)題速查表我把 H5 系列上 DA 相關(guān)的高頻問(wèn)題整理成了表格方便你對(duì)照排查。現(xiàn)象可能原因排查方法解決思路DA 報(bào)告成功但調(diào)試口無(wú)法連接Debug 權(quán)限配置為 restricted/none檢查 DA 配置文件中 debug_authorization 字段修改為 full 并重新執(zhí)行 DADA 認(rèn)證失敗提示證書不匹配OTP 中的根密鑰與工程證書不匹配檢查板卡是否為原廠 NUCLEO確認(rèn)是否二次 provisioning更換匹配的 DA 配置或恢復(fù)出廠板卡配置芯片完全無(wú)響應(yīng)NRST 后也無(wú)法連接RDP Level 2 或生命周期進(jìn)入 LOCKED嘗試回歸命令查看芯片電源和時(shí)鐘如果無(wú)法回歸只能更換芯片能連接調(diào)試器但程序不跑SECBOOT 啟用導(dǎo)致簽名校驗(yàn)失敗檢查啟動(dòng)日志查看 SECBOOT 配置關(guān)閉 SECBOOT 或?qū)Τ绦蚝灻鸇A 命令執(zhí)行后連接不穩(wěn)定SWD 時(shí)序問(wèn)題或線纜過(guò)長(zhǎng)降低 SWD 速率使用更短的杜邦線在 STM32CubeProgrammer 中設(shè)置頻率為 4MHz 以下4.2 獨(dú)家避坑技巧這些細(xì)節(jié)沒人告訴你我在折騰 H5 系列安全功能時(shí)積累了不少經(jīng)驗(yàn)有幾個(gè)細(xì)節(jié)特別值得拿出來(lái)分享。第一個(gè)是關(guān)于 STM32CubeProgrammer 的版本。DA 功能在不同版本的工具中實(shí)現(xiàn)差異很大。老版本可能根本不支持 DA或者支持和 H5 系列的連接方式不同。我建議統(tǒng)一使用最新的 STM32CubeProgrammer至少在 2.14 以上。版本不對(duì)DA 流程的成功率和穩(wěn)定性都會(huì)打折扣。第二個(gè)是 SWD 連接速率。很多人忽略了這個(gè)看似無(wú)關(guān)緊要的參數(shù)。在 provisioning 之后芯片內(nèi)部可能還殘留了一些安全校驗(yàn)邏輯如果 SWD 速率過(guò)高連接過(guò)程中容易出錯(cuò)表現(xiàn)為“時(shí)好時(shí)壞”的詭異現(xiàn)象。遇到這種情況先把速率降到 4MHz 以下再試。第三個(gè)是要學(xué)會(huì)利用--modeHOTPLUG連接參數(shù)。HOTPLUG 模式會(huì)跳過(guò)芯片的啟動(dòng)流程直接訪問(wèn)調(diào)試端口在芯片卡死在啟動(dòng)階段時(shí)非常有用。很多“連不上”的問(wèn)題用 HOTPLUG 模式就能繞過(guò)。第四個(gè)是關(guān)于二次 provisioning 的注意事項(xiàng)。如果你已經(jīng)對(duì)芯片做過(guò)一次 provisioning重新再燒錄一次 provisioning 工程時(shí)必須先執(zhí)行全擦除和回歸否則 DA 配置會(huì)疊加導(dǎo)致狀態(tài)混亂。這就像在一個(gè)已經(jīng)裝了系統(tǒng)的硬盤上再裝一次系統(tǒng)不格式化就會(huì)沖突。4.3 如何徹底避免我的建議流程經(jīng)過(guò)多次折騰我現(xiàn)在做 H5 系列開發(fā)時(shí)已經(jīng)形成了一套固定的操作流程可以最大程度避免把芯片鎖死的風(fēng)險(xiǎn)。首先在開始任何涉及 provisioning 或 RDP 的操作之前我會(huì)先截一個(gè)系統(tǒng)當(dāng)前的 Option Bytes 快照。用 STM32CubeProgrammer 的 OB 頁(yè)面導(dǎo)出一個(gè)文本文件保存所有選項(xiàng)字節(jié)的當(dāng)前值。這個(gè)文件在你需要恢復(fù)現(xiàn)場(chǎng)時(shí)是救命稻草。其次第一次燒錄 provisioning 工程時(shí)我會(huì)故意把 RDP 等級(jí)保持在 Level 0先驗(yàn)證 DA 配置本身是否正常確認(rèn) DA 能成功連接并切換調(diào)試權(quán)限之后再去提升保護(hù)等級(jí)。不要一上來(lái)就全部拉滿給排查留出余地。再次我會(huì)把 provisioning 工程和應(yīng)用程序工程分開管理。provisioning 只負(fù)責(zé)安全配置和 DA 設(shè)置應(yīng)用程序則是純功能邏輯。這樣可以避免在每次燒錄應(yīng)用代碼時(shí)都去觸碰安全配置減少誤操作的風(fēng)險(xiǎn)。最后如果你真的在一個(gè)非常重要的項(xiàng)目上用了 provisioning 并且已經(jīng)鎖死了芯片建議直接換一片新芯片把鎖死的芯片留著做安全逃生實(shí)驗(yàn)。比起不斷嘗試各種恢復(fù)命令浪費(fèi)的時(shí)間一片開發(fā)板芯片的成本其實(shí)低得多。5. 延伸思考理解 H5 系列安全模型的底層邏輯5.1 生命周期狀態(tài)機(jī)為什么“成功”不一定等于“開放”如果你一路看到這里應(yīng)該已經(jīng)理解了 DA 成功和調(diào)試口開放不是一回事。為了把這層邏輯徹底講透我再展開說(shuō)一下 H5 系列的生命周期狀態(tài)機(jī)。H5 系列芯片內(nèi)部維護(hù)了一個(gè)安全生命周期狀態(tài)機(jī)常見狀態(tài)包括STATE_OPEN出廠狀態(tài)調(diào)試口完全開放RDP 為 Level 0所有人都能讀寫 Flash。STATE_CLOSED受保護(hù)狀態(tài)RDP 至少為 Level 1調(diào)試口默認(rèn)關(guān)閉只有通過(guò) DA 認(rèn)證才能臨時(shí)打開調(diào)試權(quán)限。STATE_LOCKED永久鎖定狀態(tài)所有調(diào)試功能禁止DA 也不可恢復(fù)只能更換芯片。provisioning 的核心目的就是讓芯片從STATE_OPEN切換到STATE_CLOSED同時(shí)把 DA 所需的密鑰和證書寫入 OTP。而 DA 認(rèn)證的作用則是在STATE_CLOSED狀態(tài)下通過(guò)安全握手臨時(shí)授予調(diào)試權(quán)限。注意這里的關(guān)鍵詞是“臨時(shí)”。每次復(fù)位之后調(diào)試口都會(huì)重新回到關(guān)閉狀態(tài)必須再次執(zhí)行 DA 才能打開。這個(gè)設(shè)計(jì)和傳統(tǒng)的 MCU 完全不同。傳統(tǒng) MCU 上你只需要用調(diào)試器連上就能讀 Flash而 H5 系列把調(diào)試權(quán)限拆成了“物理連接”和“安全授權(quán)”兩層。很多剛接觸 H5 的人包括我最初都會(huì)下意識(shí)用傳統(tǒng) MCU 的思路去操作結(jié)果就是被安全機(jī)制狠狠教育了一番。5.2 DA 的根密鑰體系為什么板卡不能亂用H5 系列的 DA 機(jī)制建立在公開密鑰基礎(chǔ)設(shè)施PKI之上。ST 在芯片出廠時(shí)會(huì)在 OTP 區(qū)域?qū)懭胍粚?duì)設(shè)備獨(dú)有的密鑰對(duì)公鑰用于驗(yàn)證外部 DA 請(qǐng)求的簽名私鑰則永遠(yuǎn)不會(huì)泄露。為了便于開發(fā)ST 的 NUCLEO 開發(fā)板默認(rèn)使用 ST 公開的 DA 配置也就是開發(fā)板里的公鑰和 ST 提供的證書是匹配的。所以你直接用工程默認(rèn)配置就能完成 DA 認(rèn)證。但如果你用的是自己畫的板子或者從非正規(guī)渠道購(gòu)買的散料芯片芯片里的根密鑰可能和 ST 公共證書不匹配就必須通過(guò) STM32TrustedPackageCreator 或者其他工具生成對(duì)應(yīng)的密鑰和證書并把公鑰燒錄到芯片的 OTP 中。很多人的“DA 報(bào)告成功但無(wú)法調(diào)試”問(wèn)題其實(shí)就出在這個(gè)環(huán)節(jié)可能板卡上的證書已經(jīng)變了但工程里的配置還是默認(rèn)的 ST 證書。DA 流程的握手可能已經(jīng)完成但證書驗(yàn)證失敗最終授權(quán)沒有被芯片接受。如何確認(rèn)呢在 provisioning 完成前先用 STM32CubeProgrammer 讀一下 OTP 里與 DA 相關(guān)的區(qū)域看看里面是否已經(jīng)有內(nèi)容。如果已經(jīng)有內(nèi)容且不是全 F說(shuō)明芯片可能已經(jīng)被動(dòng)過(guò)手腳。5.3 TrustZone 對(duì)調(diào)試權(quán)限的額外影響值得一提的還有 TrustZone。H523 和 H533 都支持 TrustZone而 TrustZone 的啟用狀態(tài)會(huì)影響調(diào)試權(quán)限的分配。啟用 TrustZone 后芯片的 Flash 和 RAM 會(huì)被劃分為安全和非安全兩個(gè)區(qū)域。調(diào)試器可以配置為只允許調(diào)試安全區(qū)、只允許調(diào)試非安全區(qū)或者兩者都允許。在 provisioning 工程中如果只給非安全區(qū)授予了調(diào)試權(quán)限而你的應(yīng)用程序跑在安全區(qū)就會(huì)遇到“能連上但看不到程序”的詭異問(wèn)題。這種情況的排查方法相對(duì)簡(jiǎn)單在 DA 配置或調(diào)試器的選項(xiàng)中把安全區(qū)和非安全區(qū)的調(diào)試權(quán)限都打開。在 STM32CubeProgrammer 里連接設(shè)置中一般有Secure debug和Non-secure debug的選項(xiàng)確保兩者都勾選。5.4 H5 系列安全開發(fā)的技術(shù)選型建議我把前面所有經(jīng)驗(yàn)匯成幾句直接的建議。如果你的項(xiàng)目中使用的芯片需要防止代碼被讀取又希望保留后續(xù)現(xiàn)場(chǎng)調(diào)試的能力那么 H5 系列的 DA 機(jī)制是目前 MCU 里做得比較完善的方案。但前提是你必須理解 DA 的工作機(jī)制并且不要把 RDP Level 2 當(dāng)成“安全感的來(lái)源”。Level 2 意味著徹底的鎖定調(diào)試口和回歸路徑都沒有了。如果你的項(xiàng)目只是常規(guī)的固件開發(fā)不涉及代碼保護(hù)那我建議暫時(shí)不要碰 provisioning 和 RDP保持出廠狀態(tài)即可。安全功能的調(diào)試復(fù)雜度會(huì)顯著拖慢開發(fā)進(jìn)度確實(shí)沒必要為了“顯得專業(yè)”去折騰。如果你的團(tuán)隊(duì)有多個(gè)開發(fā)人員共用一塊板子建議為每個(gè)開發(fā)人員準(zhǔn)備獨(dú)立的 NUCLEO 板卡。因?yàn)?DA 配置和板卡綁定換人調(diào)試時(shí)證書不匹配又會(huì)出現(xiàn)“DA 成功但連不上”的問(wèn)題。6. 一些額外的操縱技巧和注意事項(xiàng)6.1 利用 STM32TrustedPackageCreator 生成自定義密鑰如果你需要在自己的板卡上啟用 H5 系列的安全功能就不能依賴 ST 的默認(rèn)證書需要自己生成一套密鑰和證書。這個(gè)過(guò)程使用的是 STM32TrustedPackageCreator 工具它在安裝 STM32CubeProgrammer 時(shí)會(huì)一并安裝。具體操作流程是打開 STM32TrustedPackageCreator選擇對(duì)應(yīng)的芯片型號(hào)然后在 DA 配置頁(yè)面生成新的密鑰對(duì)和證書。生成后會(huì)得到一組.pem格式的證書文件和.key格式的私鑰文件。這些文件需要在 provisioning 工程中逐一引用。這里有個(gè)非常關(guān)鍵的細(xì)節(jié)生成的公鑰必須提前燒錄到芯片的 OTP 區(qū)域否則芯片在驗(yàn)證 DA 請(qǐng)求時(shí)無(wú)法找到匹配的證書。這個(gè)燒錄動(dòng)作可以放在 provisioning 流程的第一步或者通過(guò) Option Bytes 設(shè)置完成。我在測(cè)試中發(fā)現(xiàn)很多人忘記這一步導(dǎo)致 DA 認(rèn)證一直失敗卻把鍋甩給 ST 的工具其實(shí)問(wèn)題出在自己的操作順序上。6.2 如何安全地用一個(gè) DA 配置同時(shí)管理多塊板卡實(shí)際項(xiàng)目中很多時(shí)候你需要同時(shí)管理多塊板卡讓它們能夠通過(guò)同一個(gè) DA 配置進(jìn)行調(diào)試。這個(gè)需求完全可以實(shí)現(xiàn)方法是在生成密鑰對(duì)時(shí)把同一個(gè)公鑰燒錄到所有板卡的 OTP 中。這樣做的風(fēng)險(xiǎn)是一旦某塊板卡丟失持有私鑰的人就可以通過(guò) DA 獲取調(diào)試權(quán)限。所以在生產(chǎn)環(huán)境中公鑰燒錄和私鑰保管需要嚴(yán)格分離。私鑰應(yīng)該存放在安全的管理員環(huán)境中普通開發(fā)人員只使用 DA 請(qǐng)求工具不接觸私鑰文件。6.3 調(diào)試口丟失后的幾條實(shí)用操作建議如果你現(xiàn)在正面對(duì)一塊“DA 成功但無(wú)法調(diào)試”的板卡我最后給你幾個(gè)直接可操作的建議。無(wú)論如何先把 DA 配置文件檢查一遍確認(rèn) debug 權(quán)限是 full。這一步可以用五分鐘完成卻能解決一半以上的問(wèn)題。然后用 HOTPLUG 模式加低速率連接試一次。注意是 HOTPLUG 模式不是普通的 SWD 連接。很多連不上的情況在 HOTPLUG 模式下都能連接成功。再試試在復(fù)位瞬間發(fā)送 DA 請(qǐng)求。具體方法是在 STM32CubeProgrammer 的 DA 配置界面點(diǎn)擊執(zhí)行 DA 的同時(shí)手動(dòng)按下板卡的 NRST 按鍵。這種“雷電操作”雖然成功率不穩(wěn)定但在某些時(shí)序條件下可以抓住芯片啟動(dòng)早期的調(diào)試窗口。如果以上都不行那么老老實(shí)實(shí)做回歸操作。但前提是芯片的 RDP 等級(jí)不是 Level 2。如果已經(jīng)是 Level 2那就直接換芯片吧不要在這塊芯片上繼續(xù)浪費(fèi)時(shí)間了。以我個(gè)人實(shí)際折騰 H5 系列的經(jīng)驗(yàn)最不值當(dāng)?shù)淖龇ň褪窃谝粋€(gè)已經(jīng)鎖死的芯片上反復(fù)嘗試各種恢復(fù)命令。芯片單價(jià)不高時(shí)間成本高。鎖死了就換一片把原始問(wèn)題記錄清楚下次燒錄前檢查好配置這才是最提高生產(chǎn)力的路徑。