1. 程式人生 > >Cortex-M3啟動深度解析

Cortex-M3啟動深度解析

cortex-m3 進入 系統 參數 全局 變量大小 編譯 直觀 clas

Cortex-Mx啟動,備忘,以免將來忘記。
中斷向量表不用說,從重置中斷開始吧

LDR     R0, =SystemInit
BLX     R0
LDR     R0, =__main
BX      R0

這裏一共就執行了兩個函數,SystemInit和__main。

我們一般在SystemInit裏面配置系統時鐘,這裏跳過。

__main是我們今天的重點。

                 __main:
0x080000C0 4804      LDR      r0,[pc,#16]  ; @0x080000D4
0x080000C2 4685      MOV      sp,r0        #設置棧頂
                 
_main_scatterload: 0x080000C4 F000F956 BL.W __scatterload (0x08000374) #分散加載(拷貝初始值、清零變量) __main_after_scatterload: 0x080000C8 F000F8D4 BL.W __cpp_initialize__aeabi_ (0x08000274) #C++初始化(全局對象構造函數執行) _main_cpp_init: 0x080000CC 4800 LDR r0,[pc,#0] ; @0x080000D0 0x080000CE 4700 BX r0 #進入C++的main函數

分散加載這裏將會初始化我們的全局靜態變量

.text:00000000 __scatterload_rt2
.text:00000000                 LDR     R4, =Region$Table$Base
.text:00000002                 MOVS    R5, #1
.text:00000004                 LDR     R6, =Region$Table$Limit
.text:00000006                 B       loc_14
.text:00000008 ; ---------------------------------------------------------------------------
.text:00000008 .text:00000008 loc_8 ; CODE XREF: __scatterload_rt2+16j .text:00000008 LDR R3, [R4,#0xC] .text:0000000A LDMIA R4!, {R0-R2} .text:0000000C ORRS R3, R5 .text:0000000E SUBS R4, #0xC .text:00000010 BLX R3 .text:00000012 ADDS R4, #0x10 .text:00000014 .text:00000014 loc_14 ; CODE XREF: __scatterload_rt2+6j .text:00000014 CMP R4, R6 .text:00000016 BCC loc_8 .text:00000018 BL __main_after_scatterload

可能匯編看起來不是很直觀,我們配合看F5得到的反編譯C代碼

void _scatterload_rt2()
{
  _DWORD *i; // [email protected]

  for ( i = &Region__Table__Base; (_UNKNOWN *)i < &Region__Table__Limit; i += 4 )
    ((void (__fastcall *)(_DWORD, _DWORD, _DWORD))(i[3] | 1))(*i, i[1], i[2]);
  _main_after_scatterload();
  JUMPOUT(&Region__Table__Base);
}

從上面看出,有一張區域表,每4個int作為一段,每一段前三個為參數,第四個為函數指針。

經過調試得知:
第一個函數是__scatterload_copy,從某個Flash地址把數據拷貝給RAM裏面的變量,也就是帶有初始值的全局變量;
第二個函數是__scatterload_zeroinit,顧名思義,就是全局變量清零,只要沒有初始值的全局變量,都清零,堆空間和棧空間一塊清。
而在匯編文件裏面我們有AREA HEAP, NOINIT, READWRITE, ALIGN=3。顯然其中的NOINIT並沒有生效

ER_IROM1:0800D704 Region$Table$Base DCD 0x800D72C       ;        #要拷貝的初始值來源,緊跟在固件源代碼後面
 DATA XREF: ER_IROM1:__scatterload_rt2o
ER_IROM1:0800D704                                         ; ER_IROM1:off_8000390o
ER_IROM1:0800D708                 DCD 0x20000000    #要復制初始值的起始地址
ER_IROM1:0800D70C                 DCD 0xCC        #帶有初始值的區域大小
ER_IROM1:0800D710                 DCD __scatterload_copy
ER_IROM1:0800D714                 DCD 0x800D7F8
ER_IROM1:0800D718                 DCD 0x200000CC    #要清零的變量起始地址
ER_IROM1:0800D71C                 DCD 0x132C    #要清零的變量大小
ER_IROM1:0800D720                 DCD __scatterload_zeroinit
ER_IROM1:0800D724                 EXPORT SHT$INIT_ARRAY$Base

因此,針對__scatterload_zeroinit而言,為了加快啟動速度,建議堆空間設得盡量小,然後在SmartOS系統初始化的時候再重新設置堆空間

Cortex-M3啟動深度解析