stm32cubeide iap
使用 stm32cubeide 实现 uart 基础上的 iap 功能。
1. 在 main.c 里面添加
/* USER CODE BEGIN PTD */
typedef void (*pFunction)(void);
/* USER CODE END PTD */
/* USER CODE BEGIN PD */
#define FLASH_APP_ADDR 0x8008000
/* USER CODE END PD */
/* USER CODE BEGIN 0 */
void UserAppStart(void)
{
printf("BOOTLOADER Start\n");
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) {
printf("APP Start...\n");
HAL_Delay(100);
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (FLASH_APP_ADDR + 4);
Jump_To_Application = (pFunction) JumpAddress; // jump to application address
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress); // initial application stack pointer
Jump_To_Application(); // execute jump, application run...
} else {
printf("No APP found!!!\n");
}
}
/* USER CODE END 0 */
参考: http://ibotx.com/?p=191 https://blog.csdn.net/mynameislinduan/article/details/83579725
2. 或者基于 en.x-cube-iap-usart\AN4657-STM32Cube_IAP_using_UART\Projects\STM3210C_EVAL\ 进行修改。 主要注意的是 flash 方面的操作。
注意, iap 程序使用 debug 版本,不要使用 release 版本,因为 release 版本会出现 hardfault 问题就出现在 Jump_To_Application();。 在 debug 版本中,汇编如下:
HAL_Delay(100);
800739a: 2064 movs r0, #100 ; 0x64
800739c: f7fa fd02 bl 8001da4 <HAL_Delay>
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
80073a0: 4b0f ldr r3, [pc, #60] ; (80073e0 <UserAppStart+0x74>)
80073a2: 681b ldr r3, [r3, #0]
80073a4: 60fb str r3, [r7, #12]
JumpToApplication = (pFunction) JumpAddress; // jump to application address
80073a6: 68fb ldr r3, [r7, #12]
80073a8: 60bb str r3, [r7, #8]
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); // initial application stack pointer
80073aa: 4b09 ldr r3, [pc, #36] ; (80073d0 <UserAppStart+0x64>)
80073ac: 681b ldr r3, [r3, #0]
80073ae: 607b str r3, [r7, #4]
__ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
80073b0: 687b ldr r3, [r7, #4]
80073b2: f383 8808 msr MSP, r3
JumpToApplication(); // execute jump, application run...
80073b6: 68bb ldr r3, [r7, #8]
80073b8: 4798 blx r3
release 版本汇编如下:
8004048: f7fd fb1c bl 8001684 <HAL_Delay>
800404c: 4b0b ldr r3, [pc, #44] ; (800407c <UserAppStart+0x5c>)
800404e: 681b ldr r3, [r3, #0]
8004050: 6822 ldr r2, [r4, #0]
8004052: f382 8808 msr MSP, r2
8004056: e8bd 4010 ldmia.w sp!, {r4, lr}
800405a: 4718 bx r3
800405c: 4808 ldr r0, [pc, #32] ; (8004080 <UserAppStart+0x60>)
800405e: e8bd 4010 ldmia.w sp!, {r4, lr}
8004062: f7ff bb15 b.w 8003690 <Serial_PutString>
8004066: bf00 nop
8004068: 08010000 .word 0x08010000
800406c: 0800573c .word 0x0800573c
8004070: 0800575b .word 0x0800575b
8004074: 2ffc0000 .word 0x2ffc0000
8004078: 0800577b .word 0x0800577b
800407c: 08010004 .word 0x08010004
8004080: 0800579c .word 0x0800579c
经过调试发现,问题就是出现在 JumpToApplication(); 跳转语句上。 release 版本在 设置完ram末地址为 堆栈指针后,使用 ldmia.w sp!, {r4, lr} 来弹出,这就产生了 hardfault。
3. app,需要修改链接文件,把链接地址改为 iap 里面对应的地址。stm32cube 链接文件是 STM32F429IGTX_FLASH.ld 这样的文件,修改
FLASH (rx) : ORIGIN = 0x08010000, LENGTH = 960K
然后修改 system_stm32f4xx.c 文件,修改
#define VECT_TAB_OFFSET 0x10000
4. iap 中,如果使用
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & APPLICATION_ADDRESS_MASK ) == 0x20000000)
这样的判断语句,注意 APPLICATION_ADDRESS_MASK 要跟着 mcu 的 ram 大小来变化,这个是堆栈的地址,也是 ram 的末端地址。
5. 然后使用 secureCRT 的 ymodem 即可发送二进制文件。
6. 如果 app 使用的是 mdk,那么需要修改三个地方。
参考: https://blog.csdn.net/Creative_Team/article/details/84334571
然后 mdk 里面 项目配置 --> User command --> After Build 增加两条命令。
$K\ARM\ARMCC\bin\fromelf.exe --bin --output=Flash\Obj\@L.bin !L
CopyHex_Flash.bat
CopyHex_Flash.bat 里面增加:
copy Flash\Obj\output.hex ..\output(mdk).hex
copy Flash\Obj\output.bin ..\output(mdk).bin