




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、三、STM32STM32 堆棧區(qū)預(yù)備知識:一個(gè)由C/C+編譯的程序占用的內(nèi)存分為以下幾個(gè)部分:棧區(qū)(stack):編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。堆區(qū)(heap):一般由程序員分配釋放,若程序員不釋放,程序結(jié)束日可能由OS回收。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表。全局區(qū)(靜態(tài)區(qū))(static):全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。程序結(jié)束后由系統(tǒng)釋放。文字常量區(qū)一常量字符串就是放在這里的。程序結(jié)束后由系統(tǒng)釋放程序代碼區(qū)一存放
2、函數(shù)體的二進(jìn)制代碼編譯后,各個(gè)區(qū)存儲內(nèi)容舉例說明如下:/main.cppinta=0;全局初始化區(qū)char*p1;全局未初始化區(qū)main()intb;棧chars=abc;棧char*p2;棧char*p3=123456”;1234560在常量區(qū),p3在棧上staticintc=0;全局(靜態(tài))初始化區(qū)p1=(char*)malloc(10);p2=(char*)malloc(20);分配得來得 1010 和 2020 字節(jié)的區(qū)域就在堆區(qū)。strcpy(p1,123456”);1234560放在常量區(qū),編譯器可能會將它與p3所指向的123456優(yōu)化成一個(gè)地方。)STM32的分區(qū)STM32的分區(qū)
3、從0 x20000000(0 x20000000是SRAM的起始地址,由此可知,堆棧等都是在RAM中的)開始。靜態(tài)區(qū),堆,棧。所有的全局變量,包括靜態(tài)變量之類的,全部存儲在靜態(tài)存儲區(qū)。緊跟靜態(tài)存儲區(qū)之后的,是堆區(qū)(如沒用到malloc,則沒有該區(qū)),之后是棧區(qū),棧在程序中存儲局部變量。先看啟動文件startup_stm32f10 x_md.s的定義:;Amountofmemory(inbytes)allocatedforStack;Tailorthisvaluetoyourapplicationneeds;StackConfiguration;StackSize(inBytes);Stack_
4、SizeEQU0 x00000400AREASTACK,NOINIT,READWRITE,ALIGN=3Stack_MemSPACEStack_Size_initial_sp;HeapConfiguration;HeapSize(inBytes);Heap_SizeEQU0 x00000200AREAHEAP,NOINIT,READWRITE,ALIGN=3_heap_baseHeap_MemSPACEHeap_Size_heap_limit這里定義了堆棧各自大小,堆:512bytes512bytes 棧 1k;1k;所以棧區(qū)大小有限制,我們在局部變量中不要定義大數(shù)組否則容易溢出。再看下cod
5、erorwziCode指存儲到flash【Rom】中的程序代碼。ZI英語是zeroinitial,就是程序中用到的變量并且被系統(tǒng)初始化為 0 0 的變量的字節(jié)數(shù),keil編譯器默認(rèn)是把你沒有初始化的變量都賦值一個(gè) 0,0,這些變量在程序運(yùn)行時(shí)是保存在RAMRAM 中的。RW是可讀可寫變量,就是初始化時(shí)候就已經(jīng)賦值了的,RW+ZI就是你的程序總共使用的 RAMRAM 字節(jié)數(shù)。RO是程序中的指令和常量,這些值是被保存到 RomRom 中的。TotalROMSize(Code+ROData+RWData)這樣所寫的程序占用的ROM的字節(jié)總數(shù),也就是說程序所下載到ROMflash中的大小。為什么Rom
6、中還要存RW,因?yàn)榈綦姾驲AM中所有數(shù)據(jù)都丟失了,每次上電 RAMRAM 中的數(shù)據(jù)是被重新賦值的,每次這些固定的值就是存儲在 RomRom 中的,為什么不包含ZI段呢,是因?yàn)閆I數(shù)據(jù)都是0,沒必要包含,只要程序運(yùn)行之前將ZI數(shù)據(jù)所在的區(qū)域一律清零即可。包含進(jìn)去反而浪費(fèi)存儲空間。實(shí)際上,ROM中的指令至少應(yīng)該有這樣的功能:1 .將RW從ROM中搬到RAM中,因?yàn)镽W是變量,變量不能存在ROM中。2.將ZI所在的RAM區(qū)域全部清零,因?yàn)閆I區(qū)域并不在Image中,所以需要程序根據(jù)編譯器給出的ZI地址及大小來將相應(yīng)得RAM區(qū)域清零。ZI中也是變量,同理:變量不能存在ROM中。1,1,首先來看:棧(S
7、TACK)(STACK)的問題. .函數(shù)的局部變量,都是存放在“棧”里面,棧的英文是:STACKoSTACK的大小,我們可以在stm32的啟動文件里面設(shè)置,在startup_stm32f10 x_hd.s里面,開頭就有:Stack_SizeEQU0 x00000800表示棧大小是0X800,也就是2048字節(jié),這樣,CPU處理任務(wù)的時(shí)候,函數(shù)局部變量過多可占用的大小就是:2048字節(jié)。注意:是所有在處理的函數(shù),包括函數(shù)嵌套,遞歸,等等,都是從這個(gè)“?!崩锩?,來分配的。HcifftAT甘ilp白一電B B0 012123 345 i iY YfuRLfuRL他的鼠誨用叩JaEUBIEFdBJaE
8、UBIEFdBl lUKLUUIWIWOxFQOxFQgHQ(hrkgHQ(hrk口的心口03200001400320000140OiMOMOftOOiMOMOftO i?ni?nomnwomnw:OaQOOOOOCWUxJOaQOOOOOCWUxJUOLlOOllUUOLlOOllUUzWUWJUUUOxIXUzWUWJUUUOxIXiQOOOOUnjABnoiQOOOOUnjABnojnraCsOOODOOOjnraCsOOODOOOQ QOiMOftOlOiMOftOl?C C60120000006012000000ILR)UaW0WC5ILR)UaW0WC5J J,-,-:41J_BI
9、4II-ai41MdlJILS4IJ.=41J_BI4II-ai41MdlJILS4IJ.=孫J.OI880002-4OxZJUJ.OI880002-4OxZJUWUWWUWo o富kincnkincn96fl96fl-ML.83830 02 22323it滄dwrarsy?addx)siazk_diL=):為AdizrarsyK地士大干柒els#stscir_dir=0.二次duiw(yi?)她IE不平第1/哀歌CPU大,川陽8日“霜昊保存在邛jmixkE固Voi.dfLnjd&cpu_-ndiBJH(va;d)(intK=1if(.*-t亡k.t,)由學(xué)回呈I)cui_Efid.i
10、nJk-C1./,1。咻愧式c13bcuucndi必=1;/jrXi桎式4-4-9L9LThr+NPrivalgcd.HSFfiMn nnflriGnflriGn n陸n nintn.ai3i(9600);dr1ny_lmt(7S、絕吁。/“始化與LED叵度在謖斗陵口prntfCst皿一次:網(wǎng)51口1thitwck-dii:priTitf(cpu_endLan;#zcntfccpuendian):finiLrtwfc.dirfiniLrtwfc.dir ctiflnctifln( () ):笆步程性亡方式find_rpu.endifind_rpu.endianan:9I9?9I9?printf
11、CUEprintfCUE 加茹瞿式 1 1小 ddde:!ns150J):LEDO=ILEIO所以,如果一個(gè)函數(shù)的局部變量過多,比如在函數(shù)里面定義一個(gè)u8buf512,這一下就占了1/4的棧大小了,再在其他函數(shù)里面來搞兩下,程序崩潰是很容易的事情,這時(shí)候,一般你會進(jìn)入到hardfault.這是初學(xué)者非常容易犯的一個(gè)錯(cuò)誤.切記不要在函數(shù)里面放N N多局部變量,尤其有大數(shù)組的時(shí)候!對于棧區(qū),一般棧頂,也就是MSP,MSP,在程序剛運(yùn)行的時(shí)候,指向程序所占用內(nèi)存的最高地址。比如附件里面的這個(gè)程序序,內(nèi)存占用如下圖:圖中,我們可以看到,程序總共占用內(nèi)存:20+2348字節(jié)=2368=0X940那么程序
12、剛開始運(yùn)行的時(shí)候:MSP=0X20000000+0X940=0X2000MSP=0X20000000+0X940=0X200009400940事實(shí)上,也是如此,如圖:圖CdfktcjimpnfRandktfinEqlArlEini#r*nCdfktcjimpnfRandktfinEqlArlEini#r*ni i莫而買嗓4 4出U U實(shí)驗(yàn)U U網(wǎng)Rk-fitJlYprnjRk-fitJlYprnj-附44加4 4EiLc=?is;iF;月巨口耳FcxithsEL:V二三M】/x0d/F.r.:?=/i:4 4:1二匕LE,It彈叵。()中忤KJ0|口除囿=1 1的慘習(xí)言,手;|*K*T國tet
13、e司崗,n:圖中,MSP就是:0X20000940,程序運(yùn)行后,MSP就是從這個(gè)地址開始,往下給函數(shù)的局部變量分配地b bs址。再說說棧的增長方向,我們可以用如下代碼測試:保存棧增長方向Z/0,向下增長;1,向上增長staticu8stack_dir;查找棧增長方向,結(jié)果保存在stack_dir里面voidfind_stack_direction(void)staticu8*addr=NULL;用于存放第一個(gè)dummy的地址u8dummy;用于獲取棧地址if(addr=NULL)第一次進(jìn)入addr=&dummy;保存dummy的地址find_stack_direction();遞歸el
14、se第二次進(jìn)入if(&dummyaddr)stack_dir=1;/第二次dummy的地址大于第一次dummy,那么說明棧增長方向是向上的.elsestack_dir=0;第二次dummy的地址小于第一次dummy,那么說明棧增長方向是向下的這個(gè)代碼不是我寫的,網(wǎng)上抄來的,思路很巧妙,利用遞歸,判斷兩次分配給dummy的地址,來比較棧是向下生長,還是向上生長。如果你在STM32測試這個(gè)函數(shù),你會發(fā)現(xiàn),STM32STM32的棧,是向下生長的。事實(shí)上,一般CPUCPU的棧增長方向,都是向下的。2,2,再來說說,堆(HEAP)(HEAP)的問題. .全局變量,靜態(tài)變量,以及內(nèi)存管理所用的內(nèi)存
15、,都是屬于“堆區(qū)”,英文名:“HEAP”,與棧區(qū)不同,堆區(qū),則從內(nèi)存區(qū)域的起始地址開始分配給各個(gè)全局變量和靜態(tài)變量。堆的生長方向,都是向上的。在程序里面,所有的內(nèi)存分為:堆+棧,只是他們各自的起始地址和增長方向不同,他們沒有一個(gè)固定的界限,所以一旦堆棧沖突,系統(tǒng)就到了崩潰的時(shí)候了。同樣,我們用附件里面的例程測試:dminidratorVSdminidratorVS;filfil實(shí)暨d d星口實(shí)號:U:U EMt&st.uvprojVicicMEMt&st.uvprojVicicM=hFe:ii::her.ElE二二dm二三受二匚金第:三己二二力a a:_3ind_Ey_3ind
16、_Ey 閽n n畫8 8. .中|回凰用國囤國乖3 3寸|sasa/*/*stack_dir的地址是0X20000004,也就是STM32的內(nèi)存起始端的地址。這里本來應(yīng)該是從0X20000000開始分配的,但是,我仿真發(fā)現(xiàn)0X20000000總是存放:0X20000398,這個(gè)值,貌似是MSP,但是又不變化,還請高手幫忙解釋下。其他的,全局變量,則依次遞增,地址肯定大于0X20000004,比如cpu_endian的地址就是0X20000005。這就是STM32內(nèi)部堆的分配規(guī)則.3,3,再說說,大小端的問題. .大端模式:低位字節(jié)存在高地址上,高位字節(jié)存在低地址上小端模式:高位字節(jié)存在高地址上
17、,低位字節(jié)存在低地址上STM32屬于小端模式,簡單的說,比如u32temp=0X12345678;假設(shè)temp地址在0X20000010.那么在內(nèi)存里面,存放就變成了:地址|HEX|0X20000010|78564312|CPU到底是大端還是小端,可以通過如下代碼測試/CPU大小端/0,小端模式;1,大端模式.staticu8cpuendian;/獲取CPU大小端模式,結(jié)果保存在cpu_endian里面voidfind_cpu_endian(void)(I23d-E678GO1234FI23d-E678GO1234F6706709 90 0# #includeinclude”三產(chǎn)不,hh3 3
18、LPclicliideidensart.nnsart.nP PfineIntie,dtlfineIntie,dtlw*w*h hf flincludfllincludfl*Ld.n*Ld.n includeincludebsji.hbsji.h星 LMluLMlu 加%A/iLIEA/iLIE 口托爆艦 TN*TN*并叁根賣臉 d d7 7 吊存柱.增蛆方向“Q,Q,向下墻 M:l.M:l.向上:酢=?taticuSstacle:_dii,;/CPUCPU 大小瑞號 2 2 個(gè)端根式上大端噴式.Tiitirijflujnj_*=T曰i*n;V V 查尼榭魯長方向,潴果保存在 0nH0nH 里置
19、IIIkZT.nhIcZ=cakZillkZT.nhIcZ=cakZill 曰 Huuk 二二 n 匚 3rcnkcz3rcnkczAodAod s:s:lacrlacr0 x20000004:0 x20000004:d二口5;:HOK:X207:-x?-:j=.4:-iisilatisr:intx=1;if(*(char*)&x=1)cpu_endian=0;小端模式elsecpu_endian=1;大端模式以上測試在STM32上,你會得到cpu_endian=0,也就是小端模式.3,3,最后說說,STM32,STM32內(nèi)存的問題. .還是以附件工程為例,在前面第一個(gè)圖,程序總共占用
20、內(nèi)存:20+2348字節(jié),這么多內(nèi)存,到底是怎么得來的呢?我們可以雙擊Project側(cè)邊欄的:Targt1,會彈出test.map在這個(gè)里面,我們就可以清楚的知道這些內(nèi)存到底是怎么來的了.在這個(gè)test.map最后,Image部分有:ImagecomponentsizesCode(inc.data)RODataRWDataZIDataDebugObjectNamelay.o/delay.c里面,facus和facms,共占用4字節(jié)11212000427led.o722630402048828startup_stm32f10 x_hd.o啟動文件,里面定義了Stack_
21、Size為0X800,所以這里是2048.712520002715sys.o348154060208720test.o/test.c里面,stackdir和cpuendian以及*addr,占用6字節(jié).38424082003050usart.o/usart.c定義了一個(gè)串口接收數(shù)組buffer,占用200字節(jié)1800278336202248216735ObjectTotals總共2248+20字節(jié)0032000(incl.Generated)000200(incl.Padding)/2字節(jié)用于對其Code(inc.data)RODataRWDataZIDataDebugLibraryMembe
22、rName8000068main.o104000084_printf.o5280000scatter.o2600000_scatter_copy.o2800000scatterzi.o48600096printfcharcommon.o36400080printfcharfile.o924400088printfhexint.o184000088printfintcommon.o0printfpercent.o600000_printf_x.o12000072exit.o8000068ferror.o60000152heapauxi.o200000libinit.o200000libinit2.o200000libshutdown.o200000libshutdown2.o400000printfpercentend.o9668libspace.o庫文件(printf使用),占用了96字節(jié)2484noretval2printf.o0rtentry.o
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 食品安全監(jiān)管與檢驗(yàn)技術(shù)試題及答案
- 委托勞務(wù)派遣服務(wù)合同協(xié)議書
- Fluostatin-B-生命科學(xué)試劑-MCE
- 文件歸檔目錄表格(按文件類型)
- 工程勘察設(shè)計(jì)合同新
- 2024年陜西省安全員《A證》考試題庫及答案
- 小班家長會發(fā)言稿文檔
- 黨委競選發(fā)言稿
- 紡織印染廢水蒸發(fā)處理
- 人民醫(yī)院耗材采購合同年
- 2024年濟(jì)南廣播電視臺招考電視工作人員高頻500題難、易錯(cuò)點(diǎn)模擬試題附帶答案詳解
- 《中國詩詞大會》九宮格(原題)
- 住院病人跌倒墜床風(fēng)險(xiǎn)評估及防范措施表
- 人教版《道德與法治》二年級下冊全冊課件
- 2024年云南省中考數(shù)學(xué)模擬試題(附答案解析)
- 無人機(jī)項(xiàng)目可行性實(shí)施報(bào)告
- 垃圾清運(yùn)服務(wù)實(shí)施方案投標(biāo)文件(技術(shù)方案)
- 智能灌溉技術(shù)在農(nóng)田水利中的應(yīng)用
- 2024-2030年中國消費(fèi)級3D打印機(jī)行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略分析報(bào)告
- JGT 486-2015 混凝土用復(fù)合摻合料
- 世界急救日常見的急救基本知識科普講座課件
評論
0/150
提交評論