BootLoader
首先要了解手中的HC32Flash容量大小,及SRAM的大小。根据HC32F460系列官方参考手册中EFM章节得知,HC32F460单片机程序是从0x00000000处开始执行的,和ST不一样。HC32F460还有一个初始化配置ICG,他要先于代码执行。
使用Ymodem协议不用写上位机,用一些终端软件Xshell,secureCRT就可以。我用过Xshell比较稳定,secureCRT传输时,第一帧只有SOH 00 FF FileName,后面的 FileSize NUL[128] CRC都没有,当然也就无法传输了。
移植Ymodem注意事项
1.配置系统时钟使用外部晶振驱动HC32F460工作,不能用系统本身的MRC(实测传输bin文件会失败,我参考过官方HC32L系列的BootLoader程序,也是这样做的)。等传输完毕后,跳转到APP之前一定要将系统时钟复位(或者在APP程序里面在执行一次时钟配置程序)
2.匹配HC32F460的串口驱动,Ymodem是ST发布的。
3.根据HC32F460芯片和BootLoader程序大小选择APP程序的入口地址,大容量的可以任性一点。
4.修改Ymodem协议中解包程序(Ymodem.c)中的Flash擦除和编程代码为HC32F460的。如下图
5.修改Flash写保护相关代码。
HC32F460的FLASH有个窗口保护机制,它是根据两个寄存器值的相对大小确定写保护的区域。当两个寄存器的值相等时,没有写保护。官方手册这么说:
如果需要对BootLoader代码严格保护,可以在BootLoader或者APP中修改两个寄存器的值。
5.修改跳转程序的相关代码
a.实现代码
en_result_t IAP_JumpToApp(uint32_t u32Addr)
{
uint32_t u32StackTop = *((__IO uint32_t *)u32Addr); //读取APP程序栈顶地址
/* 判断栈顶地址有效性 */
if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + SRAM_SIZE)))
{
/* 配置跳转到用户程序复位中断入口 */
JumpAddress = *(__IO uint32_t *)(u32Addr + 4);
Jump_To_Application = (func_ptr_t)JumpAddress;
/* 初始化用户程序的栈顶指针 */
__set_MSP(*(__IO uint32_t *)u32Addr);
Jump_To_Application();
}
return Error;
}
b.调用代码:
en_result_t ret = IAP_JumpToApp(ApplicationAddress);
if (Error == ret)
{
UsartPrintf(M4_USART1, "Jump To App Failed! Please Check ApplicationAddress!\r\n");
while(1);
}
调用代码里面的ApplicationAddress是APP程序的入口地址,**不要和BootLoader程序重叠,不要设置在0x00000400 ~ 0x0000041F,这里是ICG的配置区。**ApplicationAddress是一个宏,在common.h中定义。可以仿照ST定义多种芯片的FLASH大小和扇区大小。
实现代码里面首先判断了栈顶地址是否合法,SRAM_BASE和SRAM_SIZE也是定义在common.h中。
代码中先偏移了4字节,相当于ApplicationAdderss + 4,然后再设置MSP,最后跳到App。如果我设置ApplicationAddress为0x20000,那么真正程序入口地址为0x00020004,这里根据Cortex-M4参考手册,
0x000020004是VECT_TAB的偏移地址,发生的各种中断都要来这里查询。
APP
HC32F460的SystemInit函数中没有设置中断向量表地址,默认原有地址0x0000000。需要在程序里添加
SCB->VTOR = FLASH_BASE + VECT_TAB_OFFSET; //向量表偏移
还需要改ICG的配置
最后修改Keil配置IROM的Start和Size
IROM1的start就是BootLoader程序中ApplicationAddress,Size是从Start开始到芯片FLash最后地址的大小。
7.生成bin文件的方法
把以下指令复制到下图所在位置,编译即可在工程根目录下找到 xxx.bin文件
$K\ARM\ARMCC\bin\fromelf.exe --bin --output=@L.bin !L
具体含义可以参考ARMCC编译器的说明。
跳转后遇到的问题
一定要在APP程序中设置向量表偏移,否则生成的bin文件很大。而且无法运行。
时钟错误,原本程序中1S闪一次的指示灯变快了,在APP程序中DEBUG时发现,自己编写的时钟初始化函数没有真正执行,这是我写程序的BUG,系统跳转到APP后我获取了系统时钟为200MHz,但是指示灯闪烁速度和串口的波特率确实不对,因为我写的时钟初始化函数是先获取当前时钟源,如果是mpll就直接出去了,否则才配置时钟到200MHz。我在BootLoader程序里面页初始化了系统时钟源为mpll,所以跳转到APP后没有执行。
我参考官方IAP程序,在跳转之前把系统时钟复位了,到APP程序后重新初始化。所以我也这么干了,程序就可以跑起来了。