STM32F407开发板的HTTP模式IAP远程升级之官方例程移植

版权声明:本文为原创文章,转载请注明出处 https://blog.csdn.net/wbdxz/article/details/82859237

版权声明:本文为博主原创文章,转载请注明出处:https://blog.csdn.net/wbdxz/article/details/82859237

关于远程升级的模板建立,可以参考下面的博文

接上文为止,已经建立好了一个可以ping通的以太网工程模板,接下来进行官方例程LWIP_IAP中的iap_http模式的移植

官方例程位置

  • D:\STM32Cube\Repository\STM32Cube_FW_F4_V1.21.0\Projects\STM324xG_EVAL\Applications\LwIP\LwIP_IAP

一.移植步骤

1.将官方例程中的Src文件夹下的flash_if.c,fsdata.c,httpserver.c复制到我们自己建立的工程文件夹的Src文件夹下

将flash_if.c和httpserver.c添加到keil工程中的Gourps中

2.将官方例程中的Inc文件夹下的flash_if.h,fsdata.h,httpserver.h复制到我们自己建立的工程文件夹的Inc文件夹下

3.在app.c中添加如下代码

4.此时编译,出现了以下错误

*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'd:\Keil_v5\ARM\ARMCC\Bin'
Build target 'teach_http_iap'
compiling flash_if.c...
..\Src\flash_if.c(57): error:  #20: identifier "USER_FLASH_LAST_PAGE_ADDRESS" is undefined
    if (FlashAddress <= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS)
