實戰技能分享,一勞永逸的解決BOOT跳轉APP失敗問題,含MDK AC5,AC6和IAR,同時制作了一個視頻操作說明


視頻操作講解說明:

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 };


案例下載:

APP.7z (2.58MB)
BOOT.7z (2.59MB)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM