• 实战技能分享,一劳永逸的解决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)

  • 相关阅读:
    简述拦截器的工作原理?
    线程安全与非线程安全集合说一下,底层怎么实现的(hashmap,concurrenthashmap)
    表与表之间的关联关系
    手写9x9乘法表,冒泡排序
    主键和外键的区别
    为什么要使用连接池?
    AXI协议中的模棱两可的含义的解释(Cachable和Bufferable)
    ahb时序解析
    amba web
    Register Abstraction(9)
  • 原文地址:https://www.cnblogs.com/armfly/p/15569773.html
Copyright © 2020-2023  润新知