問題
某客戶在其產品的設計中,使用了STM32F091RCT6。客戶使用ST-Link 對STM32F091RCT6 進行編程,發現對空片進行編程之后,必須要重新上電才能運行用戶代碼;但是如果不是空片,則編程后就可以直接運行用戶代碼。由于客戶的測試系統是直接燒寫完芯片后在不斷電的情況直接進入測試模式,如果空片燒寫需要斷電的話,帶來一定的麻煩。客戶希望搞明白這件事,并希望找到辦法,能在空片編程后也可以直接運行用戶代碼。
調研
1.還原問題
在這里,使用帶有STM32F091RCT6 的NUCLEO-F091RC 板來進行問題還原,將此Nucleo 板通過USB 線連接到電腦。打開STM32 ST-LINK Utility,點擊“Connect to the target”按鈕進行芯片連接,連接后打開一個準備好的LED 燈閃爍的.hex 文件代碼,點擊“Program verify”按鈕準備進行編程。
在這里,我們勾選了“Reset after programming”,目的在于編程后對芯片進行復位,可以運行用戶代碼。然后點擊“Start”按鈕開始進行編程。
編程之后,按道理可以看到LED 燈閃爍的,但是并沒有出現。需要給MCU進行斷電后,重新上電才能看到LED 燈閃爍。也就是說需要一次上電復位才能運行用戶代碼。
2.分析問題
先來回顧一下STM32F091 的參考手冊RM0091 對于Empty Check 的描述:
首先,芯片內部存在一個查空標志,用來標志芯片是否為空片。這個標志位是在BOOT0 腳被定義到從Main Flash memory 啟動的時候使用。當這個標志位被置“1”的時候,此芯片被認為是空的,系統將從Systemmemory 中啟動Bootloader,以允許用戶進行代碼下載,即使現在BOOT0腳定義的是從Main Flash memory 啟動。此標志位只在載入Option bytes 時更新:當地址0x0800 0000 讀出的內容為0xFFFF FFFF 時,此標志位置“1”,否則為“0”。這意味著當燒寫完一個空片后需要在系統復位后執行用戶代碼的話,是必須要重新上電以產生或者在FLASH_CR寄存器中置位OBL_LAUNCH 來啟動Optionbyteloader reset,以清除此查空標志。
現在就可以來分析目前所遇到的情況了:
當空片通過SWD 連接到ST-Link 進行燒寫的情況下,由于上電時空片檢測檢測到此芯片為空片,查空標志被置位,所以系統此時從System memory 中啟動Bootloader 開始運行。通過簡單的SWD 接口對芯片進行編程,勾選的“Reset afterprogramming”將在編程結束后在RESET引腳上產生一個復位信號,但是不幸的是這個復位并不能清除查空標志,導致復位后仍然從System memory 中啟動Bootloader,而沒有運行用戶代碼,也就是我們之前遇到的現象。
一般情況下,我們都可以通過重新上電來產生POR 以清除查空標志,從MainFlash memory 啟動運行用戶代碼。但是,客戶目前的這種特殊需求就會帶來一定的麻煩。還有一種應用也會比較麻煩,也就是使用鋰電池的產品,而且這個電池直接焊接到用戶板上,無法方便地進行斷電上電。此時,若是空片是焊接在板子上進行在線編程,那么,問題來了。空片編程之后,由于不方便進行斷電,而無法完成POR的動作,不能運行用戶代碼也就無法實現一個Option byte loader reset。查空標志無法清除,程序運行將鎖死在System memory 的Bootloader。
3.問題解決
這種問題呢,解決方法當然有很多種,下面來大概地探討一下:
1) 從生產上來解決:芯片在編程器上進行單獨編程,之后再上板子,避開空片燒寫后沒有POR。
2) 從硬件上來解決:使用一個跳線,或者使用其他方式,比如在夾具上想辦法,以達到通過人工的斷電再連通上電,實現一個POR。需要在PCB 板上預留。大家可自行選擇對策。但是這會增加生產上的麻煩,降低效率。
3) 從編程方法來解決:不使用ST-Link 進行編程,直接使用Bootloader 進行串口升級,升級后跳轉到Main Flashmemory 去運行用戶代碼。需要在用戶代碼中加入將MainFlash memory 映射到0x0000 0000 的代碼。
4) 前面幾種方式大家一看就明白如果去解決了。但是,如果一定要使用ST-Link 通過SWD 進行燒寫的話,就另當別論,我們下面來探討這種方式。
一般看到這種問題,直觀思維就是思考是否有辦法,可以在ST-LINK 燒寫后通過一定的ST-LINK命令跳轉到用戶代碼去運行用戶代碼。方法看起來可行,但是有點復雜。第一,STM32 ST-LINKUtility 沒有提供類似的功能,需要用戶自行使用ST-LINK_CLI 命令;第二,需要在用戶代碼中加入別忘了將MainFlash memory 映射到0x0000 0000 的代碼;第三,由于查空標志未清除,需擔心意外的復位信號或干擾,導致復位后又跑回SystemMemory,還需要在用戶代碼中加入“每次運行都判斷是否為OptionBytes Loader reset,如果不是,就直接執行一次Option BytesLoader reset以清除查空標志”。
我們的直觀思維都是出現問題解決問題,但是看了上面的描述,這樣的解決辦法還真有點麻煩。那有沒有什么其他簡單的辦法呢?答案是有的,我們不要把思維停留在出現問題解決問題上,而是如何去避免產生問題。下面來理一理思路:
這個問題的根源在于查空標志的存在,所以需要思考的是怎么避免查空標志的影響?
來看一下查空標志產生的條件:
a) 使用了BOOT0 引腳;
b) BOOT0 引腳為低電平,啟動區域指向MainFlash memory;
c) 讀取0x0800 0000 地址的值為0xFFFF FFFF;
由于是空片編程,所以第三種條件是肯定是成立的;由于硬件設計,BOOT0 引腳的電平也不方便改來改去;所以需要把關注點放在第一個條件上——“使用了BOOT0 引腳”。由于STM32F091的特性,剛好有機會可以不使用BOOT0 引腳,而是直接使用選項字節,所以解決的辦法有了。
步驟如下:
i. 打開STM32 ST-LINK Utility,點擊“Connect to the target”按鈕進行連接;
ii. 從菜單“Target → Option Bytes”調出選項字節對話框
將“nBoot0_SW_Cfg”的打勾去掉,點擊“Apply”,改成使用選項字節中的nBoot0 和nBoot1 來控制啟動區域
iii. 再打開需要燒寫的代碼文件,點擊“Program Verify”按鈕,對話框中勾選“Reset after programming”,點擊“Start”完成燒寫動作就可以了。
這樣就可以看到用戶代碼已經在運行了,是不是很簡單。
如果,希望更簡單的完成,可以使用ST-LINK_CLI,寫一個批處理文件,包含以下動作:
ST-LINK_CLI -c SWD UR
ST-LINK_CLI -ME
ST-LINK_CLI -p xxxxxxxx.hex-v “while_programming”
ST-LINK_CLI -OBnBOOT0_SW_Cfg=0
ST-LINK_CLI –Rst
ST-LINK_CLI.exe位于STM32 ST-LINK Utility 安裝目錄里,關于命令請參考《ST-LINKUtility UM.pdf》。
結論
由于查空檢測機制,導致STM32F091 空片在使用ST-LINK編程后,不斷電的情況下復位將回到System Memory,無法進入MainFlash memory 去運行用戶代碼。所以,在特殊應用中,如果無法進行斷電再上電,需要使用辦法對這種機制進行破壞。
處理
將Boot 啟動配置為用選項字節進行控制,而不是使用Boot0引腳,以此來破壞查空機制的影響。
建議
對于問題的解決,一般從兩個方向進行思考:一是出現了問題再來找解決問題的辦法;二是如何避免出現問題。很多時候,由于思維慣性,很多工程師可能會更喜歡直接從第一種方向去思考問題;然而,事實上,如果能從第二種方向思考,阻止問題的產生,那才是最好的辦法。
-
STM32
+關注
關注
2270文章
10910瀏覽量
356649 -
STM32F091
+關注
關注
0文章
4瀏覽量
3344
原文標題:STM32F091空片編程后不能直接運行用戶代碼
文章出處:【微信號:STM32_STM8_MCU,微信公眾號:STM32單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論