MCU启动文件小解一下

news2024/12/28 5:34:39

GD32启动文件分析

  • 启动文件的一些指令
  • .s启动文件分析
    • 栈空间分配
    • 堆空间管理
    • 中断向量表定义
    • 堆空间定义
    • Reset_Handler复位程序
    • HardFault_Handler
    • _main文件分析
    • 用户堆栈初始化

GD32启动文件主要做了以下工作:
初始化SP=_initial_sp , PC=Reset_Handler指针,设置堆栈大小,初始化中断向量表,调用SystemInit,_main,最终调用到main函数。

启动文件的一些指令

指令名称作用
EQU给数字常量取一个符号名,相当于 C 语言中的 define
AREA汇编一个新的代码段或者数据段
ALIGN编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示 4 字节对齐。要注意的是,这个不是 ARM 的指令,是编译器的,这里放到一起为了方便。
SPACE分配内存空间
PRESERVE8当前文件堆栈需要按照 8 字节对齐
THUMB表示后面指令兼容 THUMB 指令。在 ARM 以前的指令集中有 16 位的THUMBM 指令,现在 Cortex-M 系列使用的都是 THUMB-2 指令集,THUMB-2 是 32 位的,兼容 16 位和 32 位的指令,是 THUMB 的超级版。
EXPORT声明一个标号具有全局属性,可被外部的文件使用
DCD以字节为单位分配内存,要求 4 字节对齐,并要求初始化这些内存
PROC定义子程序,与 ENDP 成对使用,表示子程序结束
WEAK弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不会出错。要注意的是,这个不是 ARM 的指令,是编译器的,这里放到一起为了方便。
IMPORT声明标号来自外部文件,跟 C 语言中的 extern 关键字类似
LDR从存储器中加载字到一个存储器中
BLX跳转到由寄存器给出的地址,并根据寄存器的 LSE 确定处理器的状态,还要把跳转前的下条指令地址保存到 LR
BX跳转到由寄存器/标号给出的地址,不用返回
B跳转到一个标号
IF,ELSE,ENDIF汇编条件分支语句,跟 C 语言的类似
END到达文件的末尾,文件结束

主要是一些arm指令,ARM指令还能够从keil的IDE ->help 里找到
在这里插入图片描述
在这里插入图片描述

.s启动文件分析

栈空间分配

在这里插入图片描述EQU:宏定义的伪指令,给数字常量取一个符号名,类似与 C 中的 define。定义栈大小为 0x00000400 字节,即 1024B(1KB),常量的符号是 Stack_Size。
AREA: 汇编一个新的代码段或者数据段。段名为 STACK,段名可以任意命名;
NOINIT 表示不初始化; READWRITE 表示可读可写;ALIGN=3,表示按照 2^3 对齐,
即 8 字节对齐。
SPACE 分配内存指令,分配大小为 Stack_Size 字节连续的存储单元给栈空间。
__initial_sp 紧挨着 SPACE 放置,表示栈的结束地址,栈是从高往低生长,所以结束地址就是栈顶地址。
通过map文件查看栈的initial_sp可以看到恰好栈由栈顶高地址到低地址是0x400
在这里插入图片描述

堆空间管理

在这里插入图片描述
开辟堆的大小
为 0x00000000(0 字节),段名为 HEAP,不初始化,可读可写,8 字节对齐。__heap_base表示堆的起始地址,__heap_limit 表示堆的结束地址。堆和栈的生长方向相反的,堆是由低向高生长,而栈是从高往低生长。
这里我这只为0,因为我用了freertos里heap的方式进行内存管理,就不用系统默认的堆了,因为malloc缺点比较多,容易造成较大的内存碎片。

堆可以用于动态内存分配,比如通过malloc()、calloc()和 realloc()等函数
malloc() 函数在堆上分配参数size字节大小的内存,并返回指向新分配内存起始位置处的指针,其所分配的内存未经初始化。
calloc() 函数用于给一组相同对象分配内存。参数mumitems指定分配对象的数量,size指定每个对象的大小与malloc()不同,calloc()会将已分配的内存初始化为0。
realloc() 函数用来调整(通常是增加)一块内存的大小
在这里插入图片描述
PRESERVE8:指示编译器按照 8 字节对齐。
THUMB:指示编译器之后的指令为 THUMB 指令。

