作者 | strongerHuang
微信公眾號(hào) | strongerHuang
之前從應(yīng)用的角度給大家分享過(guò)Bootloader相關(guān)的文章,今天從底層原理來(lái)給大家描述ARM處理器如何編寫B(tài)ootloader。
1關(guān)于Bootloader
Bootloader顧名思義就是引導(dǎo)加載程序,是在操作系統(tǒng)或應(yīng)用程序運(yùn)行之前的一段程序,是在系統(tǒng)上電后執(zhí)行的一段程序代碼。
BootLoader是嚴(yán)重地依賴于硬件而實(shí)現(xiàn)的,特別是在嵌入式平臺(tái)。因此,在嵌入式平臺(tái)里建立一個(gè)通用的BootLoader幾乎是不可能的。盡管如此,我們?nèi)匀豢梢詫?duì)bootloader歸納出一些通用的概念來(lái),以指導(dǎo)用戶特定的BootLoader設(shè)計(jì)與實(shí)現(xiàn)。
---來(lái)源百度百科
Bootloader在手機(jī)、電腦、眾多嵌入式系統(tǒng)中都存在,它的作用有很多,比如:初始化底層應(yīng)用驅(qū)動(dòng)、加載應(yīng)用程序、更新應(yīng)用程序等。
不同的設(shè)備,Bootloader可能差異很大,通常來(lái)說(shuō)Bootloader比較依賴底層硬件和實(shí)際項(xiàng)目需求。
2如何編寫bootloader
bootloader是一段引導(dǎo)加載程序代碼,它更新用戶的應(yīng)用程序代碼,可以使用很多硬件下載通道(例如USB、網(wǎng)絡(luò)端口)獲得新代碼。
在執(zhí)行引導(dǎo)ROM之后,將執(zhí)行bootloader程序,并在需要時(shí)進(jìn)行更新,然后執(zhí)行最終用戶應(yīng)用程序。
引導(dǎo)加載程序和用戶應(yīng)用程序應(yīng)作為兩個(gè)獨(dú)立的Project或Object進(jìn)行編寫和編譯,從而產(chǎn)生兩個(gè)獨(dú)立且可執(zhí)行的(bin/hex)文件。
引導(dǎo)加載程序的主要任務(wù)是在必要時(shí)對(duì)用戶應(yīng)用程序進(jìn)行重新編程/替換,并跳轉(zhuǎn)至用戶應(yīng)用程序以執(zhí)行該程序,應(yīng)用程序不一定需要知道引導(dǎo)加載程序的存在。
引導(dǎo)加載程序通常位于芯片閃存基址,下面通過(guò)一張圖來(lái)描述內(nèi)存和Flash代碼映射關(guān)系:
有很多方法可以引導(dǎo)bootloader進(jìn)入編程模式,以將用戶應(yīng)用程序重新編程到Flash中,或者直接跳轉(zhuǎn)到現(xiàn)有的用戶應(yīng)用程序來(lái)執(zhí)行。最簡(jiǎn)單的方法是檢查GPIO引腳以確定是否應(yīng)進(jìn)入編程模式。
大多數(shù)芯片供應(yīng)商為用戶提供了一種方便的方式,例如 ISP 和 IAP 接口,bootloader將使用它們來(lái)更新閃存內(nèi)容。
當(dāng)Flash內(nèi)容已更新或已經(jīng)是最新時(shí),引導(dǎo)加載程序?qū)⑻D(zhuǎn)到用戶應(yīng)用程序。在執(zhí)行用戶應(yīng)用程序之前,這需要許多步驟:
1.確保CPU處于特權(quán)模式。
2.禁用NVIC中所有啟用的中斷。
3.禁用所有可能產(chǎn)生中斷請(qǐng)求的使能外設(shè),并清除這些外設(shè)中的所有未使用中斷標(biāo)志。
4.清除NVIC中所有未使用的中斷請(qǐng)求。
5.禁用SysTick并清除其異常掛起位。
6.如果引導(dǎo)加載程序使用了單個(gè)故障處理程序,請(qǐng)禁用它們。
7.如果發(fā)現(xiàn)內(nèi)核當(dāng)前與PSP一起運(yùn)行,則激活MSP(由于編譯器可能仍在使用堆棧,因此在此之前需要將PSP復(fù)制到MSP)。
8.將用戶應(yīng)用程序的向量表地址加載到SCB-》 VTOR寄存器中。確保地址符合對(duì)齊要求。
9.最后一部分是將MSP設(shè)置為用戶應(yīng)用程序向量表中找到的值,然后將用戶應(yīng)用程序的重置向量值加載到PC中,也就是跳轉(zhuǎn)功能。
比如通過(guò)調(diào)用下面的示例BootJump()這樣的函數(shù)來(lái)完成此操作:
static void BootJump(uint32_t *Address){ //1.確保CPU處于特權(quán)模式。 if( CONTROL_nPRIV_Msk & __get_CONTROL()) { /* not in privileged mode */ EnablePrivilegedMode() ; } //2.禁用NVIC中所有啟用的中斷。 Disable_All_Peripherals(); //3.禁用所有可能產(chǎn)生中斷請(qǐng)求的使能外設(shè),并清除這些外設(shè)中的所有未使用中斷標(biāo)志。 NVIC-》ICER[ 0 ] = 0xFFFFFFFF; NVIC-》ICER[ 1 ] = 0xFFFFFFFF; NVIC-》ICER[ 2 ] = 0xFFFFFFFF; NVIC-》ICER[ 3 ] = 0xFFFFFFFF; NVIC-》ICER[ 4 ] = 0xFFFFFFFF; NVIC-》ICER[ 5 ] = 0xFFFFFFFF; NVIC-》ICER[ 6 ] = 0xFFFFFFFF; NVIC-》ICER[ 7 ] = 0xFFFFFFFF; //4.清除NVIC中所有未使用的中斷請(qǐng)求。 NVIC-》ICPR[ 0 ] = 0xFFFFFFFF; NVIC-》ICPR[ 1 ] = 0xFFFFFFFF; NVIC-》ICPR[ 2 ] = 0xFFFFFFFF; NVIC-》ICPR[ 3 ] = 0xFFFFFFFF; NVIC-》ICPR[ 4 ] = 0xFFFFFFFF; NVIC-》ICPR[ 5 ] = 0xFFFFFFFF; NVIC-》ICPR[ 6 ] = 0xFFFFFFFF; NVIC-》ICPR[ 7 ] = 0xFFFFFFFF; //5.禁用SysTick并清除其異常掛起位。 SysTick-》CTRL = 0; SCB-》ICSR |= SCB_ICSR_PENDSTCLR_Msk; //
6.如果引導(dǎo)加載程序使用了單個(gè)故障處理程序,請(qǐng)禁用它們。 SCB-》SHCSR &= ~( SCB_SHCSR_USGFAULTENA_Msk | \ SCB_SHCSR_BUSFAULTENA_Msk | \ SCB_SHCSR_MEMFAULTENA_Msk ) ; //7.如果發(fā)現(xiàn)內(nèi)核當(dāng)前與PSP一起運(yùn)行,則激活MSP if( CONTROL_SPSEL_Msk & __get_CONTROL()) { /* MSP is not active */ __set_MSP( __get_PSP()) ; __set_CONTROL( __get_CONTROL() & ~CONTROL_SPSEL_Msk); } //8.將用戶應(yīng)用程序的向量表地址加載到SCB-》 VTOR寄存器中。 SCB-》VTOR = ( uint32_t )Address ; //9.跳轉(zhuǎn) BootJumpASM( Address[ 0 ], Address[ 1 ]);}
再次說(shuō)明bootloader與底層硬件和實(shí)際需求有關(guān),以上代碼僅供參考,主要是提供思路,方便大家理解。
責(zé)任編輯:haq
-
芯片
+關(guān)注
關(guān)注
452文章
50005瀏覽量
419707 -
ARM
+關(guān)注
關(guān)注
134文章
9009瀏覽量
366098 -
程序
+關(guān)注
關(guān)注
115文章
3749瀏覽量
80670 -
keil
+關(guān)注
關(guān)注
68文章
1209瀏覽量
166457
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論