實戰技能分享,一勞永逸的解決BOOT跳轉APP失敗問題,含MDK AC5,AC6和IAR,同時製作了一個視訊操作說明
阿新 • • 發佈:2021-11-17
視訊操作講解說明:
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 };微信公眾號:armfly_com 安富萊論壇:www.armbbs.cn 安富萊淘寶:https://armfly.taobao.com