www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]1 前言在使用F0的片子在增加IAP后,我們經(jīng)常發(fā)現(xiàn),原來的APP必須增加一段代碼,將中斷向量表從內(nèi)部FLASH拷貝到SRAM后再執(zhí)行REMAP到SRAM,這樣操作后APP才能正常運(yùn)行,這一過程一直困擾著蝶粉們,為什么需要這樣呢?本

1 前言

在使用F0的片子在增加IAP后,我們經(jīng)常發(fā)現(xiàn),原來的APP必須增加一段代碼,將中斷向量表從內(nèi)部FLASH拷貝到SRAM后再執(zhí)行REMAP到SRAM,這樣操作后APP才能正常運(yùn)行,這一過程一直困擾著蝶粉們,為什么需要這樣呢?本文將針對這一問題為大家解惑。

2 問題詳細(xì)描述

比如F0的下面這部分代碼:

#defineAPPLICATION_ADDRESS(uint32_t)0x08004000/*Privatemacro-------------------------------------------------------------*//*Privatevariables---------------------------------------------------------*/#if(defined(__CC_ARM))__IOuint32_tVectorTable[48]__attribute__((at(0x20000000)));#elif(defined(__ICCARM__))#pragmalocation=0x20000000__no_init__IOuint32_tVectorTable[48];#elifdefined(__GNUC__)__IOuint32_tVectorTable[48]__attribute__((section(".RAMVectorTable")));#endifintmain(void){uint32_ti=0;HAL_Init();/*Configurethesystemclockto48MHz*/SystemClock_Config();/*RelocatebysoftwarethevectortabletotheinternalSRAMat0x20000000***//*CopythevectortablefromtheFlash(mappedatthebaseoftheapplicationloadaddress0x08004000)tothebaseaddressoftheSRAMat0x20000000.*/for(i=0;i<48;i++){VectorTable[i]=*(__IOuint32_t*)(APPLICATION_ADDRESS+(i<<2));}/*EnabletheSYSCFGperipheralclock*/__HAL_RCC_SYSCFG_CLK_ENABLE();/*RemapSRAMat0x00000000*/__HAL_SYSCFG_REMAPMEMORY_SRAM();/*Addyourowncodehere...*///…}123456789101112131415161718192021222324252627282930313233343536373839123456789101112131415161718192021222324252627282930313233343536373839

如上所示,在沒有加入IAP之前這部分代碼不需要的,而加入IAP后,這部分代碼在F0中就必須添加了,不然APP會(huì)運(yùn)行部正常! 從代碼中可以看出,增加的代碼執(zhí)行了從內(nèi)部FLASH中拷貝中斷向量表到內(nèi)存,然后重映射SRAM,可是,蝶粉們不禁要問,為什么要這么操作?這個(gè)又是什么原因造成的?

3 原因分析
3.1 重映射

在搞懂這個(gè)問題之前我們首先先來看看什么是重映射。例如F072的參考文檔張SYSCFG寄存器的介紹,如下圖:

MEM_MODE的介紹如下:

從以上內(nèi)容我們可以得到以下信息:
1. MEM_MODE的值在上電后有BOOT0,BOOT1的狀態(tài)值決定。
2. MEM_MODE的值決定了哪個(gè)內(nèi)存映射到地址0x0000 0000
也就是說:
? 當(dāng)MEM_MODE =00/10時(shí),Main Flash映射到地址0x0000 0000,即地址0x0800 0000映射到0x0000 0000.
? 當(dāng)MEM_MODE =01時(shí),System Flash映射到地址0x0000 0000,也就是芯片自帶的Bootloader代碼部分會(huì)映射到地址0x0000 0000,即0x1FFF C800映射到地址0x0000 0000.
? 當(dāng)MEM_MODE =11時(shí),Embeded SRAM映射到地址0x0000 0000,也就是內(nèi)存地址0x2000 0000映射到地址0x0000 0000.
3. 經(jīng)過映射后,系統(tǒng)訪問地址0x0000 0000地址,就相當(dāng)于直接訪問映射的地址,如0x0800 0000.
4. 由BOOT0,BOOT1的狀態(tài)決定MEM_MODE的值,進(jìn)而決定哪個(gè)地址映射到地址0x0000 0000,這一過程我們稱之為映射。默認(rèn)映射是系統(tǒng)自動(dòng)完成的,并由BOOT0,BOOT1的狀態(tài)決定。
5. MEM_MODE位是RW的,也就是說可以修改的,如果修改其中,也就會(huì)相應(yīng)的修改映射到0x0000 0000的地址,這一修改的過程,我們就叫其為重映射。重映射是通過用戶代碼通過修改MEM_MODE的值來完成的。

3.2 系統(tǒng)啟動(dòng)

從STM32F072的參考手冊的2.5章,我們可以看到如下內(nèi)容:

