在 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