应用内程序从用户引导加载程序跳转到用户应用程序,反之亦然,在STM32F446RE板上

如何解决应用内程序从用户引导加载程序跳转到用户应用程序,反之亦然,在STM32F446RE板上

我有一个问题。 我正在为我的STM32F446RE开发板开发一个IAP(应用程序内编程)工具,但遇到了麻烦。 我已经开发了所有必需的实用程序,以使微控制器能够从GUI接收二进制(.bin)编译文件,将其写入特定的闪存扇区并执行它。 我的问题来自从上传的代码中我想再次跳转到存储在闪存扇区0上的引导程序,我看到代码没有跳转至引导程序,而是继续执行用户应用程序代码。我已经调试了代码,发现引导加载程序代码的所有地址(msp和重置处理程序)都已正确设置,并且与上载的代码不同。

我要实现的流程如下:

1->执行存储在扇区0上的引导程序代码(从用户按钮收到中断时,从地址0x0800 0000开始)并将新接收的代码写入扇区2(从地址0x0800 8000开始)

2->设置msp地址(@ 0x0800 8000)和重置处理程序地址(0x0800 8004)

3->跳转到新代码的重置处理程序地址(@ 0x0800 8004)

4->执行新上传的代码。

5->在执行用户代码期间,如果收到中断(来自用户按钮),则设置引导加载程序的msp地址,复位处理程序并跳转到引导加载程序

6->从第一步开始再次重复。

这是用于从引导加载程序跳转到用户应用程序的代码:

    IAP_loadProgram(&data);

//pointer to the user application reset handler address
void (*user_resetHandler)(void);


//set the user application MSP address (user application starts on the flash SECTOR2
uint32_t msp_addr = *(volatile uint32_t *)APPLICATION_ADDRESS;

__set_MSP(msp_addr);

//Set now the addres of the reset handler
uint32_t resetAddr = *(volatile uint32_t *)(APPLICATION_ADDRESS + 4);

user_resetHandler = (void *)resetAddr;

//When there,the bootloader sector will be leaved and the user code execution starts
user_resetHandler();

最后,用于从用户应用程序代码跳转到引导加载程序的代码是:

  if(toBootloader){
      toBootloader = 0;

      //pointer to the user application reset handler address
      void (*bootLoader_resetHandler)(void);

      //set the user application MSP address (user application starts on the flash SECTOR2
      uint32_t msp_addr = *(volatile uint32_t *)BOOTLOADER_ADDRESS;

     __set_MSP(msp_addr);

      //Set now the address of the reset handler
      uint32_t bootLoaderResetAddr = *(volatile uint32_t *)(BOOTLOADER_ADDRESS + 4);

      bootLoader_resetHandler = (void *)bootLoaderResetAddr;

      //When there,the user code sector will be leaved and the bootloader code execution starts
      bootLoader_resetHandler();
  }

其中APPLICATION_ADDRESS为0x0800 8000,而BOOTLOADER_ADDRESS为0x0800 0000。 引导加载程序代码的前两个地址的内容为: 0x08000000:20020000
0x08000004:080044DD

同时,应用程序代码的前两个地址的内容为: 0x08008000:20020000
0x08008004:0800A1F1

我所做的最后修改是在用户应用程序链接器(.ld)文件上,在该文件中,我将Flash起始地址设置为地址0x0800 8000(而不是地址0x0800 0000)。

所有中断都正常工作,并且在上载代码之后,如果我进行硬件复位,结果是相同的,代码执行从用户应用程序代码开始,而不是从引导程序开始。 有提示吗?

解决方法

您的问题描述不清楚,但是调用该应用程序的程序远远不够。您需要确保应用程序的环境与uC重置后的环境相同。您还需要更改向量表地址。

我写了几十个引导程序,但我不理解你的问题

这里有一个示例,说明如何完成此操作(从引导加载程序调用应用程序)

void startAPP(void)
{
    static uint32_t *pAppPosition;
    static voidFunc *appResetHandler;
    static uint32_t newSP;

    pAppPosition = (uint32_t *)(bankStartAddress[0] + (uint32_t)&_BOOTFlashSize);
    appResetHandler = (voidFunc *)pAppPosition[1];
    newSP = pAppPosition[0];

    SPI_DeInit();
    FLASH_DeInit();
    I2C_DeInit();
    IRQ_DeInit();
    GPIO_DeInit();

    __disable_irq();
    __set_MSP(newSP);
    __enable_irq();
    SCB -> ICSR = 0x00000000;   // reset value;
    SCB -> SCR = 0;
    SCB -> CCR = 0x00000200;    // reset value
    SCB -> SHP[0] = 0;
    SCB -> SHCSR = 0;
    SCB -> CFSR = (SCB_CFSR_DIVBYZERO_Msk | SCB_CFSR_UNALIGNED_Msk | SCB_CFSR_UNDEFINSTR_Msk | SCB_CFSR_NOCP_Msk | SCB_CFSR_INVPC_Msk | SCB_CFSR_INVSTATE_Msk);
    SCB -> HFSR = (SCB_HFSR_DEBUGEVT_Msk | SCB_HFSR_FORCED_Msk | SCB_HFSR_VECTTBL_Msk);
    SCB -> VTOR = bankStartAddress[0] + (uint32_t)&_BOOTFlashSize;  // new vector table pos. I od not clear 8 LSB because APP start position is aligned to FLASH Sectors which are at least 2k aligned

    // SysTick
    SysTick -> CTRL = 0;
    SysTick -> LOAD = 0;
    SysTick -> VAL  = 0;

    appResetHandler();

    __builtin_unreachable();
}
,

从应用程序运行引导加载程序的最简单,最安全的方法就是使用CMSIS NVIC_SystemReset()函数发出软复位。

if( toBootloader )
{
    NVIC_SystemReset() ;
}

通过直接调用跳转到引导加载程序是不必要的,也是不明智的。尽管可以做到,就像您可以从引导加载程序跳到应用程序一样,您至少需要禁用中断/异常并将向量表从应用程序的表切换到引导加载程序的表。您的应用程序代码和引导加载程序代码都没有这样做。例如,请参见ARM: How to Write a Bootloader

发出复位的优点是将处理器以及所有片上外围设备和I / O设置为已知的复位状态,因此您无需担心初始化NVIC或任何可能产生中断的外围设备在切换向量表时。

如果您需要从应用程序向引导加载程序传递信息,则片上SRAM的状态将在复位过程中幸免,因此您可以保留空间,以使运行时启动不会初始化以将参数传递给启动程序。引导加载程序。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-