STM32 BootLoader 刷新项目 (九) 跳转指定地址-命令0x55

STM32 BootLoader 刷新项目 (九) 跳转指定地址-命令0x55

前面我们讲述了几种BootLoader中的命令,包括获取软件版本号、获取帮助、获取芯片ID、读取Flash保护Level。

下面我们来介绍一下BootLoader中最重要的功能之一—跳转!就像BootLoader词汇中的Boot一词一样,就是启动跳转。

首先我们来介绍一下Boot跳转的应用。

1. BootLoader跳转指定地址的应用

STM32的BootLoader中跳转指定地址的应用场景主要包括以下几个方面:

  1. 固件升级(Firmware Upgrade)

    • BootLoader允许在不改变硬件连接的情况下进行固件的在线升级。当新的固件版本需要部署到设备上时,BootLoader可以接收新的固件并将其烧录到指定的Flash地址,然后跳转到新固件的执行地址,从而实现固件的无缝更新。
  2. 多应用管理(Multi-Application Management)

    • 在一些复杂的应用中,可能需要在同一个设备上运行多个应用程序。BootLoader可以通过跳转到不同的地址来选择性地加载和执行不同的应用程序,实现多应用的管理。
  3. 系统恢复(System Recovery)

    • 如果设备在运行过程中出现软件故障,BootLoader可以作为一个恢复点,通过跳转到备份的固件地址来恢复系统的正常运行。
  4. 安全启动(Secure Boot)

    • 在安全敏感的应用中,BootLoader可以检查固件的合法性,确保只有经过认证的固件才能被加载执行。这可以通过跳转到经过签名验证的固件地址来实现。
  5. 调试和测试(Debugging and Testing)

    • 在开发和测试阶段,BootLoader可以方便地进行程序的调试和测试。开发者可以通过BootLoader跳转到不同的测试固件地址,快速验证新功能或修复bug。
  6. 节省资源(Resource Saving)

    • 对于资源受限的嵌入式系统,BootLoader可以减少对外部存储器的需求,通过内部Flash存储固件,节省成本和空间。
  7. 产品差异化(Product Differentiation)

    • 通过BootLoader,制造商可以为不同的市场或客户定制不同的固件版本,通过跳转到不同的固件地址来实现产品的差异化。
  8. 远程维护(Remote Maintenance)

    • BootLoader支持远程固件更新,使得设备的维护和升级可以在不接触硬件的情况下完成,这对于远程或难以接触的设备尤为重要。

这些应用场景展示了BootLoader在STM32微控制器中的灵活性和重要性,它们使得设备能够更加智能、安全和易于维护。

2. 函数跳转的方法

在STM32的BootLoader中跳转到指定地址通常涉及到以下几个步骤:

  1. 验证目标地址:确保目标地址是有效的,并且位于应用程序的合法执行区域内。
  2. 设置堆栈指针:将堆栈指针(MSP)设置为应用程序的初始堆栈值。
  3. 跳转到应用程序:使用函数指针或者直接修改程序计数器(PC)来跳转到应用程序的入口点。

下面是一个详细的代码示例,包括注释,解释每一步的作用:

