【Bootloader学习理解----跳转优化异常】

笔者接着来介绍一下Bootloader的跳转代码以及优化

1、跳转代码理解

跳转代码可能要涉及到芯片架构的知识,要跳转到对应的位置,还要设置相关的SP 堆栈指针,具体可以参考笔者这篇文章BootLoader的理解与实现。
STM32的跳转代码如下所示:

u32 ApplicationAddress = 0x08008000;  //app 地址 
typedef  void (*pFunction)(void);     //函数指针
void Jump_Used_Main(void)
{printf("\r\nboot2-------- Jump APP --------- \r\n");/*	判断栈顶 是否位于 0x20000000  128K 	  */if (  ((*(__IO uint32_t*)ApplicationAddress) >= 0x20000000) &&((*(__IO uint32_t*)ApplicationAddress) <= 0x20010000)){ 	JumpAddress = *(__IO uint32_t*) (ApplicationAddress +4);Jump_To_Application = (pFunction) JumpAddress;/*close the interrupt*/_disable_interrupr();__set_MSP(*(__IO uint32_t*) ApplicationAddress);Jump_To_Application();}else{			while(1){printf("\r\nboot2  error\r\n");}}
}

可以看到__set_MSP(* (__IO uint32_t *) ApplicationAddress);这行代码中,在取地址里面的内容时,增加了__IO的选项,

#define __IO volatile

保证是从内存里面读出来的SP栈指针的数据,然后设置到MSP,否则可能导致SP设置错误,程序跑飞。

2、跳转代码编译优化

笔者在实际开发的过程中,遇到了一个跳转过去就崩掉的情况,单步调试,发现到Set_MSP就崩掉了,很是奇怪,通过汇编一查看,就很明显了。

  • NXP LPC的单片机,
  • arm-noen-eabi-gcc的编译器。
typedef struct addr_manager_struct
{xxxxxxx;u32 image_load_addr;u32 image_exec_addr;
}addr_manager_t;
u8 main_jump(addr_manager_t* info)
{u32 *image_addr = (u32*)info->image_load_addr;u32 *sp = (u32*) image_addr [0];u32 *jump = (u32*) image_addr [1];disable_interrupt();set_msp((u32)sp);(*jump)();return 0;
}

在这里插入图片描述

  • 上述在设置完SP之后,放到r2寄存器里面,
  • 然后获取jump地址,放到r3里面,
  • 之后禁止中断修改了r2,然后禁止中断
  • 然后就把r2传到SP里面,
  • 造成跑飞,可能是一个不存在的地址

有人说sp设置的时候需要加volatile,即使改成下面的函数,也没用效果

void jump_main(addr_manager_t* info)
{u32 *image_addr = (u32*)info->image_load_addr;u32 *sp = (u32*) image_addr [0];u32 *jump = (u32*) image_addr [1];disable_interrupt();set_msp((volatile u32)sp);(*jump)();
}

在这里插入图片描述
接着再继续改,直

  • 接通过Image指针取内容,然后去获取到SP值,然后就可以了,
  • 看来是禁止中断的这个函数所影响,
  • 禁止中断如果不报存返回值,则不会对SP的值产生影响
void jump_main(addr_manager_t* info)
{u32 *image_addr = (u32*)info->image_load_addr;u32 *sp = (u32*) image_addr [0];u32 *jump = (u32*) image_addr [1];disable_interrupt();set_msp(*((volatile u32*)image_addr));(*jump)();
}

在这里插入图片描述
接着我们再尝试一种方法,就是将禁止中断函数移动位置,看一下情况,发现也是可以的。

void jump_main(addr_manager_t* info)
{disable_interrupt();u32 *image_addr = (u32*)info->image_load_addr;u32 *sp = (u32*) image_addr [0];u32 *jump = (u32*) image_addr [1];set_msp((u32)sp);(*jump)();
}

在这里插入图片描述
然后我们看一下set sp的汇编函数,也并没有指明操作的寄存器,很可能是GCC编译器优化的bug。