從以上內(nèi)容我們可以得到以下有用信息:
1. 在復(fù)位啟動(dòng)后,系統(tǒng)在系統(tǒng)時(shí)鐘的第4個(gè)上升沿根據(jù)BOOT0,BOOT1的配置獲取其值,也就是存儲到寄存器SYSCFG_CFGR1的MEM_MODE位上,根據(jù)前面3.1的信息可知,這里進(jìn)一步確定了0x0000 0000的映射地址。這一過程是系統(tǒng)自動(dòng)完成的。
2. 在系統(tǒng)啟動(dòng)后,CPU從地址0x0000 0000獲取棧頂?shù)刂?,然后?x0000 0004開始執(zhí)行代碼。換句話說,由于0x0000 0000被映射了其他地址,獲取棧頂與執(zhí)行實(shí)際上都是從映射的地址上實(shí)施的。也就是從映射的地址開始執(zhí)行代碼,比如從地址0x08000 0004開始執(zhí)行代碼(如Mian Flash映射),比如0x1FFF C804(如System Flash映射,即BootLoader啟動(dòng)).
于是,我們簡單整理下系統(tǒng)的整個(gè)啟動(dòng)流程:
-> 系統(tǒng)復(fù)位
-> CPU在系統(tǒng)時(shí)鐘的第4個(gè)上升沿根據(jù)BOOT0,BOOT1的配置確定寄存器SYSCFG_CFGR1的MEM_MODE的值
-> MEM_MODE進(jìn)一步?jīng)Q定哪個(gè)地址(Main Flash,System Flash,SRAM)映射到地址0x0000 0000.
-> CPU從地址0x0000 0000獲取棧頂,從0x0000 0004開始執(zhí)行代碼,也就是從映射地址獲取棧頂,從映射地址+4的地方開始執(zhí)行代碼。
->映射地址+4對于著復(fù)位中斷例程(如0x08000 0004),也就是系統(tǒng)一開始就執(zhí)行Reset_Handler,進(jìn)而運(yùn)行SystemInit然后進(jìn)入到main函數(shù),就這樣,整個(gè)代碼啟動(dòng)完成。

接下來就是中斷產(chǎn)生于中斷響應(yīng)了。

3.3 中斷與中斷向量表

