上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解)

本文主要是介绍上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        学习stm32代码的时候,关于汇编文件,大家一般都会参考官方给出的汇编文件。通常情况下,不会自己去写汇编文件。特别是汇编文件的最后一行,大家都会把__main看成是直接进入main函数。后面通过反汇编,发现情况并不是这样的。我们编写代码,除了keil工程中的内容,还有MicroLib库,这一点常常被我们忽视。

1、之前的汇编代码

; Reset handler
Reset_Handler   PROCEXPORT  Reset_Handler             [WEAK]IMPORT  __mainIMPORT  SystemInitLDR     R0, =SystemInitBLX     R0               LDR     R0, =__mainBX      R0ENDP

        汇编代码这部分呢,大家一般都不会陌生,我们也通常都认为是__main直接跳转到了自定义的main函数。但是实际情况,我们可以通过反汇编来确认。

2、如何生成反汇编文件

        在项目的User tab配置中,添加这样的命令,就可以在project下面生成dis文件,

fromelf --text -a -c --output=Fire_F103VE.dis ../Output/Fire_F103VE.axf

        这样在最后的axf生成的同时,也能生成dis文件。如果需要生成bin文件,也是类似的做法。

fromelf --bin --output Fire_F103VE.bin ../Output/Fire_F103VE.axf

3、找到Reset_Handler位置

        首先我们找到Reset_Handler位置,

    __Vectors0x08000000:    20000410    ...     DCD    5368719520x08000004:    08000145    E...    DCD    1342180530x08000008:    08000d81    ....    DCD    134221185

        一般向量的第二个选项就是reset入口,不过mcu很奇怪,入口地址都要减去1才是正确的地址。也就是说,这里的Reset_Handler其实是08000144,

    Reset_Handler0x08000144:    4806        .H      LDR      r0,[pc,#24] ; [0x8000160] = 0x8000e170x08000146:    4780        .G      BLX      r00x08000148:    4806        .H      LDR      r0,[pc,#24] ; [0x8000164] = 0x80001310x0800014a:    4700        .G      BX       r0

        我们发现了,这边pc最后跳转的地址是8000131,因为需要减去1,那就是8000130,

    _main_stk0x08000130:    f8dfd00c    ....    LDR      sp,__lit__00000000 ; [0x8000140] = 0x20000410.ARM.Collect$$$$00000004_main_scatterload0x08000134:    f000f82a    ..*.    BL       __scatterload ; 0x800018c

        这边执行不久,就跳转到了__scatterload,

    __scatterload__scatterload_rt20x0800018c:    4c06        .L      LDR      r4,[pc,#24] ; [0x80001a8] = 0x8000ec40x0800018e:    4d07        .M      LDR      r5,[pc,#28] ; [0x80001ac] = 0x8000ee40x08000190:    e006        ..      B        0x80001a0 ; __scatterload + 200x08000192:    68e0        .h      LDR      r0,[r4,#0xc]0x08000194:    f0400301    @...    ORR      r3,r0,#10x08000198:    e8940007    ....    LDM      r4,{r0-r2}0x0800019c:    4798        .G      BLX      r30x0800019e:    3410        .4      ADDS     r4,r4,#0x100x080001a0:    42ac        .B      CMP      r4,r50x080001a2:    d3f6        ..      BCC      0x8000192 ; __scatterload + 60x080001a4:    f7ffffc8    ....    BL       __main_after_scatterload ; 0x8000138

        快结束的时候,又跳转到了__main_after_scatterload,

    __main_after_scatterload_main_clock_main_cpp_init_main_init0x08000138:    4800        .H      LDR      r0,[pc,#0] ; [0x800013c] = 0x8000e750x0800013a:    4700        .G      BX       r0

        这边貌似要回到main函数了,看这里的地址是8000e75,那就是8000e74,

    i.mainmain0x08000e74:    bf00        ..      NOP      0x08000e76:    f7ffff9e    ....    BL       SystemClock_Config ; 0x8000db60x08000e7a:    f7ffff2b    ..+.    BL       LED_GPIO_Config ; 0x8000cd40x08000e7e:    e012        ..      B        0x8000ea6 ; main + 500x08000e80:    2200        ."      MOVS     r2,#00x08000e82:    f44f5100    O..Q    MOV      r1,#0x20000x08000e86:    4808        .H      LDR      r0,[pc,#32] ; [0x8000ea8] = 0x400110000x08000e88:    f7fffb4a    ..J.    BL       HAL_GPIO_WritePin ; 0x80005200x08000e8c:    f44f707a    O.zp    MOV      r0,#0x3e80x08000e90:    f7fff992    ....    BL       HAL_Delay ; 0x80001b80x08000e94:    2201        ."      MOVS     r2,#10x08000e96:    0351        Q.      LSLS     r1,r2,#130x08000e98:    4803        .H      LDR      r0,[pc,#12] ; [0x8000ea8] = 0x400110000x08000e9a:    f7fffb41    ..A.    BL       HAL_GPIO_WritePin ; 0x80005200x08000e9e:    f44f707a    O.zp    MOV      r0,#0x3e80x08000ea2:    f7fff989    ....    BL       HAL_Delay ; 0x80001b80x08000ea6:    e7eb        ..      B        0x8000e80 ; main + 12

        看到上面的代码,大约可以验证到我们的猜测了。

4、总结

        之前在做linux soc芯片汇编文件编写的时候,中断初始化、bss初始化、sp初始化、已初始化全局变量copy、main函数跳转,这些都是基本的内容。后面自己看mcu代码的时候,却没有发现这部分内容,当时觉得很诧异,直到后来自己看了axf文件的反汇编内容之后,才晓得ide和背后的编译器帮我们做了很多事情。刚才说的这一切,都在main函数调用之前准备好了。但恰恰这一点,对于我们debug调试、分析和boot 加载研究很有帮助。

这篇关于上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1015886

相关文章

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)