视频操作讲解说明:
https://www.bilibili.com/video/BV1Vg411T7ph
背景知识:
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_region ER_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 };