#include "stm32f10x.h" // 包含STM32F10x系列的头文件// 假设应用程序的入口地址存储在特定的Flash地址
#define APP_ENTRY_ADDR   (0x08005000) // 应用程序的入口地址// 跳转到应用程序的函数
void Jump_To_Application(void) {volatile uint32_t *appEntryAddr; // 指向应用程序入口地址的指针void (*Reset_Handler)(void);      // 应用程序的Reset_Handler函数指针// 将appEntryAddr指向存储应用程序入口地址的位置appEntryAddr = (uint32_t *) APP_ENTRY_ADDR;// 检查应用程序入口地址是否有效// 这里简单地检查地址是否在Flash范围内,实际应用中可能需要更复杂的检查if ((*appEntryAddr & 0x2FFE0000) == 0x08000000) {// 读取应用程序的入口地址uint32_t appStartAddr = *appEntryAddr;// 将Reset_Handler函数指针指向应用程序的Reset_HandlerReset_Handler = (void (*)(void)) appStartAddr;// 设置堆栈指针为应用程序的初始堆栈值// 这通常是应用程序入口地址的下一个地址__set_MSP(*((volatile uint32_t *) appStartAddr + 1));// 关闭所有中断NVIC->ICER[0] = 0xFFFFFFFF; // 禁用所有中断NVIC->ICPR[0] = 0xFFFFFFFF; // 清除所有中断挂起位// 跳转到应用程序的Reset_HandlerReset_Handler();} else {// 应用程序入口地址无效,可以在这里处理错误while(1) {// 错误处理代码}}
}
代码解释:
  • 包含头文件:包含STM32F10x系列的头文件,以便使用STM32的寄存器定义和宏。
  • 定义应用程序入口地址APP_ENTRY_ADDR是存储应用程序入口地址的位置。
  • 跳转到应用程序的函数Jump_To_Application函数执行跳转到应用程序的操作。
  • 指向应用程序入口地址的指针appEntryAddr指向存储应用程序入口地址的位置。
  • 应用程序的Reset_Handler函数指针Reset_Handler是一个函数指针,指向应用程序的Reset_Handler函数。
  • 检查应用程序入口地址是否有效:通过检查地址是否在Flash范围内来验证地址的有效性。
  • 读取应用程序的入口地址:从appEntryAddr读取应用程序的实际入口地址。
  • 设置堆栈指针:将MSP设置为应用程序的初始堆栈值,通常是应用程序入口地址的下一个地址。
  • 关闭所有中断:禁用所有中断并清除所有中断挂起位,以确保跳转过程中不会被中断干扰。
  • 跳转到应用程序的Reset_Handler:通过Reset_Handler函数指针跳转到应用程序的Reset_Handler函数,开始执行应用程序代码。

这个代码示例展示了如何在BootLoader中跳转到应用程序的入口地址,包括地址验证、堆栈指针设置和实际的跳转操作。在实际应用中,你可能需要根据具体的硬件和应用程序需求调整这些步骤。

3. 0x55命令介绍–地址跳转

在本篇文章,我们的主要是介绍0x55的命令,这个命令主要是在BootLoader中让程序跳转到指定地址。

通过上位机发送10 Byte的数据,其中第1 Byte为整个数据的长度,第2Byte为指令码,第3-6 Byte为跳转的地址,第7-10 Byte为前6个Byte的CRC校验值。上位机通过串口UART发送给下位机,下位机回复地址是否跳转成功的标志。

image-20241108071213198

下面是整个程序执行地址跳转的流程图:

BootLoader_Flow_Go_address

4. 程序设计

下面我们来进行程序设计,下面是读取上位机指令,并解析指令的过程,通过switch case判断执行哪种命令。目前通过上位机执行BL_GO_TO_ADDR指令,然后执行bootloader_handle_go_cmd(bl_rx_buffer)函数。

void  bootloader_uart_read_data(void)
{uint8_t rcv_len=0;printmsg_Host("BL_DEBUG_MSG: Receive CMD\n\r");while (1){HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);memset(bl_rx_buffer, 0, 200);//here we will read and decode the commands coming from host//first read only one byte from the host , which is the "length" field of the command packetHAL_UART_Receive(C_UART,bl_rx_buffer,1,HAL_MAX_DELAY);rcv_len= bl_rx_buffer[0];HAL_UART_Receive(C_UART,&bl_rx_buffer[1],rcv_len,HAL_MAX_DELAY);switch(bl_rx_buffer[1]){case BL_GET_VER:bootloader_handle_getver_cmd(bl_rx_buffer);break;case BL_GET_HELP:bootloader_handle_gethelp_cmd(bl_rx_buffer);break;case BL_GET_CID:bootloader_handle_getcid_cmd(bl_rx_buffer);break;case BL_GET_RDP_STATUS:bootloader_handle_getrdp_cmd(bl_rx_buffer);break;case BL_GO_TO_ADDR:bootloader_handle_go_cmd(bl_rx_buffer);break;default:printmsg("BL_DEBUG_MSG:Invalid command code received from host \n");break;}}
}

下面是地址跳转函数,通过过去输入的Buffer进行解析出跳转地址,判断跳转地址是否在正确的跳转范围内,如果在正确的跳转范围内,则向上位机发送能够跳转的回复,之后执行地址跳转。如果不在跳转范围内,则向上位机回复,地址不正确,请重新输入。

/*Helper function to handle BL_GO_TO_ADDR command */
void bootloader_handle_go_cmd(uint8_t *pBuffer)
{uint32_t go_address=0;uint8_t addr_valid = ADDR_VALID;uint8_t addr_invalid = ADDR_INVALID;printmsg("BL_DEBUG_MSG:bootloader_handle_go_cmd\n");//Total length of the command packetuint32_t command_packet_len = bl_rx_buffer[0]+1 ;//extract the CRC32 sent by the Hostuint32_t host_crc = *((uint32_t * ) (bl_rx_buffer+command_packet_len - 4) ) ;if (! bootloader_verify_crc(&bl_rx_buffer[0],command_packet_len-4,host_crc)){printmsg("BL_DEBUG_MSG:checksum success !!\n");bootloader_send_ack(pBuffer[0],1);//extract the go addressgo_address = *((uint32_t *)&pBuffer[2] );printmsg("BL_DEBUG_MSG:GO addr: %#x\n",go_address);if( verify_address(go_address) == ADDR_VALID ){//tell host that address is finebootloader_uart_write_data(&addr_valid,1);/*jump to "go" address.we dont care what is being done there.host must ensure that valid code is present over thereIts not the duty of bootloader. so just trust and jump *//* Not doing the below line will result in hardfault exception for ARM cortex M *///watch : https://www.youtube.com/watch?v=VX_12SjnNhYgo_address+=1; //make T bit =1void (*lets_jump)(void) = (void *)go_address;printmsg("BL_DEBUG_MSG: jumping to go address! \n");lets_jump();}else{printmsg("BL_DEBUG_MSG:GO addr invalid ! \n");//tell host that address is invalidbootloader_uart_write_data(&addr_invalid,1);}}else{printmsg("BL_DEBUG_MSG:checksum fail !!\n");bootloader_send_nack();}
}

5. 实战演练

下面是上位机的命令菜单,通过在终端调用Python脚本,然后在终端输入下位机连接的串口号,即可进入命令界面,目前可支持如下命令:

image-20240713104433991

在上位机中输入命令5,即为在BootLoader中执行地址跳转命令0x55,MCU根据读取跳转地址0xXXXXXXXX的值,来进行跳转,并告诉上位机能否跳转成功,由下图可以看出,当前地址跳转成功。

image-20241108080343013

目前我在STM32中刷了两段程序,其中BootLoader程序即为0x0800 0000-0x0800 7FFF处,后面0x08000 8000-0x080F FFFF为APP应用程序,则当我将跳转地址设为0x0800 8000时,MCU则会从BootLoader跳转进入到APP应用程序中。

image-20240621072216733

但为什么我们在输入跳转指令地址为0x08008000的时候,并没有跳转到App程序呢,下面我通过Hex和大家解释一下。

下面我们用STM32官方提供的工具STM32CubeProgrammer工具读取MCU中的Hex信息。

Note:必须在连接ST-Link的时候才能显示Hex信息。

image-20241108075809602

由上图我们可以看出在0x08008000地址开始处,其中第一个地址0x0800 8000地址中的值时0x20020000,这个值时Reset Handle,即中断向量表的起始地址。第二个地址0x0800 8004中的值才是实际App程序所在的Flash地址。

所以在下图中,我们执行地址跳转指令0x55,跳转地址设为0x0800 8B16,为什么比0x0800 8B15多1呢,这是因为我们使用的Thumb指令,执行的指令结尾必须+1.

image-20241108080707845

下面我们通过串口监控一下Mcu是否跳转成功,由下图可以看出,MCU成功跳转到App程序中。

image-20241108081055946

6. 系列文章

STM32 BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建

STM32 BootLoader 刷新项目 (二) 方案介绍

STM32 BootLoader 刷新项目 (三) 程序框架搭建及刷新演示

STM32 BootLoader 刷新项目 (四) 通信协议

STM32 BootLoader 刷新项目 (五) 获取软件版本号-命令0x51