從ARM官網(wǎng)上的信息得知(http://infocenter.arm.com/help/index.jsp),在Coretext-M3與Coretext-M4核中,在System Control Block中存在一個(gè)向量表偏移量寄存器 VTOR(0xE000ED08),系統(tǒng)產(chǎn)生中斷后,內(nèi)核通過這個(gè)寄存器的值來找到中斷向量表的地址,進(jìn)而執(zhí)行中斷例程代碼,當(dāng)然,此寄存器的值是可以修改的,它的默認(rèn)值為0。實(shí)際上在大部分的M3和M4的工程中,一般都是在SystemInit函數(shù)中對此寄存器的值進(jìn)行設(shè)置,當(dāng)此之前,它的值為默認(rèn)值0,由于映射關(guān)系,實(shí)際上就是指向映射地址,比如0x0800 0000. 如下圖所示:

但是,由于STM32F0XX采用的是M0核,它是沒有這個(gè)VTOR寄存器的,那么它又是怎么找到中斷向量表的地址的呢?同樣在ARM官網(wǎng)上我們找到如下信息:

也就是說,對于M0來說,中斷向量表的地址固定在地址0x0000 0000上!
對此,我們也可以這么理解,將M0理解成M3/M4的特殊情況,M0假設(shè)也存在VTOR這么一個(gè)虛擬寄存器,只不過它的值不能修改,固定為0罷了,而M3/M4的這個(gè)VTOR寄存器一開始時(shí)它的值也是為默認(rèn)值0,只不過在程序運(yùn)行到SystemInit()函數(shù)后,在代碼中明確對其進(jìn)行了修改。

我們整理下STM32F0XX中斷的調(diào)用過程:
-> 產(chǎn)生中斷
-> CPU固定到地址0x0000 0000上找中斷入口函數(shù),由于映射關(guān)系,實(shí)際上是在從映射地址上尋找。
-> 找到并執(zhí)行中斷例程

此時(shí),可以回到我們一開始的問題上來了.

3.4 回到問題分析3.4.1 從IAP跳轉(zhuǎn)到APP的過程分析

從IAP跳轉(zhuǎn)到APP時(shí)到底發(fā)生了什么呢?首先我們來看看這個(gè)跳轉(zhuǎn)代碼:

/*Testifusercodeisprogrammedstartingfromaddress"APPLICATION_ADDRESS"*/if(((*(__IOuint32_t*)APPLICATION_ADDRESS)&0x2FFE0000)==0x20000000){/*Jumptouserapplication*/JumpAddress=*(__IOuint32_t*)(APPLICATION_ADDRESS+4);JumpToApplication=(pFunction)JumpAddress;/*Initializeuserapplication'sStackPointer*/__set_MSP(*(__IOuint32_t*)APPLICATION_ADDRESS);JumpToApplication();}12345678910111234567891011

如上,首先測試APP地址是否存在用戶代碼,如果存在,則首先將APPLICATION_ADDRESS + 4,作為跳轉(zhuǎn)地址,然后從APPLICATION_ADDRESS取棧頂并賦值給SP寄存器,最后跳轉(zhuǎn)。

于是我們可以得出結(jié)論:
跳轉(zhuǎn)代碼后,PC指針變了,SP棧指針也修改了,但是,中斷向量表的位置并沒有修正為APP的中斷向量表位置,還是采用IAP的中斷向量表位置。如果此時(shí)系統(tǒng)產(chǎn)生中斷,CPU還會(huì)固定從0x0000 0000地址中去找中斷入口,由于從IAP到APP,內(nèi)存映射并沒有改變,因此,實(shí)際上還是從0x0800 0000上去找中斷入口,也就是還是在IAP的中斷向量表上尋找,繼續(xù)執(zhí)行IAP的中斷例程,進(jìn)而引發(fā)hard fault,這顯然不是我們想要的。

3.4.2 問題分析

這里的關(guān)鍵是,如何將中斷向量表的尋找位置從0x0800 0000修改到0x0800 3000(假設(shè)為APP的地址)? 從之前的分析我們可以得出有兩種方法:
1 修改寄存器VTOR的值
2 內(nèi)存重映射
M3/M4核的MCU顯然采用了第一種方法,因此,在M3/M4的MCU上,即使添加了IAP,也不需要增加本文第二章所描述的代碼。而這部分代碼,正是M0采用的第二種方法,也是唯一可以修改尋找中斷向量方式的方法。

通過將SRAM

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

在C語言的世界里,main函數(shù)扮演著無比重要的角色,它是每個(gè)C程序的起點(diǎn)和終點(diǎn)。每當(dāng)一個(gè)C程序被編譯并運(yùn)行時(shí),main函數(shù)都是第一個(gè)被執(zhí)行的函數(shù)。理解main函數(shù)的原理,對于深入學(xué)習(xí)C語言乃至整個(gè)計(jì)算機(jī)科學(xué)的底層機(jī)制都至...

關(guān)鍵字: C語言 main函數(shù)

程序員入門進(jìn)階 我 們在剛寫程序的時(shí)候,第一個(gè)都是 hello world。

關(guān)鍵字: C語言 main函數(shù)

  賽普拉斯半導(dǎo)體公司日前宣布,卡西歐創(chuàng)新型的自由式相機(jī)采用了其TrueTouch®電容式觸摸屏控制器和靜態(tài)隨機(jī)存取存儲器(SRAM)產(chǎn)品。Casio EX-FR10相機(jī)的鏡頭可以與觸摸

關(guān)鍵字: casio sram 觸摸屏控制器 賽普拉斯 ex-fr10

Cypress公司的FM4 S6E2C系列是基于ARM® Cortex®-M4的高度集成的32位MCU, 集成了閃存和SRAM,以及包括馬達(dá)控制計(jì)時(shí)器,ADC和通信接口(USB,

關(guān)鍵字: MCU sram cypress公司

SRAM不需要刷新電路即能保存它內(nèi)部存儲的數(shù)據(jù)。SRAM存儲器具有較高的性能,但是SRAM芯片也有它的缺點(diǎn),即它的集成度較低,功耗較DRAM大。

關(guān)鍵字: sram 存儲數(shù)據(jù) 電路

ISSI在存儲器芯片領(lǐng)域享有無與倫比的美譽(yù)。

關(guān)鍵字: DRAM nor閃存 sram

什么是FPGA ?它的器件結(jié)構(gòu)組成有哪些?

關(guān)鍵字: Flash sram 可編程邏輯

C語言標(biāo)準(zhǔn)在一開始(C90標(biāo)準(zhǔn) 5.1.2條),就規(guī)定了程序的執(zhí)行環(huán)境。對于沒有操作系統(tǒng)的環(huán)境來說,C程序的入口函數(shù)是什么都可以(也就是說的在單片機(jī)的C程序里,或者在操作系統(tǒng)的底層代碼的C入口處,不需要是main函數(shù))。

關(guān)鍵字: C語言 main函數(shù) 基礎(chǔ)教程 基礎(chǔ)知識

Ⅰ、概述關(guān)于SPI(Serial Peripheral Interface)串行外設(shè)接口可以說是單片機(jī)或者嵌入式軟件開發(fā)人員必須掌握的一項(xiàng)通信方式,就是你在面試相關(guān)工作的時(shí)候都可能會(huì)問及這個(gè)問題。在這里問一個(gè)簡單的問題:...

關(guān)鍵字: Flash stm32f0xx spi讀寫

最近本人在學(xué)習(xí)ARM7的遠(yuǎn)程升級,在這里將自己的學(xué)習(xí)過程與大家分享,有錯(cuò)誤的地方還請大家指出便于改正! ISP(In-System Programming)即“在系統(tǒng)可編程”,指電路板...

關(guān)鍵字: iap isp
關(guān)閉