inline void set_sp(u32 sp_value)
{asm volatile ("msr msp, %0" : "=r"(sp_value))
}

然后我们再看看armcc编译器的结果,没有任何问题。

  • armcc对于禁止中断的返回值没有处理,
  • 而GCC处理了然后导致了问题(将其中断保存值填到r2里面,然后r2的sp值被覆盖),
  • 其实应用层如果没有对返回值进行处理,即使函数有返回值,编译器优化会将其处理掉。显然GCC的编译器优化做的还是差一点。

在这里插入图片描述

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

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

相关文章

基于以太坊的智能合约开发Solidity(基础篇)

参考教程&#xff1a;基于以太坊的智能合约开发教程【Solidity】_哔哩哔哩_bilibili 1、第一个程序——Helloworld&#xff1a; //声明版本号&#xff08;程序中的版本号要和编译器版本号一致&#xff09; pragma solidity ^0.5.17; //合约 contract HelloWorld {//合约属性变…

Python轴承故障诊断 (四)基于EMD-CNN的故障分类

目录 前言 1 经验模态分解EMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 制作数据集和对应标签 2.3 故障数据的EMD分解可视化 2.4 故障数据的EMD分解预处理 3 基于EMD-CNN的轴承故障诊断分类 3.1 训练数据、测试数据分组&#xff0c;数据分batch 3.2 定义…

stu05-前端的几种常用开发工具

前端的开发工具有很多&#xff0c;可以说有几十种&#xff0c;包括记事本都可以作为前端的开发工具。下面推荐的是常用的几种前端开发工具。 1.DCloud HBuilder&#xff08;轻量级&#xff09; HBuilder是DCloud&#xff08;数字天堂&#xff09;推出的一款支持HTML5的web开发…

硬件开发笔记(十四):RK3568底板电路LVDS模块、MIPI模块电路分析、LVDS硬件接口、MIPI硬件接口详解

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/134634186 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

软考高级备考-系统架构师(机考后新版教材的备考过程与资料分享)

软考高级-系统架构设计师 考试复盘1.考试结果2.备考计划3.个人心得 资料分享 考试复盘 1.考试结果 三科压线过&#xff0c;真是太太太太太太太幸运了。上天对我如此眷顾&#xff0c;那不得不分享下我的备考过程以及一些备考资料&#xff0c;帮助更多小伙伴通过考试。 2.备考…

time模块(python)

一.sleep休眠 [rootrhel8 day04]# vim demo01_time.py import time def banzhuan():print("搬砖")time.sleep(3.5) #让程序休眠3.5秒print("结束")banzhuan()[rootrhel8 day04]# python3 demo01_time.py 搬砖 结束运行时&#xff0c;会发现程序中间暂停…

【3DsMax】制作简单的骨骼动画

效果 步骤 首先准备4个板子模型展开放置好 添加一个4段的骨骼 选中其中的一块板子添加蒙皮命令 在蒙皮的参数面板中&#xff0c;设置每块板子对应哪块骨骼 设置好后你可以发现此时就已经可以通过骨骼来控制模型了 接下来就可以制作动画 点击左下角“时间配置”按钮 设置一下动…

HarmonyOS--ArkTS(1)--基本语法(1)

目录 基本语法概述 声明式UI描述 自定义组件 创建自定义组件 自定义组件的结构--struct &#xff0c;Component&#xff0c;build()函数 生命周期 基本语法概述 装饰器&#xff1a; 用于装饰类、结构、方法以及变量&#xff0c;并赋予其特殊的含义。如上述示例中Entry、C…

VSCode安装与使用

VS Code 安装及使用 1、下载 进入VS Code官网&#xff1a;地址&#xff0c;点击 DownLoad for Windows下载windows版本 注&#xff1a; Stable&#xff1a;稳定版Insiders&#xff1a;内测版 2、安装 双击安装包&#xff0c;选择我同意此协议&#xff0c;再点击下一步 选择你…

