STM32 BootLoder 产品的更新程序的重要功能,此文档记录我的学习过程。
一、首先,准备一个带有STM32芯片的电路板,并且能控制其点亮一个灯。至此,准备工作完成。
void mcu_init(void)
{
HSI_SetSysClock(); //初始化系统时钟(64MHZ)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
IO_Init(); //初始化普通IO口
delay_init(); //滴答时钟初始化(延时函数)
}
int main(void)
{
mcu_init();
while (1)
{
LED_REVERSE; //LED闪烁
delay_ms(1000);
}
}
二、把第一步工程复制两份,一个作为BooterLoder引导程序,另一个作为APP主控程序。
我们先写BooterLoder程序,首先要给BooterLoder程序分区,这个分区得根据具体的CPU内存大小来确定,我用的CPU Flash为128K,因为我的BooterLoder程序不是很大,分配16K足够了。所以BooterLoder 末尾地址0x8000000+0x4000 = 0x8004000
在编译的的时候我出现了一个错误
Error: L6971E: sys_rcc.o(.data) type RW incompatible with mcu_usart.o(.ARM.__AT_0x20000000) type ZI in er RW_IRAM1.
百度了一说是IRAM1起始位置应该为0x200000C0(后来发现这个答案只是不适合我,我的程序另有其因),不过问题还是没能解决,后来自己查看了一下.map文件
我定义了一个数组,数组容量为1024,顿时明白程序没有为它分配足够的空间,具体原因还未知。后来删掉数组或者给把IRAM的起始地址往后移1024个字节,问题得以解决。
APP程序的地址分配是
三、接下来就是测试程序编写
BooterLoder程序实现串口发送及跳转到APP程序起始地址
void mcu_init(void)
{
HSI_SetSysClock(); //初始化系统时钟(64MHZ)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
IO_Init(); //初始化普通IO口
delay_init(); //滴答时钟初始化(延时函数)
uart_init(); //串口 (115200bps)
}
int main(void)
{
mcu_init();
while (1)
{
LED_REVERSE;
UART2_Printf("BootLoader,马上跳转至跳转到APP程序\r\n");
delay_ms(1000);
UART2_Printf("准备跳转\r\n");
iap_load_app(0x8004000); //跳转函数,跳转到0x8004000起始的地址执行程序
}
}
}
APP程序重新定义中断向量表的地址并执行正常功能
void mcu_init(void)
{
HSI_SetSysClock(); //初始化系统时钟(64MHZ)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
IO_Init(); //初始化普通IO口
delay_init(); //滴答时钟初始化(延时函数)
uart_init(); //串口 (115200bps)
}
int main(void)
{
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x4000); //重新设置中断向量表
mcu_init();
while (1)
{
LED_REVERSE;
UART2_Printf("hello world\r\n");
delay_ms(1000);
}
}
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x4000); 这一句很重要,可百度其用法。
把程序依次下载进单片机中。
用串口助手可查看程序运行情况。这就实现了BooterLoder和APP程序的地址分配以及跳转问题。