使用 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

参考: https://blog.csdn.net/nich2009/article/details/81124691

标签: uart, IAP

添加新评论