This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于CORTEX-M4的BOOTLOADER的问题(望高手指教,这个问题搞了一个星期了)

你好!

        我现在想在M4上,做一个可以利用SD卡升级用户应用代码的BOOTLOADER,目前M4的型号是LM4F231,

        附件是我的项目工程,项目下有:

        1. bootload : ti boot_loader文件(从StellarisWare拷贝过来,去除了一些UART, USB, ENT,CAN等的升级文件)。

        2. BSP: 系统的硬件初始化。

        3. driver: LCD驱动文件

        4. third_party:FATFS0.7的文件

        5. includes: 包含的头文件。

我的做法如下:

1.     新建一个工程,把TI的BOOTLOADER移入(从StellarisWare拷贝过来),加入FATFS文件系统和SD卡驱动,以及做一些简单的液晶显示(液晶是一个96*64   的单色LCD).

2.     对于FATFS和SD驱动和液晶的显示已经调试OK,我在bootload文件夹下,新建了一个bl_hooks.c的文件,里面的程序如下:

        #include "bl_hooks.h"   /* boot_loader的钩子头文件 */

        #include "bl_config.h"  /*  boot_loader的配置文件*/

         #include "../BSP/bsp.h"          /* 自己写的驱动头函数*/

        void MyHwInitFunc(void)

       {  

                BSP_Init();             //  驱动初始化函数(主要做些GPIO的初始化,SPI的初始化等*/

       }

现在的问题如下:当我把"BSP_Init(); “屏蔽掉,编译正常,DEBUG也正常,但是单我加了这句话,系统编译就出现错误(BSP_Init()没有问题,已经验证过)。

不是只有”BSP_Init()这个函数有问题,只要我加入我自己定义的函数(BSP文件夹下的函数或是third_party下的函数,都会出现编译错误)。

提示如下:

 

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. warning #10278-D: LOAD placement specified for section    ".text:decompress:none:rtsv7M4_T_le_v4SPD16_eabi.lib<copy_decompress_none.ob    j>". This section contains decompression routines required for linker    generated copy tables and C/C++ auto-initialization.  Must ensure that this    section is copied to run address before the C/C++ boot code is executed or    is placed with single allocation specifier (ex. "> MEMORY"). warning #10278-D: LOAD placement specified for section    ".text:rtsv7M4_T_le_v4SPD16_eabi.lib<memcpy_t2.obj>". This section contains    decompression routines required for linker generated copy tables and C/C++    auto-initialization.  Must ensure that this section is copied to run address    before the C/C++ boot code is executed or is placed with single allocation    specifier (ex. "> MEMORY"). warning #10278-D: LOAD placement specified for section    ".text:decompress:ZI:rtsv7M4_T_le_v4SPD16_eabi.lib<copy_zero_init.obj>".    This section contains decompression routines required for linker generated    copy tables and C/C++ auto-initialization.  Must ensure that this section is    copied to run address before the C/C++ boot code is executed or is placed    with single allocation specifier (ex. "> MEMORY"). warning #10278-D: LOAD placement specified for section    ".text:decompress:rle24:rtsv7M4_T_le_v4SPD16_eabi.lib<copy_decompress_rle.ob    j>". This section contains decompression routines required for linker    generated copy tables and C/C++ auto-initialization.  Must ensure that this    section is copied to run address before the C/C++ boot code is executed or    is placed with single allocation specifier (ex. "> MEMORY"). warning #10278-D: LOAD placement specified for section    ".text:rtsv7M4_T_le_v4SPD16_eabi.lib<copy_decompress_rle.obj>". This section    contains decompression routines required for linker generated copy tables    and C/C++ auto-initialization.  Must ensure that this section is copied to    run address before the C/C++ boot code is executed or is placed with single    allocation specifier (ex. "> MEMORY"). table.c:4070:internal fatal error #10220: (".data:mmc-lm4f231e5qr.obj")

INTERNAL ERROR: D:\ti\ccsv5\tools\compiler\tms470\bin\lnk470.exe aborted

This is a serious problem.  Please contact Customer Support with this message and a copy of the input file and help us to continue to make the tools more robust.