..\Src\flash_if.c(91): error:  #20: identifier "USER_FLASH_END_ADDRESS" is undefined
    for (i = 0; (i < DataLength) && (*FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++)
..\Src\flash_if.c: 0 warnings, 2 errors
compiling httpserver.c...
..\Src\httpserver.c(40): error:  #5: cannot open source input file "lcd_log.h": No such file or directory
  #include "lcd_log.h"
..\Src\httpserver.c: 0 warnings, 1 error
compiling app.c...
..\user\app\app.c(28): warning:  #223-D: function "IAP_httpd_init" declared implicitly
      IAP_httpd_init();
..\user\app\app.c: 1 warning, 0 errors
"teach_http_iap\teach_http_iap.axf" - 3 Error(s), 1 Warning(s).
Target not created.
Build Time Elapsed:  00:00:02

解决方法:

1.在flash_if.h中添加

//起始地址
#define USER_FLASH_FIRST_PAGE_ADDRESS 0x08020000 /* Only as example see comment */
#define USER_FLASH_LAST_PAGE_ADDRESS  0x080E0000
//结束地址
#define USER_FLASH_END_ADDRESS        FLASH_END  

2.注释掉httpserver.c中的如下代码

再次编译,出现错误

*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'd:\Keil_v5\ARM\ARMCC\Bin'
Build target 'teach_http_iap'
compiling httpserver.c...
linking...
teach_http_iap\teach_http_iap.axf: Error: L6218E: Undefined symbol IAP_httpd_init (referred from app.o).
Not enough information to list image symbols.
Not enough information to list load addresses in the image map.
Finished: 2 information, 0 warning and 1 error messages.
"teach_http_iap\teach_http_iap.axf" - 1 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed:  00:00:02

解决方法:在main.h的76行添加如下代码

#define USE_IAP_HTTP   /* enable IAP using HTTP */

再次编译,出现错误

*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'd:\Keil_v5\ARM\ARMCC\Bin'
Build target 'teach_http_iap'
compiling httpserver.c...
..\Src\httpserver.c(210): error:  #20: identifier "LOGIN_SIZE" is undefined
    char *data, *ptr, filename[40], login[LOGIN_SIZE];
..\Src\httpserver.c(273): error:  #20: identifier "USERID" is undefined
                 sprintf((char *)login,"username=%s&password=%s",USERID,PASSWORD);
..\Src\httpserver.c(273): error:  #20: identifier "PASSWORD" is undefined
                 sprintf((char *)login,"username=%s&password=%s",USERID,PASSWORD);
..\Src\httpserver.c(210): warning:  #550-D: variable "filename"  was set but never used
    char *data, *ptr, filename[40], login[LOGIN_SIZE];
..\Src\httpserver.c: 1 warning, 3 errors
"teach_http_iap\teach_http_iap.axf" - 3 Error(s), 1 Warning(s).
Target not created.
Build Time Elapsed:  00:00:02

解决方法:

在main.h的第77行添加如下代码

#define USERID       "user"
#define PASSWORD     "stm32"
#define LOGIN_SIZE   (15+ sizeof(USERID) + sizeof(PASSWORD))

在app.c的第19行添加

#include "httpserver.h"

再次编译运行,没有错误。将程序下载到开发板,断电重启(如果在下载时选择Reset and run,download to flash则不需要)

二.程序测试

打开IE浏览器(必须使用IE),输入192.168.1.120,出现下面的页面

输入用户名user,密码stm32,点击login

上传bin文件即可升级成功。


到上面为止,HTTP模式的IAP升级已经完成,但值得注意的是,我们每一次复位开发板或者开发板重新上电的时候,都自动进入了IAP模式,也就是说无法进入正常的app工作状态,这是不合乎常理的。我们希望设备在正常使用的时候直接运行app代码,当我们需要IAP升级的时候才进入升级模式。

该问题的解决方案:添加另外一个普通按键(以下称为升级按键BUTTON_WAKEUP),与PA0相连接

进入IAP模式:

  1. 保持BUTTON_WAKEUP按下不松开
  2. 按下复位按键,等2秒即可进入

进入普通app运行模式:

  • 只要复位或者重新上电时,BUTTON_WAKEUP不被按下即可

具体代码实现步骤如下:

将main.c中的以下代码

  /* USER CODE BEGIN 2 */
	App_init();
  /* USER CODE END 2 */

改写成如下代码

  /* USER CODE BEGIN 2 */
   /*
	设置BUTTON_WAKEUP按键KEY_UP,默认是低电平,按下为高电平
  */
   if (HAL_GPIO_ReadPin(BUTTON_WAKEUP_GPIO_Port,BUTTON_WAKEUP_Pin) == 0x00)
  { /* Key push-button not pressed: jump to user application */
	  /* 如果KEY_UP没有按下,则跳转至app */
    
    /* Check if valid stack address (RAM address) then jump to user application */
	  /* 检查栈顶地址信息是否合法,合法则跳转至app */
    if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
    {
      /* Jump to user application */
      JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4);
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS);
      Jump_To_Application();
      /* do nothing */
      while(1);
    }
	//如果flash栈信息中没有app代码,则打印反馈信息
	  else
	{
		printf("FLASH中没有app程序! \r\n");
		while(1);
	}
  }
  else
  {
	App_init();
  /* USER CODE END 2 */

再将

  /* USER CODE BEGIN WHILE */
  while (1)
  {
	MX_LWIP_Process();
	App_process();
  /* USER CODE END WHILE */

改写成以下形式,多加了一个" } ",这是为了满足上个代码块中的else的书写形式

  /* USER CODE BEGIN WHILE */
  while (1)
  {
	MX_LWIP_Process();
	App_process();
  }
  /* USER CODE END WHILE */

编译代码,出现以下错误:

*** Using Compiler 'V5.06 update 6 (build 750)', folder: 'd:\Keil_v5\ARM\ARMCC\Bin'
Build target 'teach_http_iap'
compiling main.c...
../Src/main.c(120): error:  #20: identifier "USER_FLASH_FIRST_PAGE_ADDRESS" is undefined
      if (((*(__IO uint32_t*)USER_FLASH_FIRST_PAGE_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
../Src/main.c(123): error:  #20: identifier "JumpAddress" is undefined
        JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4);
../Src/main.c(124): error:  #20: identifier "Jump_To_Application" is undefined
        Jump_To_Application = (pFunction) JumpAddress;
../Src/main.c(124): error:  #20: identifier "pFunction" is undefined
        Jump_To_Application = (pFunction) JumpAddress;
../Src/main.c(124): error:  #65: expected a ";"
        Jump_To_Application = (pFunction) JumpAddress;
../Src/main.c: 0 warnings, 5 errors
"teach_http_iap\teach_http_iap.axf" - 5 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed:  00:00:08

解决方法:

在main.c的

/* USER CODE BEGIN Includes */
#include "app.h"
/* USER CODE END Includes */

加入一行新的头文件

/* USER CODE BEGIN Includes */
#include "app.h"
#include "flash_if.h"
/* USER CODE END Includes */

在main.c的第65行,加入

//满足按键检测升级功能/app跳转的定义
typedef  void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;

再次编译,没有错误提示。

下载到开发板运行,尝试进入IAP模式,正常运行模式。

在本Bootloader程序中,我为它在flash中偏移了0x20000的大小,即128KB的空间。这就需要我们在生成app程序的时候,将起始地址改成0x8020000,Size改成E0000。用计算器可以计算0x100000-0x20000 = 0xE0000。

在app程序的main函数中,需要添加一条中断向量表偏移20000的代码

	SCB->VTOR = FLASH_BASE | 0x20000;//设置偏移量

至此,HTTP模式的IAP远程升级最终完成。


如果我的文字帮助到了你,欢迎打赏哈。

我的赞赏码

猜你喜欢

转载自blog.csdn.net/wbdxz/article/details/82859237