继上一篇史上最简单的bootloader【STM32F767】后,最近进一步研究了下bootloader。
任务:bootloader不变,app自我复制,将app搬运到sram中运行。
目的:1)学习bootloader;
2)没什么大用处,主要是学习---->看资料说是代码在sram中运行会快一点,本人没有测试过
学习过程有点曲折,虽然实验现象符合预期,还是有很多不明白的地方,话多不表,开始!!!
bootloader代码参考史上最简单的bootloader【STM32F767】
app文件中增加了拷贝复制的函数:
void copymyself(void)
{
extern unsigned long Image$$ER_IROM1$$Base;
extern unsigned long Image$$ER_IROM1$$Length;
extern unsigned long Load$$ER_IROM1$$Base;
//拷贝代码
volatile unsigned long TXTSize_volatile =
( unsigned long )&Image$$ER_IROM1$$Length;
memcpy(&Image$$ER_IROM1$$Base,&Load$$ER_IROM1$$Base,TXTSize_volatile);
//拷贝数据段
extern unsigned long Image$$RW_IRAM1$$Base;
extern unsigned long Load$$RW_IRAM1$$Base;
extern unsigned long Image$$RW_IRAM1$$Length;
volatile unsigned long DATSize_volatile=( unsigned long )&Image$$RW_IRAM1$$Length;
memcpy(&Image$$RW_IRAM1$$Base,&Load$$RW_IRAM1$$Base,DATSize_volatile);
//BSS段清零
extern unsigned long Image$$RW_IRAM1$$ZI$$Base;
extern unsigned long Image$$RW_IRAM1$$ZI$$Length;
volatile unsigned long ZISize_volatile=( unsigned long )&Image$$RW_IRAM1$$ZI$$Length;
memset(&Image$$RW_IRAM1$$ZI$$Base,0,ZISize_volatile);
}
散列文件改动了一点,一个一个说明!
LR_IROM1 0x08030000 0x00a0000 { ; load region size_region
ER_IROM1 0x20000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 +0 { ; RW data
.ANY (+RW +ZI)
}
}
解释:
1) ER_IROM1 0x20000000 0x00080000 运行域的地址放在sram中,因为加载地址和链接地址不一致,所
以需要代码、数据、BSS都需要重新定位(其实就是代码复制,将相关的数据复制到链接地址,比如本次
加载地址是0x08030000,链接地址0x20000000 ,就需要把0x08030000开始的相关代码和数据复制到链接
地址0x20000000)
2) RW_IRAM1 +0 +0代表紧接着上一个加载域(同一个空间中,都是在sram中。为什么可读可写,未初始化
变量要放在sram,自行查找资料,个人认为就是sram中可以对某个字节,类似nandflash norflahs就需要
以块或者扇区为单位进行读写,不怎么灵活)
启动文件改动的地方比较多,里面有很多不太明白的地方!!!
__Vectors ;DCD __initial_sp ; Top of Stack
DCD (0x20000000+0x00080000)
;DCD Reset_Handler ; Reset Handler 0x200001f8
DCD 0x080301f9 ; Reset Handler
DCD NMI_Handler ; NMI Handler
……
……
……
说明:
1)DCD (0x20000000+0x00080000) 指定栈,虽然我知道栈空间地址是向下的,对于这一句,我不是
很明白,如果是默认的 -> DCD __initial_sp ,程序无法运行
2)DCD 0x080301f9 ; Reset Handler 这一句很奇怪是不是。因为必须要这么做!!!
目的:app自我复制,然后再跳到sram中运行相关代码。
解释:
在跳转到sram中执行代码前(重定位后的代码),实现app自我复制的代码(函数copymyself) 必
须、一定、肯定、100%要“运行”flash中的。因为此时的链接地址处 app自我复制的代码(函数
copymyself) 还没被搬运到这里。
下面是反汇编文件,可以看到Reset_Handler段链接地址:0x200001f8,可以确定Reset_Handler
段在flash上地址在0x080301f8(0x080301f9是因为用的是thumb指令集)
$d.realdata
RESET
__Vectors
0x20000000: 20080000 ... DCD 537395200
0x20000004: 080301f9 .... DCD 134414841
0x20000008: 2000a901 ... DCD 536914177
0x2000000c: 20008ff1 ... DCD 536907761
0x20000010: 2000a8f9 ... DCD 536914169
0x20000014: 20000301 ... DCD 536871681
0x20000018: 2000bc21 !.. DCD 536919073
0x2000001c: 00000000 .... DCD 0
0x20000020: 00000000 .... DCD 0
0x20000024: 00000000 .... DCD 0
0x20000028: 00000000 .... DCD 0
.text
$v0
Reset_Handler
__Vectors_End
0x200001f8: f00bfd2e .... BL copymyself ; 0x2000bc58
0x200001fc: f00bfd6c ..l. BL mymain ; 0x2000bcd8
0x20000200: e7fe .. B 0x20000200 ; Reset_Handler + 8
0x20000202: e7fe .. B 0x20000202 ; Reset_Handler + 10
0x20000204: e7fe .. B 0x20000204 ; Reset_Handler + 12
0x20000206: e7fe .. B 0x20000206 ; Reset_Handler + 14
0x20000208: e7fe .. B 0x20000208 ; Reset_Handler + 16
0x2000020a: e7fe .. B 0x2000020a ; Reset_Handler + 18
0x2000020c: e7fe .. B 0x2000020c ; Reset_Handler + 20
0x2000020e: e7fe .. B 0x2000020e ; Reset_Handler + 22
0x20000210: e7fe .. B 0x20000210 ; Reset_Handler + 24
上面理解不了,可以看.map文件,map文件也能说明。
下面是 Reset_Handler段,实现功能:
1)调用void copymyself(void)函数实现app自我复制
2)初始化stm32环境
3)跳转到sram中的APP运行
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT copymyself
IMPORT mymain
IMPORT SystemInit
;LDR SP,=(0x20000000+0x00080000)
BL copymyself
;BL mymain
BL SystemInit
;LDR R0, =SystemInit
;BLX R0
LDR R0, =mymain
BLX R0
ENDP
说明:
1) BL copymyself 这个是相对跳转的指令,因为此时代码还没跳到SRAM中运行,所以用BL相对跳转
指令
2)BL SystemInit 这个是初始化stm32运行环境,至于为什么还需要初始化,我也不明白,如果不重
新初始化环境printf函数不能用,但是led反转功能是正常的,很无语,个人猜测应该是uart重定向的代
码没有被复制到sram中也就是c运行库的问题。
3) LDR R0, =mymain
BLX R0 位置有关的跳转,跳转到sram中的mymain()运行
app的实现
/* USER CODE BEGIN 0 */
void copymyself(void)
{
extern unsigned long Image$$ER_IROM1$$Base;
extern unsigned long Image$$ER_IROM1$$Length;
extern unsigned long Load$$ER_IROM1$$Base;
//拷贝代码
volatile unsigned long TXTSize_volatile =
( unsigned long )&Image$$ER_IROM1$$Length;
memcpy(&Image$$ER_IROM1$$Base,&Load$$ER_IROM1$$Base,TXTSize_volatile);
//拷贝数据段
extern unsigned long Image$$RW_IRAM1$$Base;
extern unsigned long Load$$RW_IRAM1$$Base;
extern unsigned long Image$$RW_IRAM1$$Length;
volatile unsigned long DATSize_volatile=( unsigned long )&Image$$RW_IRAM1$$Length;
memcpy(&Image$$RW_IRAM1$$Base,&Load$$RW_IRAM1$$Base,DATSize_volatile);
//BSS段清零
extern unsigned long Image$$RW_IRAM1$$ZI$$Base;
extern unsigned long Image$$RW_IRAM1$$ZI$$Length;
volatile unsigned long ZISize_volatile=( unsigned long )&Image$$RW_IRAM1$$ZI$$Length;
memset(&Image$$RW_IRAM1$$ZI$$Base,0,ZISize_volatile);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int mymain(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(led01_GPIO_Port,led01_Pin);
HAL_GPIO_TogglePin(led01_GPIO_Port,led00_Pin);
printf("this is app program \r\n");
HAL_Delay(1200);
}
/* USER CODE END 3 */
}
至此,通过app的自我复制,将代码搬运到sram中运行功能就实现了!!!
那些不明白的地方,如果哪天搞明白了,会在文中更新,同时也希望有知道的大佬能留言指导下小弟!!!
标签:Reset,RW,Image,unsigned,long,STM32F767,bootloader,IRAM1,史上 From: https://blog.csdn.net/Mr1sky/article/details/139700883