STM32 BootLoader 刷新项目 (六) 获取帮助-命令0x52

STM32 BootLoader 刷新项目 (七) 获取芯片ID-0x53

STM32 BootLoader 刷新项目 (八) 读取Flash保护ROP-0x54

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

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

相关文章

sqlite3数据库的相关API使用

1 1:使用sqlite3_exec函数读取数据库的数据,将这些数据存入链表遍历该链表&#xff0c;输出“字段”“数据”2:使用sqlite3_get_table读取数据库的数据写一个“字段" "数据”输出的循环 1 #include <stdio.h> #include <string.h> #include <unistd.…

基于Python下载HYCOM-3hourly数据(可无脑用)

基于Python下载HYCOM-3hourly数据 一、安装库二、主要函数2.1 draw_time_range2.2 download2.2.1 下载函数2.2.2 必传入参数&#xff1a;2.2.3 其他参数&#xff1a; 2.3 merge5nc 三、完整代码3.1 乱七八糟版3.2 精简版3.3 get_time_list 四、效果4.1 终端4.2 nc文件4.3 全文本…

Hbase集群搭建

1. 环境 三台节点hadoop 集群zookeeper 集群hbase 1.1环境准备 使用前文hdfs三台节点 1.11 zookeeper搭建 下载 wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz解压 tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz zookee…

为什么用SQL而不是Excel+VBA?

SQL主要服务数据库 SQL服务的是MySQL、Oracle、SQL Sever、Hive等各大数据库&#xff0c;它们都需要SQL来管理、定义。题主理解的SQL只限于查询数据、清洗数据&#xff0c;这些当然ExcelVBA都能做到&#xff0c;任何编程语言都能做到&#xff0c;但事实是SQL是数据库的管理工具…

Android OpenGL ES详解——纹理:纹理过滤GL_NEAREST和GL_LINEAR的区别

目录 一、概念 1、纹理过滤 2、邻近过滤 3、线性过滤 二、邻近过滤和线性过滤的区别 三、源码下载 一、概念 1、纹理过滤 当纹理被应用到三维物体上时&#xff0c;随着物体表面的形状和相机视角的变化&#xff0c;会导致纹理在渲染过程中出现一些问题&#xff0c;如锯齿…

OpenHarmony4.1蓝牙芯片如何适配?触觉智能RK3568主板SBC3568演示

当打开蓝牙后没有反应时&#xff0c;需要排查蓝牙节点是否对应、固件是否加载成功&#xff0c;本文介绍开源鸿蒙OpenHarmony4.1系统下适配蓝牙的方法&#xff0c;触觉智能SBC3568主板演示 修改对应节点 开发板蓝牙硬件连接为UART1&#xff0c;修改对应的节点&#xff0c;路径为…

Kafka高频面试题详解

1、kafka是如何做到高效读写 1&#xff09;Kafka 本身是分布式集群&#xff0c;可以采用分区技术&#xff0c;并行度高 2&#xff09;读数据采用稀疏索引&#xff0c;可以快速定位要消费的数据。&#xff08;mysql中索引多了之后&#xff0c;写入速度就慢了&#xff09; 3&a…

ML 系列: 第 23 节 — 离散概率分布 (多项式分布)

目录 一、说明 二、多项式分布公式 2.1 多项式分布的解释 2.2 示例 2.3 特殊情况&#xff1a;二项分布 2.4 期望值 &#xff08;Mean&#xff09; 2.5 方差 三、总结 3.1 python示例 一、说明 伯努利分布对这样一种情况进行建模&#xff1a;随机变量可以采用两个可能的值&#…

MFC工控项目实例三十实现一个简单的流程

启动按钮夹紧 密闭&#xff0c;时间0到平衡 进气&#xff0c;时间1到进气关&#xff0c;时间2到平衡关 检测&#xff0c;时间3到平衡 排气&#xff0c;时间4到夹紧开、密闭开、排气关。 相关代码 void CSEAL_PRESSUREDlg::OnTimer_2(UINT nIDEvent_2) {// if (nIDEvent_21 &am…

当使用key-value方式进行参数传递时,若key对应的是一个对象或数组结构,如何利用API Post工具进行模拟操作。

