0x03 LiteOS内核详解--stm32启动流程(下)

举报
樊心昊 发表于 2020/05/25 13:21:06 2020/05/25
3.5k+ 0 0
【摘要】 STM32复位后运行的第一条汇编代码当对STM32进行上电操作或者复位操作(按复位按钮,调用复位函数),STM32就会跳转到“中断向量表”中的地址0x0000_0004处执行已经写好的Rest_Hander处理函数,该函数使用汇编语言写的,在LiteOS中的如下位置“liteos\arch\arm\arm-m\armv7-m\gcc\los_startup.S”, 1. Reset_Han...

STM32复位后运行的第一条汇编代码

当对STM32进行上电操作或者复位操作(按复位按钮,调用复位函数),STM32就会跳转到“中断向量表”中的地址0x0000_0004处执行已经写好的Rest_Hander处理函数,该函数使用汇编语言写的,在LiteOS中的如下位置“liteos\arch\arm\arm-m\armv7-m\gcc\los_startup.S”,

1.  Reset_Handler:  

2.      cpsid   i  

3.      ldr     sp, =_estack            /* set msp, as it is not set in the vector */  

4.    

5.  #if defined (__VFP_FP__) && !defined(__SOFTFP__)    /* if FPU exist. */  

6.      /* enable FPU */  

7.    

8.      ldr     r0, =0xE000ED88  

9.      ldr     r1, [r0]  

10.     orr     r1, r1, #(0xf << 20)                    /* enable cp10 cp11 both */  

11.     str     r1, [r0]  

12. #endif  

13.   

14.     /* init the data section */  

15.   

16.     ldr     r1, =_sdata  

17.     ldr     r2, =_edata  

18.     ldr     r3, =_sidata  

19. 0:  

20.     cmp     r1, r2  

21.     beq     0f  

22.     ldr     r0, [r3], #4  /* _sidata地址对应内存中的数据读到r0中,并将_sidata地址加4 */

23.     str     r0, [r1], #4  /* R0中的数据写到_sdata地址对应内存中,并将_sdata地址加4 */

24.     b       0b  

25. 0:  

26.   

27.     /* init the bss section */  

28.   

29.     mov     r0, #0  

30.     ldr     r1, =_sbss  

31.     ldr     r2, =_ebss  

32. 0:  

33.     cmp     r1, r2  

34.     beq     0f  

35.     str     r0, [r1], #4  

36.     b       0b  

37. 0:  

38.     bl      SystemInit  

39.     bl      __libc_init_array  

40.     bl      main  

41.   

42.     b       .  

43.   

44. .size  Reset_Handler, . - Reset_Handler 

第2行:关闭所有中断,等价于PRIMASK=1

第3行:读取栈顶指针并赋值给sp寄存器,这个“_estack”符号的值定义在链接脚本中,os.ld文件* 中,取决于芯片RAM大小。

image.png

第5~11行,MPU初始化,暂不讲解。

第16行,将_sdata段的起始地址赋值给r1寄存器

第17行,将_edata段的起始地址赋值给r2寄存器

第18行,将_sidata段的起始地址赋值给r3寄存器

上面这三个符号的值都来自于os.ld文件中,_sdata~_edata之间的空间用于存放全局变量的值,所以在初始化中,需要将这块空间清0。

image.png

image.png

       第19~24行,首先使用cmp     r1, r2判断r1和r2寄存器中的值是否相等也就是_sdata和_edata的值是否相等,一开始肯定不相等,就不执行跳到0f地址处的这条指令了,注意:0f和0b这样写法你们可能很少见,0是标签0,就是代码块前面的那个0,我们的这个文件中有很多为0的标签,所以就通过b=backward和f=forward来区分是跳到后面的标签0处还是前面的标签0处,前面和后面不好区分,可以根据back单词有返回的含义来进行区分。

总体看来19~24行就是一个for循环,判断退出循环的条件是_sdata和_edata的值是否相等,在循环中将全局变量的数据从flash拷贝到ram的加载地址对应空间中。

ldr R0,[R3],#4 ;将存储器地址为R3的字数据读入寄存器R0,并将R3+4的值存入R3。

str R0,[R1],#4 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+4写入R1

       第29-36行,采用上面的类似于“for循环”的方法将.bss段清0.

       第37-40行,执行SystemInit函数,用C语言在外部实现的,执行__libc_init_array函数,执行我们的main函数,单片机就转起来了!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。