为什么要讲bootloader
1.转为一名不算真正的嵌入式软件工程师,起初对bootloader理解起来非常的吃力。如同天书一般,经过积累,后来也慢慢的开始熟悉起来。什么叫bootloader,为什么boot引脚有这么多组合。这个我建议大家可以看看网上的相关教程。本节内容主要从工程的角度来看待相关问题,当然也有一些不足还请指正。
BOOT在跳转前为什么要为APP提供干净的运行环境?
我们知道,BootLoader也是一段人为编制的程序代码,那么需要使用到一定的外设,以及中断向量的设置,一般的处理都是在跳转到APP前一个一个清除相关外设以及中断设置。这有一个隐患,就是可能BootLoader未清除干净导致APP运行环境混乱,代码会出现意想不到的问题。举个例子,就相当于埋了个地雷,你没踩到只是一时幸运,踩到了那就说明你前期没做好排雷工作。
如何提供一个干净的运行环境??
借用一张图:
怎么去理解这张图呢?
第一,我们想要把环境清除干净,除了手动清除每个外设,中断设置外,还可以通过复位。有的人可能会问复位后,系统不是又跳转到bootloader里了吗,那意义是啥? 这个就需要一个标志,那如何去设置呢,可以用全局变量吗?
首先我们先看这段代码:
uint32_t g_JumpInit __attribute__((at(0x2000A000), zero_init));
看不懂没关系,来看看AI是如何解释这段话的
那为啥不同全局变量:
来看看区别
可以简单理解成全局变量初始化后值不变,而g_JumpInit可以被初始化为0的全局变量。
下面了解其作用后,我们再来看看如何保证g_JumpInit如何不被初始化。
设置MDK的STC文件
注意(初次设置点击Edit无效,需要先去掉勾选)
设置初始化为0的全局变量
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00100000 { ; load region size_region
ER_IROM1 0x08000000 0x00100000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x0000A000 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM2 0x2000A000 UNINIT 0x00006000 {
.ANY (NO_INIT)
}
//注意地址必须在范围内,例如我用的407VE芯片,RAM是64K,整个RAM是0x20000000-0x20010000,两个加起来不能超过这个位置
}
设置好后就可以使用g_JumpInit,需要注意一点,我们在跳转前硬件初始化后,再次进入boot程序不能将跳转程序放在硬件初始化后执行,否则毫无意义。一定要在进入int main 就马上跳转,不要进入init后再跳转,这是个小细节。