程序中区域划分:
/** BootLoder区 10KB
* START_ADDR 0x08000000
* START_ADDR 0x080027FF
*/
/* 程序执行区 58KB */
#define FLASH_EXECUT_START_ADDR 0x08002800
#define FLASH_EXECUT_END_ADDR 0x08010FFF
/* 程序固件区 58KB */
#define FLASH_FIRMWARE_START_ADDR 0x08011000
#define FLASH_FIRMWARE_END_ADDR 0x0801F7FF
/* 标志区 2KB*/
#define FLASH_FLAG_START_ADDR 0x0801F800
#define FLASH_FLAG_END_ADDR 0x0801FFFF
我的操作是app程序使用keil先烧写到固件区(0x08011000 - 0x0801F7FF),在boot程序中将固件区程序搬运到执行区(0x08002800 - 0x08010FFF),搬运完成后跳转到执行区开始执行。程序可以正常运行。
在APP程序中接收新的APP固件到固件区。当我接收到一包1K大小的数据,连续半页写入。执行操作是先擦除一页,再写入两个半页,然后循环。
在接收新的固件数据不会发生硬件错误,一旦我开始操作Flash时,就时不时发生硬件错误。经排除可能原因,最后定位到flash。使用软件读取到flash完整数据,发现,擦除固件区时,对应的运行区数据也会被擦除,我大为不解。
用MDK调试程序,发现程序一擦除flash,就随机发生硬件错误中断,用鼠标悬浮到函数上时,显示函数地址在0x08011000以后,也就是地址在固件区,不再运行区。虽然程序已经搬运到0x08002800,并跳转到0x08002800执行,但是函数地址不在这。这也是发生硬件错误的原因。
原来是在MDK编译时,函数地址已经确定好了,与在flash位置无关。所以我操作函数地址位置时,就会发生硬件错误中断。也就是说想让程序最终位于flash哪个位置,在MDK中就要设置好。
当时我是为了让程序下载到固件区,来模拟bootloader搬运功能。但是显然是不能实现的。
后来我的解决办法是再找一块B板子,用B板子将APP程序发送到A板子。B板子自己的程序下载到固件区,要发送的程序(在A板子运行的APP)下载到运行区。这样B板子将位于运行区的程序发送到A板子,A板子将程序先存放到固件区,接收完成无误后,bootloader再将固件区程序搬运到运行区。这样就实现了A板子运行区程序的更新。