中断向量表定义

在这里插入图片描述
定义一个数据段,名字为 RESET, READONLY 表示只读。EXPORT 表示声明一个标号
具有全局属性,可被外部的文件使用。这里是声明了__Vectors、__Vectors_End 和__Vectors_Size 三个标号具有全局性,可被外部的文件使用。
当内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。为了决定 ESR的入口地址, 内核使用了向量表查表机制。向量表其实是一个 WORD(32 位整数)数组。
每个下标对应一种异常,该下标元素的值则是该 ESR 的入口地址。
在复位后,该寄存器的值为 0。因此,在地址 0 (即 FLASH 地址 0) 处必须包含一张向量表,用于初始时的异常分配。
当然,我们如果说有bootloader的话,我们的起始地址将不会在0,这时候就需要通过 NVIC 中的一个重定位寄存器来指出向量表的地址。
在这里插入图片描述

转载自正点原子启动文件解析
举个例子,如果发生了异常 SVCall,则 NVIC 会计算出偏移移量是 11x4=0x2C,然后从那里取出服务例程的入口地址并跳入。要注意的是这里有个另类:地址 0x0000 0000 并不是什么入口地址,而是给出了复位后 MSP 的初值。
灰色部分是系统内核中断,后面就是用户的中断。

堆空间定义

接下来是定义只读代码段,定义一个段命为.text,只读的代码段,在 CODE 区。
在这里插入图片描述

Reset_Handler复位程序

在这里插入图片描述
PROC、ENDP 一对伪指令作为程序的起始和结束。
通过EXPORT 和 week 来声明其全局属性,同时将其声明为弱函数,外部可以定义覆盖。
IMPORT 表示SystemInit和__main来自外部文件。
LDR表示将Systeminit和_main存储到寄存器R0中。
BLX 表示跳转到由寄存器给出的地址,并根据寄存器的 LSE 确定处理器的状态,还要把跳转前的下条指令地址保存到 LR。
BX 表示跳转到由寄存器/标号给出的地址,不用返回。这里表示切换到__main地址,最终调用 main 函数,不返回,进入 C 的世界。

HardFault_Handler

在这里插入图片描述
若定义了HardFault_Handler,则执行我们自己的HardFault_Handler,若没有定义,则运行B . 这条汇编,进行原地跳转。
其他的中断也是如下。
在这里插入图片描述

_main文件分析

当看到__main 函数时,估计有不少人认为这个是 main 函数的别名或是编译之后的名字,
否则在启动代码中再也无法找到和 main 相关的字眼了。可事实是,_main 和 main 是两个完全不同的函数。_main 代码是编译器自动创建的,因此无法找到_main 代码。MDK 文档中有一句说明:it is automatically craated by the linker when it sees a definition of main() 。大体意
思可以理解为:当编译器发现定义了 main 函数,那么就会自动创建_main。
程序经过汇编启动代码,执行到__main()后,可以看出有两个大的函数:
__scatterload():负责把 RW/RO 输出段从装载域地址复制到运行域地址,并完成了 ZI运行域的初始化工作。
1._scatterload_null:判断r10和r11是否相等,不相等就跳到_scatterload_copy
2._scatterload_copy 复制好之后,在会到_scatterload_null判断是否相等,相等后进入__scatterload_zeroinit
3.__scatterload_zeroinit:对ZI段进行清零,最后跳回__scatterload
然后跳转到__rt_entry()

__rt_entry() :负责初始化堆栈,完成库函数的初始化,最后自动跳转向 main()函数。
先调用 __user_setup_stackheap 函数,然后调用__user_libspace进行一些微库的初始化,最后到__user_setup_stackheap初始化堆栈,调用__rt _entry_main最后回到main。
在这里插入图片描述

用户堆栈初始化

