久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標(biāo)題: 解析STM32啟動(dòng)過程 [打印本頁]

作者: rduyjhnb    時(shí)間: 2018-9-16 15:14
標(biāo)題: 解析STM32啟動(dòng)過程
相對(duì)于ARM上一代的主流ARM7/ARM9內(nèi)核架構(gòu),新一代Cortex內(nèi)核架構(gòu)的啟動(dòng)方式有了比較大的變化。ARM7/ARM9內(nèi)核的控制器在復(fù)位后,CPU會(huì)從存儲(chǔ)空間的絕對(duì)地址0x000000取出第一條指令執(zhí)行復(fù)位中斷服務(wù)程序的方式啟動(dòng),即固定了復(fù)位后的起始地址為0x000000PC = 0x000000)同時(shí)中斷向量表的位置并不是固定的。而Cortex-M3內(nèi)核則正好相反,有3種情況:
1 通過boot引腳設(shè)置可以將中斷向量表定位于SRAM區(qū),即起始地址為0x2000000,同時(shí)復(fù)位后PC指針位于0x2000000處;
2 通過boot引腳設(shè)置可以將中斷向量表定位于FLASH區(qū),即起始地址為0x8000000,同時(shí)復(fù)位后PC指針位于0x8000000處;
3 通過boot引腳設(shè)置可以將中斷向量表定位于內(nèi)置Bootloader區(qū),本文不對(duì)這種情況做論述;
Cortex-M3內(nèi)核規(guī)定,起始地址必須存放堆頂指針,而第二個(gè)地址則必須存放復(fù)位中斷入口向量地址,這樣在Cortex-M3內(nèi)核復(fù)位后,會(huì)自動(dòng)從起始地址的下一個(gè)32位空間取出復(fù)位中斷入口向量,跳轉(zhuǎn)執(zhí)行復(fù)位中斷服務(wù)程序。對(duì)比ARM7/ARM9內(nèi)核,Cortex-M3內(nèi)核則是固定了中斷向量表的位置而起始地址是可變化的。
有了上述準(zhǔn)備只是后,下面以STM322.02固件庫提供的啟動(dòng)文件“stm32f10x_vector.s”為模板,對(duì)STM32的啟動(dòng)過程做一個(gè)簡要而全面的解析。

