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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2096|回復: 0
打印 上一主題 下一主題
收起左側

解析STM32啟動過程

[復制鏈接]
跳轉到指定樓層
樓主
ID:398655 發表于 2018-9-16 15:14 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
相對于ARM上一代的主流ARM7/ARM9內核架構,新一代Cortex內核架構的啟動方式有了比較大的變化。ARM7/ARM9內核的控制器在復位后,CPU會從存儲空間的絕對地址0x000000取出第一條指令執行復位中斷服務程序的方式啟動,即固定了復位后的起始地址為0x000000PC = 0x000000)同時中斷向量表的位置并不是固定的。而Cortex-M3內核則正好相反,有3種情況:
1 通過boot引腳設置可以將中斷向量表定位于SRAM區,即起始地址為0x2000000,同時復位后PC指針位于0x2000000處;
2 通過boot引腳設置可以將中斷向量表定位于FLASH區,即起始地址為0x8000000,同時復位后PC指針位于0x8000000處;
3 通過boot引腳設置可以將中斷向量表定位于內置Bootloader區,本文不對這種情況做論述;
Cortex-M3內核規定,起始地址必須存放堆頂指針,而第二個地址則必須存放復位中斷入口向量地址,這樣在Cortex-M3內核復位后,會自動從起始地址的下一個32位空間取出復位中斷入口向量,跳轉執行復位中斷服務程序。對比ARM7/ARM9內核,Cortex-M3內核則是固定了中斷向量表的位置而起始地址是可變化的。
有了上述準備只是后,下面以STM322.02固件庫提供的啟動文件“stm32f10x_vector.s”為模板,對STM32的啟動過程做一個簡要而全面的解析。

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

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: av网址在线播放 | 日韩一级电影免费观看 | 日韩激情视频一区 | 日韩国产免费观看 | 亚洲福利av | 午夜爽爽爽男女免费观看影院 | 国产视频精品在线观看 | 在线观看中文字幕 | 日韩精品一区二区不卡 | 毛片国产 | 国产亚洲精品久久久久动 | 亚洲视频在线观看 | 国产探花 | 免费av观看 | 91麻豆精品国产91久久久更新资源速度超快 | 精品国产乱码久久久久久1区2区 | 国产一区二区三区高清 | 日韩美女爱爱 | 酒色成人网 | 精品久久国产 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 亚洲精品在线免费 | 麻豆亚洲| 中文字幕1区 | 久久午夜精品福利一区二区 | 国产美女视频 | 一区二区福利视频 | 国产一级特黄视频 | 91精品国产色综合久久 | 国产乱肥老妇国产一区二 | 精品一区二区在线观看 | 91亚洲国产成人久久精品网站 | 国产成人精品网站 | 精品99在线 | 欧美亚洲国产一区二区三区 | 亚洲精品视频播放 | 久久成人精品视频 | 91高清在线观看 | 中文字幕在线视频免费视频 | 日韩av一区二区在线观看 | 日韩一级|