在这里插入图片描述
ALIGN 表示对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示4 字节对齐。
首先判断是否定义了__MICROLIB。关于__MICROLIB 这个宏定义,我们是在 KEIL里面配置。
在这里插入图片描述
如果定义__MICROLIB,声明__initial_sp、__heap_base 和__heap_limit
这三个标号具有全局属性,可被外部的文件使用。__initial_sp 表示栈顶地址,__heap_base表示堆起始地址,__heap_limit 表示堆结束地址。
没有定义__MICROLIB,实际的情况就是我们没有定义__MICROLIB,所以使用默认的 C 库运行。堆栈的初始化由 C 库函数__main 来完成。
IMPORT 声明__use_two_region_memory 标号来自外部文件。
EXPORT 声明__user_initial_stackheap 具有全局属性,可被外部的文件使用。
标号__user_initial_stackheap,表示用户堆栈初始化程序入口。
接下来进行堆栈空间初始化,堆是从低到高生长,栈是从高到低生长,是两个互相独立的数据段,并且不能交叉使用。
保存堆起始地址。
保存栈大小。
保存堆大小。
保存栈顶指针。
跳转到 LR 标号给出的地址,不用返回。
END 表示到达文件的末尾,文件结束。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1415764.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

眼底增强型疾病感知蒸馏模型 FDDM:无需配对,fundus 指导 OCT 分类

眼底增强型疾病感知蒸馏模型 FDDM:fundus 指导 OCT 分类 核心思想设计思路训练和推理 效果总结子问题: 疾病特定特征的提取与蒸馏子问题: 类间关系的理解与建模 核心思想 论文:https://arxiv.org/pdf/2308.00291.pdf 代码:https://github.c…

C#调用SqlSugar操作达梦数据库报错“无效的表或视图名”

