随着电子技术的发展,客户对嵌入式产品的期望也越来越高,对应的嵌入式产品功能越来越丰富,里面包含的代码也越来越复杂。很多时候很难把所有功能都实现之后再进行测试验证,而是阶段性的开发对应的功能,然后进行测试验证。为了能够升级对应MCU里面包含的Application,越来越多的的嵌入式产品会包含Bootloader进行Application升级:修改之前的Bug和添加新的功能实现。
本文主要介绍IAR Embedded Workbench中的一些相关特性,帮助开发人员进行Bootloader和Application联合开发和调试。
一个Workspace同时包含Bootloader和Application工程
通常来说,Bootloader和Application需要单独建立工程,在IAR Embedded Workbench中,可以在一个Workspace里面同时包含Bootloader和Application的工程:
将变量放置到指定的地址
在IAR Embedded Workbench中,开发人员可以很方便的将变量放置到指定的地址:
· #pragma location · @
在Bootloader和Application中,需要通过共享变量进行交互(比如Bootloader传给Application的MCU复位原因,Application传给Bootloader的升级请求等),这些共享变量需要放置到指定的位置。
下面通过一个简单的例子来说明利用#pragma location和@将变量放置到指定的地址:
/* Shared variables between Bootloader and Application */ #pragma location = 0x2001FFF8 static uint32_t UpdateRequest; //#pragma location = 0x2001FFFC static uint32_t McuResetReason @0x2001FFFC;
Build之后在生成的map文件中查看,对应的变量会被放置到指定的地址:
UpdateRequest 0x2001'fff8 0x4 Data Lc main.o [3] McuResetReason 0x2001'fffc 0x4 Data Lc main.o [3]
声明变量不初始化
在IAR Embedded Workbench中,开发人员可以很方便的使用关键字__no_init将变量声明为不初始化。
在Bootloader和Application中,有些变量是不能进行初始化的,比如Bootloader传给Application的MCU复位原因变量不能在Application中初始化,而Application传给Bootloader的升级请求变量不能在Bootloader中初始化。
下面是在Bootloader中声明Application传给Bootloader的升级请求变量UpdateRequest不初始化:
/* Shared variables between Bootloader and Application */ #pragma location = 0x2001FFF8 __no_init static uint32_t UpdateRequest; //#pragma location = 0x2001FFFC static uint32_t McuResetReason @0x2001FFFC;
Build之后在生成的map文件中查看,对应的变量类型是uninit
Absolute sections, part 1 of 2: 0x4 .noinit uninit 0x2001'fff8 0x4 main.o [3] - 0x2001'fffc 0x4 Absolute sections, part 2 of 2: 0x4 .bss zero 0x2001'fffc 0x4 main.o [3] - 0x2002'0000 0x4计算Application Checksum并在Bootloader中校验
在Bootloader跳转到Application之前,需要计算Application对应的校验码并和之前存取在Application的校验码进行比较,确保Application是完整的。
在IAR Embedded Workbench中内嵌了ielftool,可以在Link的时候生成对应代码区域的校验码并存储在指定的地址:
在Application ICF中把计算出的checksum放到对应的地址:
place at address mem: 0x080FFFFC { section .checksum };
在Bootloader ICF中定义(define)并导出(exported)Application Checksum计算相关的信息:开始地址,结束地址以及存放对应checksum的地址:
define symbol __ICFEDIT_region_FLASH_start__ = 0x08000000; define symbol __ICFEDIT_region_FLASH_end__ = 0x08003FFF; define exported symbol APPROM_start = 0x08004000; define exported symbol CHECKSUM_start = 0x08004000; define exported symbol CHECKSUM_end = 0x080FFFFB; define exported symbol CHECKSUM_address = 0x080FFFFC; define symbol APPROM_end = 0x080FFFFF;
在Bootloader 程序中计算对应Application的checksum并和之前存放的checksum进行比较:
extern uint32_t CHECKSUM_start; extern uint32_t CHECKSUM_end; extern uint32_t CHECKSUM_address; /* Resets the CRC calculation unit */ CRC->CR = 0x01; /* Calculate the code flash checksum using CRC calculation unit */ CrcValue = HAL_CRC_Accumulate(&hcrc, (uint32_t *)&CHECKSUM_start, (((uint32_t)&CHECKSUM_end - (uint32_t)&CHECKSUM_start + 1u)/4u)); /* Compare the calculated checksum with the previously stored checksum */ /* Only jump to Applicstion when the checksum is the same */ if(*((uint32_t *)&CHECKSUM_address) == CrcValue)
单独调试Application
在IAR Embedded Workbench中调试时,下载完成之后调试器会把PC设置为对应应用程序的起始地址(软复位),这样可以在没有Bootloader的情况下,单独调试Application。
注意:需要在Application初始化的时候把中断向量重定向到Application的中断向量表。
联合调试Bootloader和Application
在开发Bootloader和Application时,最后需要联合调试,确保程序可以在Bootloader和Application正常跳转。
IAR Embedded Workbench提供非常方便的功能帮助开发人员联合调试Bootloader和Application。
通常来说Bootloader和Application的代码放置到不同的Flash区域,可以单独下载(下载Bootloader的时候不会影响Application,同理,下载Application的时候不会影响Bootloader)。当然,也可以一起下载。可以让Linker在Bootloader中包含Application,或者Application中包含Bootloader(注意,不能同时,否则会重复包含)。
下面以Application中包含Bootloader为例。在Project > Options > Linker > Input中输入BOOT,并选择对应的Bootloader.bin文件:
在Application的ICF文件中,把Bootloader放到对应的Flash区域:
define exported symbol boot_vector = 0x08000000; place at address mem: boot_vector { readonly section .BOOT };
这样Bootloader就会包含在Application中:
Section Kind Address Size Object ------- ---- ------- ---- ------ "A2": 0x18b8 .BOOT const 0x800'0000 0x18b8 Bootloader.bin [1] - 0x800'18b8 0x18b8 "A0": 0x188 .intvec ro code 0x800'4000 0x188 startup_stm32f405xx.o [3] - 0x800'4188 0x188 "P1": 0x78fc .text ro code 0x800'4188 0xf12 xprintffull_nomb.o [7] .text ro code 0x800'509a 0x2a copy_init3.o [9] .text ro code 0x800'50c4 0x16 strchr.o [9] .text ro code 0x800'50dc 0x40 xfail_s.o [7] .text ro code 0x800'511c 0x36 strlen.o [9] .text ro code 0x800'5154 0x58 memchr.o [9]
调试时,可以在Bootloader工程中加载Application的调试信息,也可以在Application工程中加载Bootloader的调试信息,从而实现Bootloader和Application联合调试。
下面以Application工程师中包含Bootloader调试为例。在Project > Options > Debugger > Images中勾选“Download extra image”和“Debug info only”,并选择对应的Bootloader.out文件:
同时由于Bootloader和Application都包含__vector_table,需要在Project > Options > Debugger > Extra Option中输入对应的命令:--drv_vector_table_base=0x08000000(0x08000000是Bootloader的__vector_table地址)。这样调试时调试器会使用Bootloader的__vector_table:
注意:不要勾选Project > Options > Debugger > Setup中的Run to main选项,这样调试的时候,下载完成之后调试器会让程序停在对应的入口地址,而不是main函数:
这样调试的时候,调试器会指向Bootloader的入口地址,通过View > Images打开对应的Images窗口,里面会显示Bootloader和Application的调试信息:
总结
本文主要介绍了IAR Embedded Workbench中的一些相关特性,帮助开发人员进行Bootloader和Application联合开发和调试。
全部0条评论
快来发表一下你的评论吧 !