程序清單一:
;文件“stm32f10x_vector.s”,其中注釋為行號(hào)
DATA_IN_ExtSRAM EQU 0
1
Stack_Size EQU 0x00000400
2
AREA STACK, NOINIT, READWRITE, ALIGN = 3
3
Stack_Mem SPACE Stack_Size
4
__initial_sp
5
Heap_Size EQU 0x00000400
6
AREA HEAP, NOINIT, READWRITE, ALIGN = 3
7
__heap_base
8
Heap_Mem SPACE Heap_Size
9
__heap_limit
10
THUMB
11
PRESERVE8
12
IMPORT NMIException
13
IMPORT HardFaultException
14
IMPORT MemManageException
15
IMPORT BusFaultException
16
IMPORT UsageFaultException
17
IMPORT SVCHandler
18
IMPORT DebugMonitor
19
IMPORT PendSVC
20
IMPORT SysTickHandler
21
IMPORT WWDG_IRQHandler
22
IMPORT PVD_IRQHandler
23
IMPORT TAMPER_IRQHandler
24
IMPORT RTC_IRQHandler
25
IMPORT FLASH_IRQHandler
26
IMPORT RCC_IRQHandler
27
IMPORT EXTI0_IRQHandler
28
IMPORT EXTI1_IRQHandler
29
IMPORT EXTI2_IRQHandler
30
IMPORT EXTI3_IRQHandler
31
IMPORT EXTI4_IRQHandler
32
IMPORT DMA1_Channel1_IRQHandler
33
IMPORT DMA1_Channel2_IRQHandler
34
IMPORT DMA1_Channel3_IRQHandler
35
IMPORT DMA1_Channel4_IRQHandler
36
IMPORT DMA1_Channel5_IRQHandler
37
IMPORT DMA1_Channel6_IRQHandler
38
IMPORT DMA1_Channel7_IRQHandler
39
IMPORT ADC1_2_IRQHandler
40
IMPORT USB_HP_CAN_TX_IRQHandler
41
IMPORT USB_LP_CAN_RX0_IRQHandler
42
IMPORT CAN_RX1_IRQHandler
43
IMPORT CAN_SCE_IRQHandler
44
IMPORT EXTI9_5_IRQHandler
45
IMPORT TIM1_BRK_IRQHandler
46
IMPORT TIM1_UP_IRQHandler
47
IMPORT TIM1_TRG_COM_IRQHandler
48
IMPORT TIM1_CC_IRQHandler
49
IMPORT TIM2_IRQHandler
50
IMPORT TIM3_IRQHandler
51
IMPORT TIM4_IRQHandler
52
IMPORT I2C1_EV_IRQHandler
53
IMPORT I2C1_ER_IRQHandler
54
IMPORT I2C2_EV_IRQHandler
55
IMPORT I2C2_ER_IRQHandler
56
IMPORT SPI1_IRQHandler
57
IMPORT SPI2_IRQHandler
58
IMPORT USART1_IRQHandler
59
IMPORT USART2_IRQHandler
60
IMPORT USART3_IRQHandler
61
IMPORT EXTI15_10_IRQHandler
62
IMPORT RTCAlarm_IRQHandler
63
IMPORT USBWakeUp_IRQHandler
64
IMPORT TIM8_BRK_IRQHandler
65
IMPORT TIM8_UP_IRQHandler
66
IMPORT TIM8_TRG_COM_IRQHandler
67
IMPORT TIM8_CC_IRQHandler
68
IMPORT ADC3_IRQHandler
69
IMPORT FSMC_IRQHandler
70
IMPORT SDIO_IRQHandler
71
IMPORT TIM5_IRQHandler
72
IMPORT SPI3_IRQHandler
73
IMPORT UART4_IRQHandler
74
IMPORT UART5_IRQHandler
75
IMPORT TIM6_IRQHandler
76
IMPORT TIM7_IRQHandler
77
IMPORT DMA2_Channel1_IRQHandler
78
IMPORT DMA2_Channel2_IRQHandler
79
IMPORT DMA2_Channel3_IRQHandler
80
IMPORT DMA2_Channel4_5_IRQHandler
81
AREA RESET, DATA, READONLY
82
EXPORT __Vectors
83
__Vectors
84
DCD __initial_sp
85
DCD Reset_Handler
86
DCD NMIException
87
DCD HardFaultException
88
DCD MemManageException
89
DCD BusFaultException
90
DCD UsageFaultException
91
DCD 0
92
DCD 0
93
DCD 0
94
DCD 0
95
DCD SVCHandler
96
DCD DebugMonitor
97
DCD 0
98
DCD PendSVC
99
DCD SysTickHandler
100
DCD WWDG_IRQHandler
101
DCD PVD_IRQHandler
102
DCD TAMPER_IRQHandler
103
DCD RTC_IRQHandler
104
DCD FLASH_IRQHandler
105
DCD RCC_IRQHandler
106
DCD EXTI0_IRQHandler
107
DCD EXTI1_IRQHandler
108
DCD EXTI2_IRQHandler
109
DCD EXTI3_IRQHandler
110
DCD EXTI4_IRQHandler
111
DCD DMA1_Channel1_IRQHandler
112
DCD DMA1_Channel2_IRQHandler
113
DCD DMA1_Channel3_IRQHandler
114
DCD DMA1_Channel4_IRQHandler
115
DCD DMA1_Channel5_IRQHandler
116
DCD DMA1_Channel6_IRQHandler
117
DCD DMA1_Channel7_IRQHandler
118
DCD ADC1_2_IRQHandler
119
DCD USB_HP_CAN_TX_IRQHandler
120
DCD USB_LP_CAN_RX0_IRQHandler
121
DCD CAN_RX1_IRQHandler
122
DCD CAN_SCE_IRQHandler
123
DCD EXTI9_5_IRQHandler
124
DCD TIM1_BRK_IRQHandler
125
DCD TIM1_UP_IRQHandler
126
DCD TIM1_TRG_COM_IRQHandler
127
DCD TIM1_CC_IRQHandler
128
DCD TIM2_IRQHandler
129
DCD TIM3_IRQHandler
130
DCD TIM4_IRQHandler
131
DCD I2C1_EV_IRQHandler
132
DCD I2C1_ER_IRQHandler
133
DCD I2C2_EV_IRQHandler
134
DCD I2C2_ER_IRQHandler
135
DCD SPI1_IRQHandler
136
DCD SPI2_IRQHandler
137
DCD USART1_IRQHandler
138
DCD USART2_IRQHandler
139
DCD USART3_IRQHandler
140
DCD EXTI15_10_IRQHandler
141
DCD RTCAlarm_IRQHandler
142
DCD USBWakeUp_IRQHandler
143
DCD TIM8_BRK_IRQHandler
144
DCD TIM8_UP_IRQHandler
145
DCD TIM8_TRG_COM_IRQHandler
146
DCD TIM8_CC_IRQHandler
147
DCD ADC3_IRQHandler
148
DCD FSMC_IRQHandler
149
DCD SDIO_IRQHandler
150
DCD TIM5_IRQHandler
151
DCD SPI3_IRQHandler
152
DCD UART4_IRQHandler
153
DCD UART5_IRQHandler
154
DCD TIM6_IRQHandler
155
DCD TIM7_IRQHandler
156
DCD DMA2_Channel1_IRQHandler
157
DCD DMA2_Channel2_IRQHandler
158
DCD DMA2_Channel3_IRQHandler
159
DCD DMA2_Channel4_5_IRQHandler
160
AREA |.text|, CODE, READONLY
161
Reset_Handler PROC
162
EXPORT Reset_Handler
163
IF DATA_IN_ExtSRAM == 1
164
LDR R0,= 0x00000114
165
LDR R1,= 0x40021014
166
STR R0,[R1]
167
LDR R0,= 0x000001E0
168
LDR R1,= 0x40021018
169
STR R0,[R1]
170
LDR R0,= 0x44BB44BB
171
LDR R1,= 0x40011400
172
STR R0,[R1]
173
LDR R0,= 0xBBBBBBBB
174
LDR R1,= 0x40011404
175
STR R0,[R1]
176
LDR R0,= 0xB44444BB
177
LDR R1,= 0x40011800
178
STR R0,[R1]
179
LDR R0,= 0xBBBBBBBB
180
LDR R1,= 0x40011804
181
STR R0,[R1]
182
LDR R0,= 0x44BBBBBB
183
LDR R1,= 0x40011C00
184
STR R0,[R1]
185
LDR R0,= 0xBBBB4444
186
LDR R1,= 0x40011C04
187
STR R0,[R1]
188
LDR R0,= 0x44BBBBBB
189
LDR R1,= 0x40012000
190
STR R0,[R1]
191
LDR R0,= 0x44444B44
192
LDR R1,= 0x40012004
193
STR R0,[R1]
194
LDR R0,= 0x00001011
195
LDR R1,= 0xA0000010
196
STR R0,[R1]
197
LDR R0,= 0x00000200
198
LDR R1,= 0xA0000014
199
STR R0,[R1]
200
ENDIF
201
IMPORT __main
202
LDR R0, =__main
203
BX R0
204
ENDP
205
ALIGN
206
IF :DEF:__MICROLIB
207
EXPORT __initial_sp
208
EXPORT __heap_base
209
EXPORT __heap_limit
210
ELSE
211
IMPORT __use_two_region_memory
212
EXPORT __user_initial_stackheap
213
__user_initial_stackheap
214
LDR R0, = Heap_Mem
215
LDR R1, = (Stack_Mem + Stack_Size)
216
LDR R2, = (Heap_Mem + Heap_Size)
217
LDR R3, = Stack_Mem
218
BX LR
219
ALIGN
220
ENDIF
221
END
222
ENDIF
223
END
224

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