安装达梦数据库后,使用SqlSugar连接测试数据库并基于DBFirst方式创建数据库表对应的类,主要代码如下: SqlSugarClient db new SqlSugarClient(new ConnectionConfig(){DbType DbType.Dm,ConnectionString "Serverlocalhost; User Id…

Redis3-秒杀活动

秒杀 准备工作 我是参照下面这位大佬的i骄傲成下载的 csdn友情链接 Jmeter模拟多线程的压力测试工具 秒杀代码: package com.aaa.controller;import io.netty.util.internal.StringUtil; import org.apache.commons.lang.StringUtils; import org.springfram…

YoloV8改进策略:BackBone改进|DCNv4最新实践|高效涨点|多种改进教程|完整论文翻译

摘要 涨点效果:在我自己的数据集上,mAP50 由0.986涨到了0.993,mAP50-95由0.737涨到0.77,涨点明显! DCNv4是可变形卷积的第四版,速度和v3相比有了大幅度的提升,但是环境搭建有一定的难度,对新手不太友好。如果在使用过程遇到编译的问题,请严格按照我写的环境配置。 …

【GitHub项目推荐--不错的 TypeScript 学习项目】【转载】

在线白板工具 Excalidraw 标星 33k,是一款非常轻量的在线白板工具,可以直接在浏览器打开,轻松绘制具有手绘风格的图形。 如下图所示,Excalidraw 支持最常用的图形元素:方框、圆、菱形、线,可以方便的使用…

51-17 视频理解串讲— MViT 论文精读

继TimeSformer模型之后,咱们再介绍两篇来自Facebook AI的论文,即Multiscale Vision Transformers以及改进版MViTv2: Improved Multiscale Vision Transformers for Classification and Detection。 由于本司大模型组最近组织阅读的论文较多,…

文献翻译 || Ubuntu安装zotero文献管理软件,提高文献阅读效率

文章目录 前言安装方式选择apt方式snap方式 zotero的简单使用文献导入中文翻译插件下载并安装使用体验 前言 虽然在win下有很多文献管理软件和好用的文献翻译软件,但是如果平常有使用Ubuntu进行开发的需求,实际上很不愿意为了好好看文献专门切到Windows…

HarmonyOS鸿蒙学习基础篇 - 通用事件

一、引言 HarmonyOS鸿蒙是华为推出的分布式操作系统,旨在为各种智能设备提供统一的操作系统。鸿蒙系统的一大特色是其强大的分布式能力,而通用事件则是实现这一能力的关键技术之一,本篇博客将介绍HarmonyOS鸿蒙中的通用事件。 二、 点击事件…

圈子论坛社交实名制系统---H5小程序APP,三端源码交付,允许二开!PHP系统uni书写!

圈子系统是一种社会化网络平台,它的核心是以用户为中心,围绕用户的兴趣、爱好、经历和职业等因素,将具有相同特质的个体聚集起来,形成具有共同话题和兴趣的社交圈子。这样的系统旨在帮助用户拓宽社交范围,提升社交效率…

Vue基知识六

一 vuex 1.1 简介 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。 1.2 何时使用…

【代码】使用预训练的语义分割网络

P274书上的代码,这里是从ipynb文件中按顺序复制来的: 使用到的图片如下: 代码: import numpy as np import pandas as pd import matplotlib.pyplot as plt import PIL import torch from torchvision import transforms impor…

华为机考入门python3--(4)牛客4-字符串分隔

分类:字符串 知识点: 复制符号* 复制3个0 0*3 000 字符串截取 截取第i位到j-1位 str[i:j] 题目来自【牛客】 input_str input().strip()# 先补齐 if len(input_str) % 8 ! 0: input_str 0 * (8 - len(input_str) % 8) # 每8个分 out…

嵌入式软件工程师面试题——2025校招社招通用(C/C++)(四十四)

说明: 面试群,群号: 228447240面试题来源于网络书籍,公司题目以及博主原创或修改(题目大部分来源于各种公司);文中很多题目,或许大家直接编译器写完,1分钟就出结果了。但…

win10通过ssh链接deepin23并开启x11转发

前提 主机环境:win10 lstc 虚拟机环境:deepin23beta2 终端:tabby x11服务器: vcxsrv 安装ssh sudo apt install ssh开启root登录(看你需求) 首先你要给root账号设置密码 sudo passwd root修改配置文件 sudo vim /etc/ssh/ss…

源聚达科技:抖店的专营店怎么开

在数字化浪潮的推动下,抖音平台不仅为人们提供了丰富的娱乐内容,也成为了电商的新战场。不少创业者和品牌商纷纷选择在抖音上开设自己的专营店,以此抓住流量红利,拓宽销售渠道。那么,如何在抖音平台上成功开设一家专营…

Redis实现多种限流算法

一 常见限流算法 1 固定窗口限流 每一个时间段计数器,当计数器达到阈值后拒绝,每过完这个时间段,计数器重置0,重新计数。 优点:实现简单,性能高; 缺点:明显的临界问题&#xff0c…

PBM模型学习(五)UDF生长模型

DEFINE_PB_GROWTH_RATE(name, cell, thread, d_i) 该UDF在每个时间步开始时执行,只有在时间步开始时,颗粒粒径才会更新,同时才会UDF才会向文件写入数据GR单位是m/sC_PHASE DIAMETER(c,ts):返回颗粒粒径???,ts为颗粒相的线程C_VOF(cell,thread):颗粒相总体积C_PB DISCI(c…

在DevEco开发工具中,使用Previewer预览界面中的UI组件

1、在DevEco工具中,点击并展开PreViewer预览器 2、在PreViewer预览器中,点击Tt按钮(Inspector)切换至组件查看模式 3、在组件查看模式下选择组件,代码呈现选中状态,右侧呈现组件树,右下方呈现组…

FLStudio21.2.2国内中文版本怎么下载?

FL studio简称FL,全称:Fruity Loops Studio。在中国我们习惯叫它"水果"。它让你的计算机就像是全功能的音乐工作站,大混音盘,非常先进的制作工具,让你的音乐突破想象力的限制。 FL Studio主要功能 1、FL St…

Authorization Failed You can close this page and return to the IDE

一.问题描述 注册JetBrains成功,并且通过了学生认证,但在activate pycharm时,却显示Authorization Failed You can close this page and return to the IDE如上图 二.原因: 可能是因为之前使用了破解版pycharm 三.解决方法&am…