bootloader学习笔记---第二篇
目錄
一、鏈接地址與跳轉(zhuǎn)
二、bootloader疑難問題
1、應(yīng)用程序中使用中斷導(dǎo)致程序跑飛或者不能重新下載程序?
2、中斷向量表具體是怎么重映射?
3、bootloader更新app過程中意外斷電,怎么處理?流程是先備份后擦出然后燒寫嗎?
4、botloader燒寫app程序過程中突然斷電或者斷開連接導(dǎo)致bootloader無法使用,必須重新燒寫,這是什么原因呢?
5、怎么將BOOT程序和APP程序一起燒進(jìn)板子?
6、第一,多核芯片是否給每個核編寫一個bootloader,并分別放在每個核相應(yīng)的flash里?第二,上位機軟件下發(fā)的信息是否可以通過ID來區(qū)分送到哪個核里?第三,上位機軟件是不是必須和CAN盒子配套?
?7、bootloader升級過程很慢,100k左右的s19文件需要十多分鐘?
8、boot程序,對于app的跳轉(zhuǎn)地址有什么要求?boot程序比較大,跳轉(zhuǎn)地址是0x25000,跳轉(zhuǎn)總是失敗?
9、可以直接從APP區(qū)域跳轉(zhuǎn)到到BOOT區(qū)域直接升級,而不用經(jīng)過一個重啟的過程嗎?正常項目都是APP啟動升級的
10、boot 更新app的時候,將flash drv(擦除,寫入等風(fēng)險操作函數(shù))臨時通過can從上位機下載到ram中并運行,通過修改鏈接文件指定自定義的一塊ram,可以把收到的flash drv的數(shù)據(jù)放到這塊地址,在執(zhí)行擦除或者寫入操作時,1.怎么找到擦除或?qū)懭牒瘮?shù)的ram地址并執(zhí)行?2.如果可以找到地址,怎么往擦除或?qū)懭牒瘮?shù)傳遞參數(shù)(這兩個函數(shù)知道ram地址,不是函數(shù),怎么傳遞參數(shù))?
11、將地址強制轉(zhuǎn)換為函數(shù)指針調(diào)用,會造成hard fault interrupt?
三、備注
一、鏈接地址與跳轉(zhuǎn)
這里討論第一篇文章中提到的第二種情況,即第二種常見的情況就是app燒寫在flash上,app應(yīng)該在ram內(nèi)存里運行,app或者是bootloader需要把app拷貝到內(nèi)存ram中去,1、如果是bootloader拷貝的,那么bootloader要跳轉(zhuǎn)到內(nèi)存ram中去執(zhí)行app;2、如果是app自己把自己復(fù)制到內(nèi)存中去的,那么bootloader直接跳轉(zhuǎn)到app的位置就可以了。
這里有三個問題,1、誰把app從flash復(fù)制到ram中去?2、具體是復(fù)制到哪里?3、如果bootloader要跳轉(zhuǎn)到ram中去怎么跳?
第一個問題,app自我復(fù)制,bootloader幫忙復(fù)制;第二個問題,這個地址我們可以預(yù)先設(shè)置好;第三個問題,用函數(shù)指針跳轉(zhuǎn)。
下面介紹兩種跳轉(zhuǎn)方式。
第一、相對跳轉(zhuǎn),BL main; 這是條匯編語句,這條語句會讓pc=當(dāng)前pc+相對位移。不管我們程序放在哪里,相對跳轉(zhuǎn)都能成功。編譯器是默認(rèn)優(yōu)先使用相對跳轉(zhuǎn)。
?
第二、絕對跳轉(zhuǎn),是讓pc=要跳轉(zhuǎn)的地址。比如,LDR r5 , [pc, #24]? ? ?BLX r5。函數(shù)指針的方式也是絕對跳轉(zhuǎn)的方式。對于絕對跳轉(zhuǎn),在對應(yīng)的地址上面必須有對應(yīng)的代碼。stm32上電后第二件事情就是跳轉(zhuǎn)到Reset_Handler中去,這也是絕對跳轉(zhuǎn)。如果是長距離調(diào)用,也會使用絕對跳轉(zhuǎn)。如果是絕對跳轉(zhuǎn),我們程序燒錄的位置如果發(fā)生變化,即我們燒錄的地址和鏈接文件(散列文件)中指定的地址不一致,那么跳轉(zhuǎn)過去的地址就會出現(xiàn)錯誤,因為跳轉(zhuǎn)的絕對地址的那塊內(nèi)存可能沒有初始化,程序會崩潰。
散列文件?
如果我們?nèi)缟蠄D那樣使用散列文件修改了app程序的鏈接地址,那么app程序會把指令和數(shù)據(jù)放在0x20000000。那么這相當(dāng)于,bootloader跳轉(zhuǎn)到app中,app自己把自己復(fù)制到0x20000000??梢钥吹缴⒘形募?#xff0c;鏈接地址和加載地址都是同一個地址,鏈接地址就是運行時的地址,我們可以使用燒錄工具來決定程序的燒錄地址,在這里加載地址沒有用,只有鏈接地址有用。
?上面的代碼是app自己復(fù)制自己到內(nèi)存的
第二種情況,需要bootloader把app復(fù)制到內(nèi)存中去時,app文件的頭部一般會包含以下幾種信息,1、加載地址:即要拷貝到內(nèi)存的那個地址,2、入口地址:即第一條指令地址,3、長度,4、CRC。
這就需要bootloader啟動后需要去app的燒錄地址讀取這些頭部信息,接著解析這些頭部信息,然后讀取app.bin存入內(nèi)存,最后跳轉(zhuǎn)到內(nèi)存中去執(zhí)行app程序。
解析頭部信息,需要注意的是,存儲方式是大字節(jié)序還是小字節(jié)序,
這里我補充一個知識點:我們在對flash進(jìn)行讀寫操作時,flash中對應(yīng)的應(yīng)用程序文件將不能運行,所以必須將flash driver拷貝到ram區(qū)域,這是由flash的硬件性質(zhì)決定的,為什么呢?
因為,flash只有一套自己的crossbar(類似交叉開關(guān),同一時刻只能執(zhí)行一種操作)訪問總線,當(dāng)其被用作寫數(shù)據(jù)時,不能同時讀取數(shù)據(jù)(譬如CPU取指執(zhí)行程序)。但在支持RWW partition的flash中是不必如此操作的,它支持在不同flash分區(qū)同時進(jìn)行讀和寫。
二、bootloader疑難問題
1、應(yīng)用程序中使用中斷導(dǎo)致程序跑飛或者不能重新下載程序?
這個要看具體的MCU(內(nèi)核),一個原則是使能中斷和異常發(fā)生之前必須確保其中斷向量表和中斷/異常ISR已經(jīng)ready。
2、中斷向量表具體是怎么重映射?
更改向量表基地址寄存器,也叫中斷向量表偏移量寄存器,中斷向量表的重定向可以是在bootloader進(jìn)入用戶程序之前改,也可以在用戶程序里面改,對于在Cortex-M3內(nèi)核的MCU上可以通過設(shè)置SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET,關(guān)于這個寄存器的描述可以見下圖;該寄存器的值來實現(xiàn)中斷向量表的重定義。如果沒有這類的寄存器可以參考這位博主的辦法嘗試解決STM32F0芯片IAP實現(xiàn)之中斷向量表重映射(沒有中斷向量表偏移寄存器SCB->VTOR的應(yīng)對方法)_a只如初見的博客-CSDN博客_中斷重映射
3、bootloader更新app過程中意外斷電,怎么處理?流程是先備份后擦出然后燒寫嗎?
一般是雙應(yīng)用程序分區(qū),更新完新的應(yīng)用程序之后才擦除老的應(yīng)用程序分區(qū)并設(shè)置跳轉(zhuǎn)標(biāo)志,以保證時鐘有一個分區(qū)中的應(yīng)用程序正確可用。
4、botloader燒寫app程序過程中突然斷電或者斷開連接導(dǎo)致bootloader無法使用,必須重新燒寫,這是什么原因呢?
如果應(yīng)用程序新過程中斷電或者意外復(fù)位,則應(yīng)用程序更新失敗,相應(yīng)的應(yīng)用程序完整性校驗通不過,當(dāng)然得重新下載,為了避免這種情況下應(yīng)用程序丟失,常常BootLoader需要對應(yīng)用程序進(jìn)行雙備份,即使用兩個不同的NVM分區(qū)來保存應(yīng)用程序,只有新的應(yīng)用程序更新成功之后,才擦除老的應(yīng)用程序。
5、怎么將BOOT程序和APP程序一起燒進(jìn)板子?
用任意文本編輯器打開bootloader和app工程生成的S19文件拷貝即可合并,然后使用調(diào)試器通過SWD/JTAG接口下載即可。
6、第一,多核芯片是否給每個核編寫一個bootloader,并分別放在每個核相應(yīng)的flash里?第二,上位機軟件下發(fā)的信息是否可以通過ID來區(qū)分送到哪個核里?第三,上位機軟件是不是必須和CAN盒子配套?
多核MCU只需要為其boot CPU core開發(fā)一個bootloader就可以了,可以通過ID或者地址來判斷,可以復(fù)用我們的上位機軟件,但其只有簡單功能,要用這個上位機軟件需要使用匹配的CAN適配器,否則需要修改底層dll以適用于其他CAN適配器
?7、bootloader升級過程很慢,100k左右的s19文件需要十多分鐘?
Flash擦除本身很耗時間,另外,可以在將S19文件每行的數(shù)據(jù)設(shè)置為更長(比如128字節(jié)或者512字節(jié))或者把bootloader里面改為接收10行s19再燒寫,提高Flash燒寫效率,再或者就是提高通信速率
8、boot程序,對于app的跳轉(zhuǎn)地址有什么要求?boot程序比較大,跳轉(zhuǎn)地址是0x25000,跳轉(zhuǎn)總是失敗?
這個要看跳轉(zhuǎn)具體是如何實現(xiàn)的?要反匯編看看具體的匯編跳轉(zhuǎn)指令,不同的匯編跳轉(zhuǎn)指令支持的跳轉(zhuǎn)地址范圍不同。
9、可以直接從APP區(qū)域跳轉(zhuǎn)到到BOOT區(qū)域直接升級,而不用經(jīng)過一個重啟的過程嗎?正常項目都是APP啟動升級的
可以在APP中接收到boot請求后使用函數(shù)指針直接跳轉(zhuǎn)到bootloader的reset_handler,但需要在跳轉(zhuǎn)之前反初始化/復(fù)位APP使用的所有時鐘和外設(shè),以避免APP與bootloader的相互影響。當(dāng)然,我們推薦的方式還是軟件復(fù)位或者看門狗溢出復(fù)位進(jìn)入bootloader。
10、boot 更新app的時候,將flash drv(擦除,寫入等風(fēng)險操作函數(shù))臨時通過can從上位機下載到ram中并運行,通過修改鏈接文件指定自定義的一塊ram,可以把收到的flash drv的數(shù)據(jù)放到這塊地址,在執(zhí)行擦除或者寫入操作時,1.怎么找到擦除或?qū)懭牒瘮?shù)的ram地址并執(zhí)行?2.如果可以找到地址,怎么往擦除或?qū)懭牒瘮?shù)傳遞參數(shù)(這兩個函數(shù)知道ram地址,不是函數(shù),怎么傳遞參數(shù))?
第1個問題,使用函數(shù)查找表,類似中斷向量表的工作原理;第2個問題使用函數(shù)指針,因為函數(shù)名本身就是地址,我們可以定義一個和flash drv相同格式的函數(shù)指針,然后向這個函數(shù)指針傳遞的參數(shù)就是傳遞給了flash drv函數(shù);
11、將地址強制轉(zhuǎn)換為函數(shù)指針調(diào)用,會造成hard fault interrupt?
typedef void(*pfun_t)(void);pfun_t pfun = (pfun_t)0x00500000; pfun();注意是把中斷向量(中斷ISR函數(shù)地址,存在中斷向量表地址的內(nèi)容)而不是中斷向量地址本身轉(zhuǎn)換成函數(shù)指針執(zhí)行。
三、備注
本文部分內(nèi)容是根據(jù)韋東山老師的視頻整理編寫的筆記從0寫B(tài)ootLoader(適用于單片機),還有部分公眾號中汽車電子expert成長之路的文章評論,部分圖片來自于cortex-m3權(quán)威指南。
=文檔信息=
本學(xué)習(xí)筆記由博主整理編輯,僅供非商用學(xué)習(xí)交流使用
由于水平有限,錯誤和紕漏之處在所難免,歡迎大家交流指正
如本文涉及侵權(quán),請隨時留言博主,必妥善處置
版權(quán)聲明:非商用自由轉(zhuǎn)載-保持署名-注明出處
總結(jié)
以上是生活随笔為你收集整理的bootloader学习笔记---第二篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 七十七、java版商城之直播短视频带货S
- 下一篇: Unity项目设置