>> Compilation failure gmake: *** [sd_bootload.out] Error 1 gmake: Target `all' not remade because of errors.

**** Build Finished ****

在Problems下显示:

#10278-D LOAD placement specified for section

 

看上面的提示,感觉是加入的文件,链接出了问题,但是我的链接文件时拷贝TI例程内的bl_link_ccs.cmd,这个问题如何解决?

望高人指教,这个问题困扰一个星期了,都没办法调通。

我用的是CCS5.1,MCU用的是LM4F231E5QR(256K FLASH, 32K SRAM),

 

 

 

 

 

sd_bootload.rar
  • 楼主的问题很有趣,貌似是楼主调用的FatFS中某些函数用到了rtsv7M4_T_le_v4SPD16_eabi.lib基础库中的某些函数,但linker又不允许这些函数在库未初始化时候使用,于是就强制出错了。


    楼主看到的调用BSP_Init ()出错应该是表象,其实是因为bsp.c调用了disk_timerproc(),所以编译器会试图连接编译FatFS的东西。FatFS中某些函数会用到rtsv7M4_T_le_v4SPD16_eabi.lib中函数,所以就碰到了这个问题(但至于是哪个函数导致的我没有找到)。看起来楼主的程序里似乎也不一定要用到这些rtsv7M4_T_le_v4SPD16_eabi.lib里的函数,所以连接时想办法绕开就行了。


    解决办法是在compiler设置的optimization中把optimization打开就好了(opt_level = 1 or above),这样link时候就不会把所有东西都连接进来了

  • 你好!

           我按你的方法做了,把opt_level 设置为2,可以编译成功,但是出现如下问题:

    1. 编译成功以后,仿真的时候,程序在“ProcessorInit”这个程序里面死掉了,不知道是什么原因。

    2. 由于FATFS需要用到一个定时器,我把系统节拍更改为如下:

     .if $$defined(ENET_ENABLE_UPDATE)

         .ref    SysTickIntHandler

         .word   SysTickIntHandler               ;; Offset 3C: SysTick handler

     .else  

          .if $$defined(SD_ENABLE_UPDATE)

                  .ref Tmr_TickISR_Handler              ;;  我在bl_config.h里面已经定义了SD_ENABLE_UPDATE,这一部分是FATFS需要用到一个定时器中断

                  .word Tmr_TickISR_Handler  

         .else    

                  .word   IntDefaultHandler               ;; Offset 3C: SysTick handler    

         .endif  

    .endif

    编译的窗口提示:

    <Linking>

    warning #10278-D: LOAD placement specified for section   

    ".text:decompress:ZI:rtsv7M4_T_le_v4SPD16_eabi.lib<copy_zero_init.obj>".   

    This section contains decompression routines required for linker generated   

     copy tables and C/C++ auto-initialization.  Must ensure that this section is   

    copied to run address before the C/C++ boot code is executed or is placed   

    with single allocation specifier (ex. "> MEMORY").

    'Finished building target: sd_bootload.out'

     

    上面的编译,是已经把opt_level 设置为2了。

    按提示,有生成“sd_bootload.out',但是,我把”sd_bootload.out'“导入以后,发现很莫名其妙的问题,如附件(本来在”bl_startup_ccs.s“函数下的”b   ResetISR“,

    在汇编的对应窗口,变成了”LSL   R6, R2, #0x4“,很匪夷所思,无法执行。

    3. 通过查阅TI文档,我利用在 .cmd文件下,加入”--zero_init=off“,屏蔽掉”copy_zero_init.obj“的调用,这次可以编译成功,但是出来的代码也是错的。

    请问:是否还有其它办法?我想应该把”copy_zero_init.obj“搞进去,编译可用的可能性比较高。

     

     

  • 优化开了,编译器会自己做些事情,所以有些代码和汇编不会一一对应

    楼主可以把工程中优化还是设置成disable,只有BSP和FatFS两个目录的优化设置为0,也可以的。

  • 你好!

            首先谢谢你的回答。

            但是我现在还是出现了同一个问题:

            由于需要用到一个时间中断函数,我在”bl_startup_ccs.s“下,做了如下更改:

     把

           .if $$defined(ENET_ENABLE_UPDATE)
               .ref    SysTickIntHandler
               .word   SysTickIntHandler               ;; Offset 3C: SysTick handler
          .else

               .word   IntDefaultHandler               ;; Offset 3C: SysTick handler

           .endif

    更改为:

           .if $$defined(ENET_ENABLE_UPDATE)
               .ref    SysTickIntHandler
               .word   SysTickIntHandler               ;; Offset 3C: SysTick handler
          .else
                .if $$defined(SD_ENABLE_UPDATE)        ; SD_ENABLE_UPDATE在bl_config.h里面已经定义了
                      .ref Tmr_TickISR_Handler             ;这个函数已经定义,在BSP.C中
                      .word Tmr_TickISR_Handler
               .else
                     .word   IntDefaultHandler               ;; Offset 3C: SysTick handler
                .endif
     .endif

            编译还是出现同样的提示,即使我调节了COMPILE LEVEL也是样的,同样,如果这个中断不加,还是可以编译过去(需要调节COMPILE level)。

            而且,上次你说的办法,更改了编译的等级,可以编译出.out文件,但是很郁闷的事情是,执行的时候,在汇编调用"ProcessorInit“这个的程序的时候,就死掉了。主要是死在代码拷贝这个地方(从ROM-->RAM这一过程)。

           我的SD卡的FATFS是参考“StellarisWare”中的sd_card里面的项目,查看了它的.map, 发现也有引用rtsv7M4_T_le_v4SPD16_eabi.lib里面的文件。

           有没有办法更改.CMD文件,把项目里需要用的的.obj(rtsv7M4_T_le_v4SPD16_eabi.lib里面的内容)编译进去?

     

     

  • 看了下,楼主出错主要是因为自动初始化变量,需要用到rtsv7M4_T_le_v4SPD16_eabi.lib里面的函数。

    试着把mmc-lm4f231e5qr.c文件中下面几行的全局变量初始自动赋值去掉,不需要设置优化,也可以成功编译了。楼主可以试试,记得自己修改下初始化程序把这些值初始化了。


    static volatile
    DSTATUS Stat;// = STA_NOINIT; /* Disk status */

    static volatile
    BYTE Timer1, Timer2; /* 100Hz decrement timer */

    static
    BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */

    static
    BYTE PowerFlag;// = 0; /* indicates if "power" is on */

  • 你好!

          按你说的,是可以编译出.out文件,但是仍旧有一个warming:

    <Linking>
    warning #10278-D: LOAD placement specified for section
       ".text:decompress:ZI:rtsv7M4_T_le_v4SPD16_eabi.lib<copy_zero_init.obj>".
       This section contains decompression routines required for linker generated
       copy tables and C/C++ auto-initialization.  Must ensure that this section is
       copied to run address before the C/C++ boot code is executed or is placed
       with single allocation specifier (ex. "> MEMORY").
    'Finished building target: sd_bootload.out'

    而且DEBUG的时候,好像代码也不对:

     

     

  • 楼主有没有彻底clean过再重新编译?因为完全没有优化,楼主单步跟踪下来可以查看ResetISR的地址到底是多少,可以一步步跟踪是怎么跳过去的

    我觉得这个warning应该没有问题,它是提醒库中用于变量初始化的函数(在.text段)被赋予了LOAD,这样应该在初始化前保证库函数被复制到RAM中去,否则可能工作不正常。楼主如果确认自己的代码已经把.text段的程序复制进RAM,那么应该不会导致问题。

    楼主也可以在下面设置中关掉所有用库函数初始化的过程。这样就不会有warning出现,但要注意的是,所有的全局变量的初值都将变成未知值需要楼主手工初始化(自己写代码初始化)。

  • 你好!

          我这里情况还是不太乐观,之前你提得更改为--ram_model,去掉全局变量定义时的初始化,都有问题。我在DEBUG的时候,运行地址是在0x20000000以后(也就是SRAM),但是,给我的感觉,好像在RAM里面的代码不太对,因为程序无法进入ResetISR, 经常会乱跳,有些跳到没有代码的地方,有些跳到没有地址空间的地方,我有一个疑问就是:我在链接文件里面,设定了load = FLASH,run = SRAM,那么,这个代码的搬运工作,在哪里做?(因为我在debug的时候,从_c_int00开始,它的地址就已经在SRAM里面了)。 

           我用了一个好的例程(不是bootload),跟踪了一下,在系统刚开始上电的时候,RESET函数,会先调用_c_int00,而_c_int00主要也是做了以下事情:

          1. 把CP11和CP10 赋值为0x3;

           2. 把堆栈付给R13(SP).

           3.  调用__TI_auto_init函数。

           4. 跳到main函数执行。

           给我的理解,应该是函数在正常开始运行时,因该是做以下运行环境的初始化,才能开始main的工作,但是从boot_loader,由于无法引入       rtsv7M4_T_le_v4SPD16_eabi.lib的obj文件,所以运行环境没有建立,所以在导入SRAM以后,会出问题,呵呵,这是我猜测的,不知道对不对?

    搞得郁闷,马工,还有没有其它办法?

  • 楼主可能有个误解,上电时首先执行的程序是ResetISR(由中断向量表决定)。非bootload例程上电复位时候才会通过ResetISR调用_c_int00,c_int00应该会执行楼主所说的大部分功能。

    而bootload例程,上电后执行ResetISR,但并没有去调用_c_int00。代码复制的工作在ResetISR中执行(bl_startup_ccs.s文件335行以后)进行。

    楼主的问题应该出在之前的调用上,楼主复制这些代码到RAM中的动作在335行才执行,之前RAM中并没有正确的代码,如果出现一些函数调用,多半会出问题。

    比方说BL_INIT_FN_HOOK什么的。。。

    楼主可以仔细检查下。

  • 你好!

            很感谢你一直在帮我处理这个问题。

            之前我也是认为代码是由BOOT LOADER实现复制的,而且我也能找到代码:

    ProcessorInit: .asmfunc
        ;;
        ;; Copy the code image from flash to SRAM.
        ;;
     .if $$defined(FLASH_PATCH_COMPATIBLE)
        movs    r0, #0x1000
     .else
        movs    r0, #0x0000
     .endif
        ldr     r1, bss_start
    ;    ldr  r2, init_end
    copy_loop:
            ldr     r3, [r0], #4
            str     r3, [r1], #4
            cmp     r1, r2

            blt     copy_loop

    但是从我这么多次的debug,发现我还没做代码复制,代码就在SRAM里面了(见下图),不知道问什么?

  • 之前看错了,ProcessorInit才是复制代码的。所以在ResetISR函数开始时(251行)就已经复制了代码。

    楼主会执行到_c_int00_函数很奇怪,按理说应该不会调用这个函数才对。根据楼主的代码,上电后应该会直接执行ResetISR函数,而这个函数完全不会调用_c_int00_。建议楼主把断点设在ResetISR开始位置,一步步跟踪看看为什么会跑过去,估计中间某个位置可能跑飞。

  • 你好!

             我有试过,复位完,都跑到_c_int00_的函数,而且,ResetISR是由_c_int00_调用。

             我觉得这样也没错,你看中断向量表的的地址分配:RsetISR-0x20000000,这说明,ResetISR的入口地址应该放在SRAM,刚开始启动的时候,

             SRAM里面没有数据,也不太可能一复位就跑到ResetISR的地方执行。

             之前说的一上电就在SRAM里面执行,这个情况是我没有加自己的代码,直接从ti例程里面编译过来的,有点晕。。。

  • 如果不加楼主自己的函数也会跑到_c_int00_?

    楼主说的跑到的_c_int00_应该是在楼主自己文件里的而不是TI库里的吧?

  • 不是在我自己文件里面,而是在“bl_startup_ccs.s”里面,我刚刚用了“StellarisWare”里面的开发例程"ek-lm3s8962"里面的”boot_serial“, 也是从_c_int00_开始跑,而且地址也是在SRAM里面。

  • 我在想楼主是否清楚M3的启动机制?bl_startup_ccs.s文件中的Vectors定义了上电后M3的执行过程:

    1. 首先会载入堆栈指针,从0x0000 0000位置读入堆栈(__STACK_TOP)

    2. 跳转到0x0000 0004位置中保存的地址开始程序执行。也就是ResetISR - 0x20000000地址。

        感觉这是为了从flash中运行ResetISR程序。楼主试试看把断点设置在ResetISR - 0x2000 0000这个地址上,看看能不能停下来

    Vectors:

    .ref __STACK_TOP
    .word __STACK_TOP ;; Offset 00: Initial stack pointer

    .if $$defined(FLASH_PATCH_COMPATIBLE)

    .word ResetISR - 0x1ffff000 ;; Offset 04: Reset handler
    .word NmiSR - 0x1ffff000 ;; Offset 08: NMI handler
    .word FaultISR - 0x1ffff000 ;; Offset 0C: Hard fault handler

    .else

    .word ResetISR - 0x20000000 ;; Offset 04: Reset handler
    .word NmiSR - 0x20000000 ;; Offset 08: NMI handler
    .word FaultISR - 0x20000000 ;; Offset 0C: Hard fault handler

    .endif

    .word IntDefaultHandler ;; Offset 10: MPU fault handler
    .word IntDefaultHandler ;; Offset 14: Bus fault handler
    .word IntDefaultHandler ;; Offset 18: Usage fault handler
    .word 0 ;; Offset 1C: Reserved
    .word 0 ;; Offset 20: Reserved
    .word 0 ;; Offset 24: Reserved

  • 所以觉得楼主的问题很有意思,按理说应该以M3硬件工作机制为准,但现在似乎编译器做了些奇怪的事情。我得翻翻编译器手册去

  • 我觉得有一种可能性,SRAM里面的代码是仿真器复制进去的,用仿真器时候,程序入口是_c_int00_。而不用仿真器时候,会从RsetISR-0x20000000开始,而代码复制是ProcessorInit这个程序做的。


    楼主可以验证下,在_c_int00_函数中间放句点LED的程序,分别用仿真器和和不用仿真器运行看看



  •  你好!

            昨天有点事,回复晚了。

            我根据你的建议,在分别在_c_int00_和ResetISR里面加入了点灯的程序,两种情况都是:

            仿真的时候,LED都能点亮,拔掉仿真器,都没点亮LED。(感觉好像,不仿真的时候,程序都没有跑起来)。

            见图:  

  • 这么说,用仿真器时候可以正常执行ResetISR程序吧?我觉得两种可能:

    1. 这时候如果ResetISR能正常执行且是由_c_int00_调用的话,那代码就应该是仿真器复制到内存中去的(否则_c_int00_跳转到RAM中应该没有任何东西)。这种情况下仿真器运行是不是没问题?

    2. 还是像之前那样RAM里面程序是空的,只是因为某种原因跳进_c_int00_然后调用ResetISR。那么最好把_c_int00_拿出RAM执行区,直接放进flash,在flash中执行,然后跳转到ResetISR在flash中的位置

    ===========================================================

    非仿真器时候,我还是认为会根据中断向量表,从ResetISR - 0x2000 000位置(flash中某处)执行,这时候理应是ResetISR在flash中执行。楼主可以在ProcessorInit里面放上点LED的程序,看看是不是这样的,如果灯能被点亮,说明执行了ResetISR且正确跳到ProcessorInit,但复制数据到RAM的过程,或者结束跳转可能有问题

  • 另外,楼主可以在烧录程序到Flash中后,看看flash开始位置0x0000 0000是多少,0x0000 0004是多少。

    然后看看0x0000 0004中值所指的地方,有什么内容。

  • 你好!

             你那里能不能提供一个仿真BOOT_LOADER的时候从FLASH开始跑的CMD文件?

             因为我现在用仿真器仿真的时候,每次连接上以后,代码都是从SRAM里面跑。

  • MEMORY
    {
    FLASH (RX) : origin = 0x00000000, length = 0x00040000
    SRAM (RWX) : origin = 0x20000000, length = 0x00008000
    }

    SECTIONS
    {
    GROUP
    {
    .intvecs
    .text
    .const
    .data
    .cinit
    } load = FLASH, run = FLASH, LOAD_START(init_load), RUN_START(init_run), SIZE(init_size)

    GROUP
    {
    .bss
    .stack
    } run = SRAM, RUN_START(bss_run), RUN_END(bss_end), SIZE(bss_size), RUN_END(__STACK_TOP)
    }

  • 你好!

            由于之前把BOOTLOADER拷贝到SRAM一直出错,所以我更改了做法,把BOOTLOADER放在FLASH里面执行,这样有个弊端,就是无法实现BOOTLOADER自升级,但是至少可以实现APP的升级,目前已经可以把SD卡里面的BIN文件读取,也可以升级APP了,但是还是有点问题,下面是我的代码:

        while(1)
        {
         fresult = f_open(&g_sFileObject, "/hello.bin", FA_OPEN_EXISTING | FA_READ);   // 判断是否有hello.bin的文件,如果有,进入升级代码
         if (fresult == FR_OK)
         {
             delay_nop(300000);
             delay_nop(300000);
            updata_code();
         }
         else
         {
             fresult = f_open(&g_sFileObject, "/sd_card.bin", FA_OPEN_EXISTING | FA_READ); // 判断是否有sd_card.bin的文件,如果有,进入升级代码
             if (fresult == FR_OK)
             {
                 delay_nop(300000);
                 delay_nop(300000);
                 updata_code();
             }
             else
             {
              fresult = f_open(&g_sFileObject, "/timers.bin", FA_OPEN_EXISTING | FA_READ); // 判断是否有timer.bin的文件,如果有,进入升级代码
                 if (fresult == FR_OK)
                 {
                     delay_nop(300000);
                     delay_nop(300000);
                     updata_code();
                 }
                 else
                 {
                  fresult = f_open(&g_sFileObject, "/sine.bin", FA_OPEN_EXISTING | FA_READ); // 判断是否有sine.bin的文件,如果有,进入升级代码
                     if (fresult == FR_OK)
                     {
                         delay_nop(300000);
                         delay_nop(300000);
                         updata_code();
                     }
         else
         {
               asm("  NOP");       // 没有需要的BIN文件,调到这里

         }
                 }
             }
         }
        }

    updata_code()

    {

    这里加入了擦除FLASH和烧写FLASH的代码。

    // 下面这一段,实现中断向量的重新定位,以及跳到0x00008004 的地方,读取RESET的入口地址,跳转套RESET的位置。

      __asm("  MOVW    R0, #(0x00008000 & 0xffff)\n"
        " MOVT    R0, #(0x00008000 >> 16)\n"
        " MOVW    R1, #(0xE000ED08 & 0xffff)\n"
        "  MOVT    R1, #(0xE000ED08 >> 16)\n"
        "   STR     R0, [R1]\n"
        " LDR     SP, [R0]\n"
        "   LDR     R0, [R0, #4]\n"
        " NOP\n"
        " NOP\n"
        " NOP\n"
        " NOP\n"
        " NOP\n"
        " NOP\n"
        "  BX     R0\n");

    }

    我把0X00008000之前的空间,用于做BOOTLOADER,我目前有下面几个问题:

    1.    对于升级,不是每次都有效果,有时可以,有时不可以(就是执行 BX     R0 以后,有时APP不会执行,有跳到RESET开始,但是感觉APP没有执行。)

            对于跳转套RESET的地方执行,有什么好的建议吗?还是编译APP的时候,需要做什么设置?

    2.    对于APP上的中断,好像不能用,我在APP做了一个LCD显示和LED闪烁,LED灯闪烁由定时器控制,在仿真的时候,LED可以闪烁,但是导入以后,LED没有闪烁。

           对于APP的中断,有什么好的建议吗?

  • 1. 对于APP,都需要帮助APP把VTABLE、堆栈重新指向APP程序使用的地址,并跳转到APP程序的入口地址

    同时APP要设置flash起始地址为0X00008000

    感觉楼主在配置VTABLE时候的代码不对,楼主可以查阅下器件手册里面VTABLE寄存器的用法。

    2. 感觉和1的原因是一样的。

  • 您好,您的后来方案是bootloader在flash上运行,能请教您个问题么?在flash上运行,bootloader程序需要怎样改,cmd文件需要更改什么?(run=FLASH)  还有bl_start_up.s文件需要修改什么?将processorInit注释掉?还是我自己重新建立一个正常的工程,使用默认生成的启动文件,写main函数,在main函数中等待程序更新命令,这个bootloader工程完全与普通的应用程序完全一致。

     

     

                     谢谢

  • 这么长时间过去了,楼主估计早就忘了。关于boot的例程,网上做过的人不多,只有官网TI的一个英文手册,只能慢慢啃哪个了。

  • 顶起,希望楼主和IT员工能看到,我出现的问题与楼主一致,但是现在不知道bootloader在flash运行怎么配置,是不是与普通的应用工程一致;

    例如: bootloader 占用0~0x2800      应用程序占用0x2800~0x10000     sram共用