实战技能分享,一劳永逸的解决BOOT跳转APP失败问题,含MDK AC5,AC6和IAR,同时制作了一个视频操作说明

本文主要是介绍实战技能分享,一劳永逸的解决BOOT跳转APP失败问题,含MDK AC5,AC6和IAR,同时制作了一个视频操作说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

视频操作讲解说明

文字版讲解

背景知识:

解决办法:

MDK AC5设置:

IAR设置:

案例下载:


视频操作讲解说明

实战技能分享,一劳永逸的解决BOOT跳转APP失败问题,含MDK AC5,AC6和IAR

文字版讲解

背景知识:

BOOT跳转到APP,就跟我们程序里面函数调用跳转是一样的,并不会复位外设,需要用户手动去操作。导致我们BOOT跳转APP经常会遇到这样那样的问题,根本原因还是BOOT跳转前没有提供一个干净的环境给APP运行,这个环境如果可以达到和程序刚上电时的状态是最好的。
一般情况下,大家的跳转程序应该是下面这种玩法,各种倒腾中断,外设复位等,那个遗漏了,在APP里面都会有意想不到的效果。

static void JumpToApp(void)
{uint32_t i=0;void (*SysMemBootJump)(void);        /* 声明一个函数指针 */__IO uint32_t BootAddr = 0x08100000; /* STM32H7的系统BootLoader地址 *//* 关闭全局中断 */DISABLE_INT(); /* 关闭滴答定时器,复位到默认值 */SysTick->CTRL = 0;SysTick->LOAD = 0;SysTick->VAL = 0;/* 设置所有时钟到默认状态,使用HSI时钟 */HAL_RCC_DeInit();/* 关闭所有中断,清除所有中断挂起标志 */for (i = 0; i < 8; i++){NVIC->ICER[i]=0xFFFFFFFF;NVIC->ICPR[i]=0xFFFFFFFF;}        /* 使能全局中断 */ENABLE_INT();/* 跳转到系统BootLoader,首地址是MSP,地址+4是复位中断服务程序地址 */SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));/* 设置主堆栈指针 */__set_MSP(*(uint32_t *)BootAddr);/* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */__set_CONTROL(0);/* 跳转到系统BootLoader */SysMemBootJump(); /* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */while (1){}
}

解决办法:

我们跳转前,人为的做一个跳转操作,提供一个干净的运行环境,思路框图如下:

 

框图含义:我们的正常BOOT里面有各种操作,跳转前逐个复位太繁琐,经常会有各种遗漏没考虑到,特别是BOOT里面用到了,APP也用到的外设。

那么我们就可以人为的执行一个软件复位,复位后直接跳转到APP即可,这里就有一个核心,就是我们要设置一个不被编译器初始化的变量,我们可以BOOT和APP里面都使用。

 

MDK AC5设置:

AC5设置设置最简单,定义下即可。

uint32_t g_JumpInit __attribute__((at(0x20000000), zero_init));


MDK AC6设置:

uint32_t g_JumpInit __attribute__( ( section( ".bss.NoInit"))); 


分享加载设置:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00200000  {    ; load region size_regionER_IROM1 0x08000000 0x00200000  {  ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO)}RW_IRAM1 0x20000000 UNINIT 0x00000004  {  ; RW data - 128KB DTCM*(.bss.NoInit)}RW_IRAM2 0x24000000 0x00080000  {  ; RW data - 512KB AXI SRAM.ANY (+RW +ZI)}
}

IAR设置:

定义:

#pragma location = ".NoInit"  
uint32_t g_JumpInit;

分散加载设置:

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__     = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__       = 0x081FFFFF;
define symbol __ICFEDIT_region_RAM_start__     = 0x24000000;
define symbol __ICFEDIT_region_RAM_end__       = 0x2407FFFF;
define symbol __ICFEDIT_region_ITCMRAM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ITCMRAM_end__   = 0x0000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000;
define symbol __ICFEDIT_size_heap__   = 0x800;
/**** End of ICF editor section. ###ICF###*/define memory mem with size = 4G;
define region ROM_region      = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region      = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];
define region ITCMRAM_region  = mem:[from __ICFEDIT_region_ITCMRAM_start__ to __ICFEDIT_region_ITCMRAM_end__];
define region NoInit_region  = mem:[from 0x20000000 to 0x20000004];define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };initialize by copy { readwrite };
do not initialize  { section .noinit };place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };place in ROM_region   { readonly };
place in RAM_region   { readwrite,block CSTACK, block HEAP };
place in NoInit_region  {section .NoInit};do not initialize  { section .NoInit };

案例下载:

APP.7z (2.58MB)

BOOT.7z (2.59MB)
 

这篇关于实战技能分享,一劳永逸的解决BOOT跳转APP失败问题,含MDK AC5,AC6和IAR,同时制作了一个视频操作说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Redis多种内存淘汰策略及配置技巧分享

《Redis多种内存淘汰策略及配置技巧分享》本文介绍了Redis内存满时的淘汰机制,包括内存淘汰机制的概念,Redis提供的8种淘汰策略(如noeviction、volatile-lru等)及其适用场... 目录前言一、什么是 Redis 的内存淘汰机制?二、Redis 内存淘汰策略1. pythonnoe

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

Linux中shell解析脚本的通配符、元字符、转义符说明

《Linux中shell解析脚本的通配符、元字符、转义符说明》:本文主要介绍shell通配符、元字符、转义符以及shell解析脚本的过程,通配符用于路径扩展,元字符用于多命令分割,转义符用于将特殊... 目录一、linux shell通配符(wildcard)二、shell元字符(特殊字符 Meta)三、s

linux报错INFO:task xxxxxx:634 blocked for more than 120 seconds.三种解决方式

《linux报错INFO:taskxxxxxx:634blockedformorethan120seconds.三种解决方式》文章描述了一个Linux最小系统运行时出现的“hung_ta... 目录1.问题描述2.解决办法2.1 缩小文件系统缓存大小2.2 修改系统IO调度策略2.3 取消120秒时间限制3

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB