RT-Thread源碼學習第一篇,分析裸機程序的開始代碼

利用業餘時間,自學了一點STM32編程,作過幾個小玩具。但一直侷限在裸機代碼裏,沒有機會學習rtos,深覺得憾。編程

春節閒在家裏無聊,就翻了一下野火的教程,發現對rtt講得很好,並且不須要硬件,只用軟件仿真就能夠學習,恰好利用這個機會入一下門。函數

過去我寫裸機代碼,主要就是用st公司的std庫。std庫包裝得很好,再加上mdk5的pack management很好用,就沒怎麼關注底層。據說rtos要修改啓動代碼,看來彙編這個坎是繞不過了。只好突擊了一下ARM的指令集,勉強能看懂源碼。學習

讀啓動文件的源碼,發現先是定義了堆棧地址,而後跳到SystemInit函數。SystemInit函數負責調節單片機時鐘寄存器的值,並把時鐘源由內部晶振切換到外部晶振,這部分很好理解。再以後就跳到了__main函數。這個函數我在文件系統裏沒有搜到源碼,無論是c的仍是彙編的都沒有,估計被MDK5隱藏了。spa

以stm32f103c8t6和mdk5.24爲例,我寫了一個空的while循環做爲main函數,而後compile、debug,看反彙編。debug

空的main函數:code

int main(void)
{
    while(1)
    {
        
    }
}

 反彙編,assembly模式:blog

__main:
0x080000EC F000F802  BL.W     __scatterload (0x080000F4)
0x080000F0 F000F82C  BL.W     __rt_entry (0x0800014C)

說明裏面還有兩個子函數__scatterload和__rt_entry。教程

看代碼__scatterload還有兩個子函數,分別爲__scatterload_null和__scatterload_zeroinit。源碼

__scatterload:
0x080000F4 A00A      ADR      r0,{pc}+4  ; @0x08000120
0x080000F6 E8900C00  LDM      r0,{r10-r11}
0x080000FA 4482      ADD      r10,r10,r0
0x080000FC 4483      ADD      r11,r11,r0
0x080000FE F1AA0701  SUB      r7,r10,#0x01
                 __scatterload_null:
0x08000102 45DA      CMP      r10,r11
0x08000104 D101      BNE      0x0800010A
0x08000106 F000F821  BL.W     __rt_entry (0x0800014C)
0x0800010A F2AF0E09  ADR.W    lr,{pc}-0x07  ; @0x08000103
0x0800010E E8BA000F  LDM      r10!,{r0-r3}
0x08000112 F0130F01  TST      r3,#0x01
0x08000116 BF18      IT       NE
0x08000118 1AFB      SUBNE    r3,r7,r3
0x0800011A F0430301  ORR      r3,r3,#0x01
0x0800011E 4718      BX       r3
0x08000120 0254      DCW      0x0254
0x08000122 0000      DCW      0x0000
0x08000124 0264      DCW      0x0264
0x08000126 0000      DCW      0x0000
                 __scatterload_zeroinit:
