RT-Thread源码学习第一篇,分析裸机程序的开始代码

利用业余时间,自学了一点STM32编程,做过几个小玩具。但一直局限在裸机代码里,没有机会学习rtos,深以为憾。

春节闲在家里无聊,就翻了一下野火的教程,发现对rtt讲得很好,而且不需要硬件,只用软件仿真就可以学习,刚好利用这个机会入一下门。

过去我写裸机代码,主要就是用st公司的std库。std库包装得很好,再加上mdk5的pack management很好用,就没怎么关注底层。听说rtos要修改启动代码,看来汇编这个坎是绕不过了。只好突击了一下ARM的指令集,勉强能看懂源码。

读启动文件的源码,发现先是定义了堆栈地址,然后跳到SystemInit函数。SystemInit函数负责调节单片机时钟寄存器的值,并把时钟源由内部晶振切换到外部晶振,这部分很好理解。再之后就跳到了__main函数。这个函数我在文件系统里没有搜到源码,不管是c的还是汇编的都没有,估计被MDK5隐藏了。

以stm32f103c8t6和mdk5.24为例,我写了一个空的while循环作为main函数,然后compile、debug,看反汇编。

空的main函数:

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

 反汇编,assembly模式:

                 __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。

__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

现在是除夕夜,还有三分钟就大年初一了,祝有幸能看到这篇文字的人新春快乐。

转载于:https://my.oschina.net/u/4076592/blog/3008461

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值