1. 后端服务代码如下 RequestMapping("/handle11")public Person handle11(Person person){System.out.println(person);return person;} 2. 后端入参结构 person是一个对象&#xff0c;对象结构如下&#xff1a; public class Person {private String username …

MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并

MySQL技巧之跨服务器数据查询&#xff1a;基础篇-A数据库与B数据库查询合并 上一篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的链接名: MY_ODBC_MYSQL 以…

人工智能赋能快递物流,基于YOLOv3全系列【tiny/l/spp】参数模型开发构建物流分拣场景下快递包裹智能检测计数系统

随着电商互联网的迅猛发展&#xff0c;消费者的购物习惯发生了翻天覆地的变化&#xff0c;网购已成为日常生活不可或缺的一部分。这一趋势直接推动了快递物流行业的快速扩张&#xff0c;每天都有数以亿计的包裹在全球范围内流转。然而&#xff0c;传统的快递点物流包裹分拣工作…

Nginx中实现流量控制(限制给定时间内HTTP请求的数量)示例

场景 流量控制 流量限制 (rate-limiting)&#xff0c;可以用来限制用户在给定时间内HTTP请求的数量。 流量限制可以用作安全目的&#xff0c;比如可以减慢暴力密码破解的速率&#xff0c; 更常见的情况是该功能被用来保护上游应用服务器不被同时太多用户请求所压垮。 流量…

【ARM Coresight OpenOCD 系列 5 -- arp_examine 使用介绍】

文章目录 OpenOCD arp_examine 使用 OpenOCD arp_examine 使用 因为我们很多时候运行 Openocd 的时候有些 core 还没有启动, 所以最好在配置脚本中添加 -defer-examine这个参数, 如下&#xff1a; #cortex-m33 target create ${_CHIPNAME}.m33 cortex_m -dap ${_CHIPNAME}.da…

【AI新领域应用】AlphaFold 2,原子级别精度的蛋白质3D结构预测,李沐论文精读(2021Nature封面,2024诺贝尔奖)

文章目录 AlphaFold 2 —— 原子级别精度的蛋白质3D结构预测背景&#xff08;2024诺奖与AI学习资料&#xff09;1、摘要、导论、写作技巧2、方案&#xff1a;模型&#xff0c;编码器&#xff0c;解码器3、实验&#xff1a;数据集&#xff0c;训练&#xff0c;结果 AlphaFold 2 …

微服务day06

MQ入门 同步处理业务&#xff1a; 异步处理&#xff1a; 将任务处理后交给MQ来进行分发处理。 MQ的相关知识 同步调用 同步调用的小结 异步调用 MQ技术选型 RabbitMQ 安装部署 其中包含几个概念&#xff1a; publisher&#xff1a;生产者&#xff0c;也就是发送消息的一方 …

[ Linux 命令基础 2 ] Linux 命令详解-系统管理命令

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

Linux:vim命令总结及环境配置

文章目录 前言一、vim的基本概念二、vim模式命令解析1. 命令模式1&#xff09;命令模式到其他模式的转换&#xff1a;2&#xff09;光标定位&#xff1a;3&#xff09;其他命令&#xff1a; 2. 插入模式3. 底行模式4. 替换模式5. 视图模式6. 外部命令 三、vim环境的配置1. 环境…

【在Linux世界中追寻伟大的One Piece】多路转接epoll

目录 1 -> I/O多路转接之poll 1.1 -> poll函数接口 1.2 -> poll的优点 1.3 -> poll的缺点 1.4 -> poll示例 1.4.1 -> 使用poll监控标准输入 2 -> I/O多路转接之epoll 2.1 -> 初识epoll 2.2 -> epoll的相关系统调用 2.2.1 -> epoll_cre…

JS爬虫实战之TikTok_Shop验证码

TikTok_Shop验证码逆向 逆向前准备思路1- 确认接口2- 参数确认3- 获取轨迹参数4- 构建请求5- 结果展示 结语 逆向前准备 首先我们得有TK Shop账号&#xff0c;否则是无法抓取到数据的。拥有账号后&#xff0c;我们直接进入登录。 TikTok Shop 登录页面 思路 逆向步骤一般分为…