基于STM32F030的程序跳转后跑飞问题以及IAP配置细节

本文详细描述了在基于STM32F030的IAP(在应用编程)过程中遇到的程序跳转后跑飞问题及其解决方法。关键问题在于中断向量表的正确配置以及RAM空间分配,作者通过关闭中断、调整RAM分配和深入理解中断向量映射解决了问题。此外,还分享了STM32F0的IAP远程更新配置细节。
AI助手已提取文章相关产品:

程序跳转后跑飞 关键问题描述:

(只想看IAP细节配置的可以往下拉,前面的问题分析跳过)

IAP远程更新程序配置无误,且程序能程序跳转。但跳转后程序总是在固定的程序段跑飞重启设备。

尝试过的办法:

1、怀疑中断向量表重映射地址不对应,由于M0内核的特殊性,是把中断向量复制到RAM上,就各种方案尝试分配RAM区。

结果如下图:

RAM1必须是0x200000B4开头,因为stm32f030的中断向量表只有45个中断向量,每个向量地址是32位的即4个字节,45*4=0xB4,因此RAM必须留出0XB4空间存储中断向量,且RAM空间必须连续,因此RAM1要从0x20000000+B4开始。

如果不按照上面这个做,某些中断会发送错误(以我的工程是发生了各种奇怪的错误,只有像上面这样的配置才不会中断错误)

2、怀疑是程序烧录过程的问题。因为我是boot工程和APP工程都是在KEIL5上直接编译然后用ST-LINK V2一个个烧录的。后面我把boot程序的main函数只留一行代码,就是进入main就直接跳转程序到app,结果app正常运行,不会跑飞。

证明:多个工程文件只要地址不重叠可以编译后通过ST-LINK V2一个一个烧录到单片机

这也说明了程序跳转后会跑飞,问题出在boot工程的配置上或者是打开的外设上

3、首先认为是程序跳转前中断关闭未成功。在这个问题上,我踩过下面这个坑,是别的博主写的,可以参考参考:

我一开始是调用HAL库上的这个函数:

void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
{
  /* Check the parameters */
  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
  
  /* Disable interrupt */
  NVIC_DisableIRQ(IRQn);
}一个个关闭中断,结果一样未解决问题。

后面看见有博主说为了以防万一要关闭所有曾经打开的外设,我就如下关闭了所有曾经使能的外设,包括GPIO:

    IWDG_WINDOW_DISABLE;
    __HAL_RCC_GPIOF_CLK_DISABLE();
  __HAL_RCC_GPIOA_CLK_DISABLE();
  __HAL_RCC_GPIOB_CLK_DISABLE();
    __HAL_RCC_TIM3_CLK_DISABLE();
    __HAL_RCC_USART3_CLK_DISABLE();
    __HAL_RCC_USART2_CLK_DISABLE();
    __HAL_RCC_USART1_CLK_DISABLE();
    __HAL_RCC_USART4_CLK_DISABLE();问题一样没有解决,现象也是没变化。

4、回到了问题的关键又诡异的现象——程序总是在固定的程序段跑飞

再加上之前分析的,问题出现在boot工程上,那就很可能是boot工程配置有问题,尤其是在内存地址分配上。因为把boot工程的main程序删减就没问题所以我猜想假设是boot工程上的一些程序地址和APP上重复了,所以APP一运行到这个程序就卡住跑飞,但又因为查看程序地址ROM分配是没重叠的,那所以重叠的部分是不是在RAM分配上?因为程序运行不仅仅需要ROM寻址找到需要运行的程序地址,还需要RAM支持程序运行工程中产生、处理数据。APP工程的RAM分配不能变只能像上面第1点描述的那样。boot工程RAM原来是如下图这样分配的(直接把所有RAM都用上,因为当时觉得程序跳转后,RAM可以自动初始化)

后来我把boot工程的RAM分配修改成这样:

我特意把RAM1这个从0x2000000B8开始比0x2000000B4大一个字的空间,就是避免boot工程的RAM空间APP工程的中断向量复制后所在的RAM地址(0x200000000—0x2000000B4)有一丁点重叠。ROM空间也是,避免了与APP工程的有一丁点重叠。

我不知道问题本质是不是这个原因(抛砖引玉,望各位大佬评论区指教),但是我做到这里,所描述的问题立马解决了。

基于STM32F0的IAP远程更新配置细节

1、去ST官网参考ST官方文档:Jumping_topic_about_different_procedure_code_zone_based_on_STM32F0.pdf

2、STM32F0的IAP远程更新配置步骤相同,但是具体配置会根据不同具体单片机型号有差异,比如中断向量的重映射,我的单片机是stm32f030,中断向量__Vectors 除了栈顶就45个,而官方文档举例的时候是有48个,就是下面这段绿色的代码,在我的情况下需要把48改成45:

还有其他的差异需要自己去挖掘。挖掘办法就是用文档等资料描述的内容在stm32底层固件上找到验证,就上面所说的中断向量重映射的不同型号单片机的差异我就是在stm32f030启动文件上发现的

3、程序跳转前,必须关闭所有中断,不能贪图方便直接关总中断然后在APP程序再打开总中断,必须一个个去关闭,即使总中断开着也是无所谓的,至于为什么,我上面的问题分析里已经给了参考。如果关闭中断后发现还是出现问题或者说是没关闭成功,如果你对这个关闭中断的库函数底层不熟悉建议操作寄存器关闭中断,且关闭中断前再把中断标志位清除。因为程序跳转后不会把中断以及其他外设寄存器状态位重置,只有单片机复位才会重置。

最后,真的真的太不容易了,本来以为可以在优快云里站在巨人的肩膀上,但这个问题的解决方案,我也是两天两夜没找到对我有用,都是自己自己一步一步去分析,烧录了几十上百次代码尝试的结果,如果大家觉得我的解决方案有用,有能力的可以支持一下,觉得我的一般般或者不好也欢迎大佬评论区指教,活到老学到老!

您可能感兴趣的与本文相关内容

在Windows Server上设置WebSocket服务器通常需要使用支持WebSocket功能的服务器端框架,如Node.js的WS库或Microsoft的ASP.NET Core。以下是使用Node.js作为示例的简要步骤: 1. **安装Node.js**: 首先确保你已经安装了Node.js,如果没有,访问https://nodejs.org/ 下载并按照官方文档安装。 2. **创建项目**: 打开命令提示符或PowerShell,进入你想创建项目的目录,然后运行 `npm init -y` 初始化一个新的Node.js项目。 3. **安装WebSocket库**: 使用 `npm install ws` 命令安装ws模块,它是一个流行的用于WebSocket通信的库。 4. **编写服务器代码**: 在项目根目录创建一个名为 `server.js` 或其他名字的文件,然后添加如下基本WebSocket服务器代码: ```javascript const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', (ws) => { console.log('Client connected'); ws.on('message', (message) => { console.log(`Received: ${message}`); // 发送回客户端的消息 ws.send(`You said: ${message}`); }); ws.on('close', () => { console.log('Client disconnected'); }); }); ``` 5. **启动服务**: 运行 `node server.js` 启动WebSocket服务器。此时,服务器将在8080端口监听WebSocket连接。 6. **启用HTTPS**: 如果你需要HTTPS,你需要获取SSL证书并将它们放置在合适的路径,可以使用像Let's Encrypt这样的免费证书颁发机构。然后使用像`https-server`之类的工具,例如: ``` npm install https-server https-server -p 443 -c ./path/to/cert.pem -k ./path/to/key.pem ``` 注意:上面的过程涉及到命令行操作,并且HTTPS部分需要额外的SSL证书管理,如果你对这些操作不熟悉,可能需要查阅相关的技术文档或寻求专业帮助。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值