如程序清單一,STM32的啟動(dòng)代碼一共224行,使用了匯編語言編寫,這其中的主要原因下文將會(huì)給出交代。現(xiàn)在從第一行開始分析:
l 1行:定義是否使用外部SRAM,為1則使用,為0則表示不使用。此語行若用C語言表達(dá)則等價(jià)于:
#define DATA_IN_ExtSRAM 0
l 2行:定義棧空間大小為0x00000400個(gè)字節(jié),即1Kbyte。此語行亦等價(jià)于:
#define Stack_Size 0x00000400
l 3行:偽指令AREA,表示
l 4行:開辟一段大小為Stack_Size的內(nèi)存空間作為棧。
l 5行:標(biāo)號(hào)__initial_sp,表示棧空間頂?shù)刂贰?/font>
l 6行:定義堆空間大小為0x00000400個(gè)字節(jié),也為1Kbyte
l 7行:偽指令AREA,表示
l 8行:標(biāo)號(hào)__heap_base,表示堆空間起始地址。
l 9行:開辟一段大小為Heap_Size的內(nèi)存空間作為堆。
l 10行:標(biāo)號(hào)__heap_limit,表示堆空間結(jié)束地址。
l 11行:告訴編譯器使用THUMB指令集。
l 12行:告訴編譯器以8字節(jié)對(duì)齊。
l 13—81行:IMPORT指令,指示后續(xù)符號(hào)是在外部文件定義的(類似C語言中的全局變量聲明),而下文可能會(huì)使用到這些符號(hào)。
l 82行:定義只讀數(shù)據(jù)段,實(shí)際上是在CODE區(qū)(假設(shè)STM32FLASH啟動(dòng),則此中斷向量表起始地址即為0x8000000
l 83行:將標(biāo)號(hào)__Vectors聲明為全局標(biāo)號(hào),這樣外部文件就可以使用這個(gè)標(biāo)號(hào)。
l 84行:標(biāo)號(hào)__Vectors,表示中斷向量表入口地址。
l 85—160行:建立中斷向量表。
l 161行:
l 162行:復(fù)位中斷服務(wù)程序,PROC…ENDP結(jié)構(gòu)表示程序的開始和結(jié)束。
l 163行:聲明復(fù)位中斷向量Reset_Handler為全局屬性,這樣外部文件就可以調(diào)用此復(fù)位中斷服務(wù)。
l 164行:IF…ENDIF為預(yù)編譯結(jié)構(gòu),判斷是否使用外部SRAM,在第1行中已定義為不使用
l 165—201行:此部分代碼的作用是設(shè)置FSMC總線以支持SRAM,因不使用外部SRAM因此此部分代碼不會(huì)被編譯。
l 202行:聲明__main標(biāo)號(hào)。
l 203—204行:跳轉(zhuǎn)__main地址執(zhí)行。
l 207行:IF…ELSE…ENDIF結(jié)構(gòu),判斷是否使用DEF:__MICROLIB(此處為不使用)。
l 208—210行:若使用DEF:__MICROLIB,則將__initial_sp__heap_base__heap_limit亦即棧頂?shù)刂罚咽寄┑刂焚x予全局屬性,使外部程序可以使用。
l 212行:定義全局標(biāo)號(hào)__use_two_region_memory
l 213行:聲明全局標(biāo)號(hào)__user_initial_stackheap,這樣外程序也可調(diào)用此標(biāo)號(hào)。
l 214行:標(biāo)號(hào)__user_initial_stackheap,表示用戶堆棧初始化程序入口。
l 215—218行:分別保存棧頂指針和棧大小,堆始地址和堆大小至R0R1R2R3寄存器。
l 224行:程序完畢。
以上便是STM32的啟動(dòng)代碼的完整解析,接下來對(duì)幾個(gè)小地方做解釋:
1 AREA指令:偽指令,用于定義代碼段或數(shù)據(jù)段,后跟屬性標(biāo)號(hào)。其中比較重要的一個(gè)標(biāo)號(hào)為“READONLY”或者“READWRITE”,其中“READONLY”表示該段為只讀屬性,聯(lián)系到STM32的內(nèi)部存儲(chǔ)介質(zhì),可知具有只讀屬性的段保存于FLASH區(qū),即0x8000000地址后。而“READONLY”表示該段為可讀寫屬性,可知可讀寫段保存于SRAM區(qū),即0x2000000地址后。由此可以從第37行代碼知道,堆棧段位于SRAM空間。從第82行可知,中斷向量表放置與FLASH區(qū),而這也是整片啟動(dòng)代碼中最先被放進(jìn)FLASH區(qū)的數(shù)據(jù)。因此可以得到一條重要的信息:0x8000000地址存放的是棧頂?shù)刂?/font>__initial_sp0x8000004地址存放的是復(fù)位中斷向量Reset_HandlerSTM32使用32位總線,因此存儲(chǔ)空間為4字節(jié)對(duì)齊)。
2 DCD指令:作用是開辟一段空間,其意義等價(jià)于C語言中的地址符“&”。因此從第84行開始建立的中斷向量表則類似于使用C語言定義了一個(gè)指針數(shù)組,其每一個(gè)成員都是一個(gè)函數(shù)指針,分別指向各個(gè)中斷服務(wù)函數(shù)。
3 標(biāo)號(hào):前文多處使用了標(biāo)號(hào)一詞。標(biāo)號(hào)主要用于表示一片內(nèi)存空間的某個(gè)位置,等價(jià)于C語言中的地址概念。地址僅僅表示存儲(chǔ)空間的一個(gè)位置,從C語言的角度來看,變量的地址,數(shù)組的地址或是函數(shù)的入口地址在本質(zhì)上并無區(qū)別。
4 202行中的__main標(biāo)號(hào)并不表示C程序中的main函數(shù)入口地址,因此第204行也并不是跳轉(zhuǎn)至main函數(shù)開始執(zhí)行C程序。__main標(biāo)號(hào)表示C/C++標(biāo)準(zhǔn)實(shí)時(shí)庫函數(shù)里的一個(gè)初始化子程序__main的入口地址。該程序的一個(gè)主要作用是初始化堆棧(對(duì)于程序清單一來說則是跳轉(zhuǎn)__user_initial_stackheap標(biāo)號(hào)進(jìn)行初始化堆棧的),并初始化映像文件,最后跳轉(zhuǎn)C程序中的main函數(shù)。這就解釋了為何所有的C程序必須有一個(gè)main函數(shù)作為程序的起點(diǎn)——因?yàn)檫@是由C/C++標(biāo)準(zhǔn)實(shí)時(shí)庫所規(guī)定的——并且不能更改,因?yàn)?/font>C/C++標(biāo)準(zhǔn)實(shí)時(shí)庫并不對(duì)外界開發(fā)源代碼。因此,實(shí)際上在用戶可見的前提下,程序在第204行后就跳轉(zhuǎn)至.c文件中的main函數(shù),開始執(zhí)行C程序了。
至此可以總結(jié)一下STM32的啟動(dòng)文件和啟動(dòng)過程。首先對(duì)棧和堆的大小進(jìn)行定義,并在代碼區(qū)的起始處建立中斷向量表,其第一個(gè)表項(xiàng)是棧頂?shù)刂罚诙䝼(gè)表項(xiàng)是復(fù)位中斷服務(wù)入口地址。然后在復(fù)位中斷服務(wù)程序中跳轉(zhuǎn)¬¬C/C++標(biāo)準(zhǔn)實(shí)時(shí)庫的__main函數(shù),完成用戶堆棧等的初始化后,跳轉(zhuǎn).c文件中的main函數(shù)開始執(zhí)行C程序。假設(shè)STM32被設(shè)置為從內(nèi)部FLASH啟動(dòng)(這也是最常見的一種情況),中斷向量表起始地位為0x8000000,則棧頂?shù)刂反娣庞?/font>0x8000000處,而復(fù)位中斷服務(wù)入口地址存放于0x8000004處。當(dāng)STM32遇到復(fù)位信號(hào)后,則從0x80000004處取出復(fù)位中斷服務(wù)入口地址,繼而執(zhí)行復(fù)位中斷服務(wù)程序,然后跳轉(zhuǎn)__main函數(shù),最后進(jìn)入mian函數(shù),來到C的世界。






歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 在线观看欧美日韩视频 | 欧美日韩国产在线播放 | 青青草网站| www.黄色av| 精品久久免费 | 在线视频a | 日日爱影视 | 黄色av毛片 | 特级西西444www大精品视频 | 韩日视频 | 天堂在线中文资源 | 蜜桃精品一区二区三区 | 在线视频日韩 | 亚洲视频三区 | 黄色片在线 | 中文字幕在线播放视频 | 日韩精品视频在线播放 | 亚洲精品1区2区 | 中文字幕丰满人伦在线 | 国产精品美女 | 婷婷精品 | 成人免费视频网址 | 免费不卡视频 | 成人免费在线 | 欧美激情在线观看 | 欧美午夜视频 | 日本在线看片 | 亚洲区视频 | 精品成人av | 国产人成| 国产91免费 | 日本在线视频一区 | h片在线免费观看 | 懂色av一区二区三区 | 天天夜夜操 | 国产91清纯白嫩初高中在线观看 | 人人草av | 久久精品国产一区 | 91视频精品 | 香蕉av在线 | 毛片tv|