【Vulnhub 靶场】【hacksudo: ProximaCentauri】【简单 - 中等】【20210608】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/hacksudo-proximacentauri,709/ 靶场下载&#xff1a;https://download.vulnhub.com/hacksudo/hacksudo-ProximaCentauri.zip 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年06月08日 文件大小&…

【LeetCode:70. 爬楼梯 | 递归 -> 记忆化搜索 -> DP】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【图片版】计算机组成原理考前复习题【第3章 存储系统-2(Cache)】

目录 前言 考前复习题&#xff08;必记&#xff09; 结尾 前言 在计算机组成原理的学习过程中&#xff0c;我们深入探索了计算机系统概述这一重要领域。计算机系统作为现代科技的核心&#xff0c;是整个计算机科学的基石。我们将学到的知识与理论转化为了能够解决现实问题…

如何防止恶意调用和攻击对抖音商品详情API的影响?

防止恶意调用和攻击对抖音商品详情API的影响是开发者和平台必须关注的问题。恶意调用和攻击可能导致服务中断、数据泄露或其他安全问题&#xff0c;对平台和用户造成损失。本文将介绍一些常见的恶意调用和攻击方式&#xff0c;并提出相应的防范措施&#xff0c;以确保抖音商品详…

python画动漫形象(魔法少女小圆晓美焰,super beautiful)

1.源代码 import turtle as te import time WriteStep 15 # 贝塞尔函数的取样次数 Speed 5 Width 600 # 界面宽度 Height 500 # 界面高度 Xh 0 # 记录前一个贝塞尔函数的手柄 Yh 0 def Bezier(p1, p2, t): # 一阶贝塞尔函数 return p1 * (1 - t) p2 * t def Bezier_2(x1…

stu06-VSCode里的常用快捷键

Alt Z&#xff1a;文字自动换行。当一行的文字太长时&#xff0c;可以使用。或者查看→自动换行Alt Shift ↓ &#xff1a;快速复制当前行到下一行Alt Shift ↑ &#xff1a;快速复制当前行到上一行Alt B&#xff1a;在默认浏览器中打开当前.html文件Ctrl Enter&#xf…

端口复用和重映射

一、端口复用 &#xff08;1&#xff09;端口复用概念 端口复用是将一个I/O赋予多个功能&#xff0c;通过设置I/O的工作模式来切换不同的功能。 STM32有很多的内置外设&#xff0c;这些外设的外部引脚都是与GPIO复用的。也就是说&#xff0c;一个GPIO如果可以复用为内置外设的…

《PySpark大数据分析实战》图书上线啦

《PySpark大数据分析实战》图书上线啦 《PySpark大数据分析实战》图书上线啦特殊的日子关于创作关于数据关于Spark关于PySpark关于图书/专栏 《PySpark大数据分析实战》图书上线啦 特殊的日子 不知不觉一转眼入驻CSDN已经满一年了&#xff0c;这真是一个充满意义的特殊的日子&…

sfp8472学习CDR

1,cdr名称解释 因为光信号传输至一定距离的时候,通常是长距离传输,其波形会出现一定程度的失真,接收端接收到的信号是一个个长短不一的脉冲信号,这个时候在接收端,我们就无法得到我们需要的数据。所以,这个时候就需要有信号的再生,信号的再生功能为再放大、再整形和再…

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-2稳定性分析Stability

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-2稳定性分析Stability 0. 序言1. 稳定的分类2. 稳定的对象3. 稳定的系统4. 系统稳定性的讨论5. 补充内容——Transfer Function(传递函数) - nonzero Initial Condition(非零初始…

ubuntu20 安装docker

一.官网安装文档 &#xff08;基本按官方文档安装&#xff09; Install Docker Engine on Ubuntu | Docker Docs 二.安装步骤 1.docker 需要64位操作系统、linux内核要在3.1以上 #uname -r 2.卸载可能存在的旧版本 #sudo apt-get remove docker docker-engine docker-ce …