0x08000128 2300      MOVS     r3,#0x00
0x0800012A 2400      MOVS     r4,#0x00
0x0800012C 2500      MOVS     r5,#0x00
0x0800012E 2600      MOVS     r6,#0x00
0x08000130 3A10      SUBS     r2,r2,#0x10
0x08000132 BF28      IT       CS
0x08000134 C178      STMCS    r1!,{r3-r6}
0x08000136 D8FB      BHI      0x08000130
0x08000138 0752      LSLS     r2,r2,#29
0x0800013A BF28      IT       CS
0x0800013C C130      STMCS    r1!,{r4-r5}
0x0800013E BF48      IT       MI
0x08000140 600B      STRMI    r3,[r1,#0x00]
0x08000142 4770      BX       lr

__scatterload_null分別將加載域起始地址(沒太懂,看結果彷佛是緊挨着main函數後的一個地址)、運行域(ram)起始地址、map大小和__scatterload_zeroinit入口地址取出,再跳到__scatterload_zeroinit。__scatterload_zeroinit負責將ram清空,並回到__scatterload_null,再跳到__rt_entry。it

__rt_entry先調用__user_setup_stackheap函數創建堆棧。__user_setup_stackheap調用__user_initial_stackheap函數初始化堆棧。最後進入main函數,完成芯片的啓動。

__rt_lib_init:
0x08000144 B51F      PUSH     {r0-r4,lr}
                 __rt_lib_init_alloca_1:
0x08000146 BD1F      POP      {r0-r4,pc}
                 __rt_lib_shutdown:
0x08000148 B510      PUSH     {r4,lr}
                 __rt_lib_shutdown_cpp_1:
0x0800014A BD10      POP      {r4,pc}
                 __rt_entry:
0x0800014C F000F831  BL.W     __user_setup_stackheap (0x080001B2)
0x08000150 4611      MOV      r1,r2
                 __rt_entry_li:
0x08000152 F7FFFFF7  BL.W     __rt_lib_init (0x08000144)
                 __rt_entry_main:
0x08000156 F000F90B  BL.W     main (0x08000370)
0x0800015A F000F84F  BL.W     exit (0x080001FC)
                 __rt_exit:
0x0800015E B403      PUSH     {r0-r1}
                 __rt_exit_ls:
0x08000160 F7FFFFF2  BL.W     __rt_lib_shutdown (0x08000148)
                 __rt_exit_exit:
0x08000164 BC03      POP      {r0-r1}
0x08000166 F000F857  BL.W     _sys_exit (0x08000218)
0x0800016A 0000      MOVS     r0,r0
__user_initial_stackheap:
0x08000188 4804      LDR      r0,[pc,#16]  ; @0x0800019C
0x0800018A 4905      LDR      r1,[pc,#20]  ; @0x080001A0
0x0800018C 4A05      LDR      r2,[pc,#20]  ; @0x080001A4
0x0800018E 4B06      LDR      r3,[pc,#24]  ; @0x080001A8
0x08000190 4770      BX       lr
0x08000192 0000      DCW      0x0000
0x08000194 0311      DCW      0x0311
0x08000196 0800      DCW      0x0800
0x08000198 00ED      DCW      0x00ED
0x0800019A 0800      DCW      0x0800
0x0800019C 0060      DCW      0x0060
0x0800019E 2000      DCW      0x2000
0x080001A0 0660      DCW      0x0660
0x080001A2 2000      DCW      0x2000
0x080001A4 0260      DCW      0x0260
0x080001A6 2000      DCW      0x2000
0x080001A8 0260      DCW      0x0260
0x080001AA 2000      DCW      0x2000
                 __use_two_region_memory:
0x080001AC 4770      BX       lr
                 __rt_heap_escrow$2region:
0x080001AE 4770      BX       lr
                 __rt_heap_expand$2region:
0x080001B0 4770      BX       lr
                 __user_setup_stackheap:
0x080001B2 4675      MOV      r5,lr
0x080001B4 F000F82C  BL.W     __user_libspace (0x08000210)
0x080001B8 46AE      MOV      lr,r5
0x080001BA 0005      MOVS     r5,r0
0x080001BC 4669      MOV      r1,sp
0x080001BE 4653      MOV      r3,r10
0x080001C0 F0200007  BIC      r0,r0,#0x07
0x080001C4 4685      MOV      sp,r0
0x080001C6 B018      ADD      sp,sp,#0x60
0x080001C8 B520      PUSH     {r5,lr}
0x080001CA F7FFFFDD  BL.W     __user_initial_stackheap (0x08000188)
0x080001CE E8BD4020  POP      {r5,lr}
0x080001D2 F04F0600  MOV      r6,#0x00
0x080001D6 F04F0700  MOV      r7,#0x00
0x080001DA F04F0800  MOV      r8,#0x00
0x080001DE F04F0B00  MOV      r11,#0x00
0x080001E2 F0210107  BIC      r1,r1,#0x07
0x080001E6 46AC      MOV      r12,r5
0x080001E8 E8AC09C0  STM      r12!,{r6-r8,r11}
0x080001EC E8AC09C0  STM      r12!,{r6-r8,r11}
0x080001F0 E8AC09C0  STM      r12!,{r6-r8,r11}
0x080001F4 E8AC09C0  STM      r12!,{r6-r8,r11}
0x080001F8 468D      MOV      sp,r1
0x080001FA 4770      BX       lr
                 exit:
0x080001FC B510      PUSH     {r4,lr}
0x080001FE 4604      MOV      r4,r0
0x08000200 F3AF8000  NOP.W    
0x08000204 4620      MOV      r0,r4
0x08000206 E8BD4010  POP      {r4,lr}
0x0800020A F7FFBFA8  B.W      __rt_exit (0x0800015E)
0x0800020E 0000      MOVS     r0,r0
                 __user_libspace:
0x08000210 4800      LDR      r0,[pc,#0]  ; @0x08000214
0x08000212 4770      BX       lr
0x08000214 0000      DCW      0x0000
0x08000216 2000      DCW      0x2000
                 _sys_exit:
0x08000218 4901      LDR      r1,[pc,#4]  ; @0x08000220
0x0800021A 2018      MOVS     r0,#0x18
0x0800021C BEAB      BKPT     0xAB
0x0800021E E7FE      B        0x0800021E
0x08000220 0026      DCW      0x0026
0x08000222 0002      DCW      0x0002

如今是除夕夜,還有三分鐘就大年初一了,祝有幸能看到這篇文字的人新春快樂。

相關文章
相關標籤/搜索