1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
启动文件:
startup_stm32f40_41xxx.s Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size SPACE和DCD的区别在于: SPACE和DCD的功能类似,SPACE申请一片内存空间,DCD申请一个字(32bit)的内存空间。 SPACE和DCD的区别在于,SPACE申请空间但不赋初值,DCD申请一个字的空间,并赋初值。 AREA 语法格式: AREA 段名 属性1 ,属性2 ,…… AREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用“|”括起来,如:|1_test| 。 属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下: — CODE 属性:用于定义代码段,默认为READONLY 。 — DATA 属性:用于定义数据段,默认为READWRITE 。 — READONLY 属性:指定本段为只读,代码段默认为READONLY 。 — READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE 。 — ALIGN 属性:使用方式为ALIGN表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。 — COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元。 一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。 使用示例: AREA Init ,CODE ,READONLY ; 该伪指令定义了一个代码段,段名为Init ,属性为只读。 NOINIT 指示数据节未初始化,或初始化为零。 它只包含空间保留指令 SPACE 或初始化值为零的DCB、DCD、DCDU、DCQ、DCQU、DCW 或 DCWU。 您可以在链接时决定某区域是未初始化还是初始化为零(请参阅《RealView 编译工具链接器和实用程序指南》中的第 3 章 使用基本链接器功能) 设置初始SP 设置初始PC=Reset_Handler 设置向量表入口地址,并初始化向量表 调用SystemInit,把系统时钟配制成72M,SystemInit在库文件system_stm32f10.c定义 调转到标号_main,最终来到C程序文件 ; Reset handler Reset_Handler PROC // reset_hander子程序 EXPORT Reset_Handler [WEAK] //供其他模块调用 IMPORT SystemInit //其他模块供自己调用 IMPORT __main //同上 LDR R0, =SystemInit //把SystemInit 的地址加载到寄存器R0。 BLX R0 //程序跳转到R0 中的地址执行程序,之后系统的时钟就被设置成72MHZ LDR R0, =__main //把_main 的地址加载到寄存器R0 BX R0 //程序跳转到R0 中的地址执行程序,执行完毕之后就去到我们熟知的C 世界 ENDP //表示子程序的结束 PROC 是子程序定义伪指令。一般用法为: 1 子程序名PROC NEAR ( 或FAR ) 2 …… 3 ret 4子程序名ENDP 其中NEAR 和FAR 是属性词。 NEAR属性(段内近调用): 调用程序和子程序在同一代码段中,只能被相同代码段的其他程序调用。 FAR属性(段间远调用):调用程序和子程序不在同一代码段中,可以被相同或不同代码段的程序调用。 ———————————————— 版权声明:本文为CSDN博主「燕无鸻」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_43836778/article/details/108330898 上面是对基本的arm指令找到一些解释 可能并不能具体说明启动过程下面在总结下 .S 文件中基本定义了各个段的定义 但是没有具体的实际地址,汇编中各个标号的偏移地址跟编译链接后的地址是两个不同的概念 但是经过编译器的重定向后才编程我们需要的地址 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp ; ; ; Heap_Size EQU 0x00000200 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit PRESERVE8 THUMB ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler 据上图可以看到,_initial_sp栈顶指针和向量表起始地址均未设置。 默认情况下,cortex-m0+内核认为该表位于零地址处,且各向量占用4 字节,因此每个表项占用4 字节 重定向后: 中断向量表里的中断跳转地址在编译后就定下来了,SCB->VTOR向量 可动态调整就是让我们的程序运行后还能改变向量的跳转地址。方法就是:在RAM 重建一个中断向量表,在想改变的位置重新赋值新的跳转地址 要想实现Flash程序跳转和SRAM程序跳转,第一步先设置SCB->VTOR向量,重置中断向量表的起始地址(不是默认的0x00000000了),其中_DSB()为数据同步隔离、_ISB()为指令同步隔离(确保接下来的所有指令都使用新配置)。 以上为改变中断向量表起始地址,经过_DSB()和_ISB()指令后接下来要给这些地址指针重新赋值,也就是在FlashLoader_ASM()和SRAMLoader_ASM()被调函数中重新配置MSP和PC的值。 以SJ_FLASH_BASE=0x10000000,SJ_SRAM_BASE=0x20000000为例: 以上两个函数均是将SJ_FLASH_BASE或SJ_SRAM_BASE地址处存储的值赋给SP ,再将地址值偏移4字节后得到的地址里存储的值给PC 上面过程类似启动文件中中断向量表里提到的Reset_Handler,也是先给_initial_sp 栈顶指针赋值中断向量表起始地址,然后地址偏移4 字节程序跳转到启动文件后面定义的Reset_Handler函数执行如下: 区别只不过是_main和SystemInit代表的是入口地址常量,而前者是直接操作地址值。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1777 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1080 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1678 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
595浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
554浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 12:06 , Processed in 0.721446 second(s), Total 46, Slave 40 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号