接下去直到,已经建立了一个可以通通的工程模板,接下来进行官方示例程LWIP_IAP中的iap_http模式的移植
官方示例
D:STM32CubeRepositorySTM32Cube_FW_F4_V1.21.0ProjectsSTM324xG_EVALApplicationsLwIPLwIP_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_v5ARMARMCCBin’
Build target ‘teach_http_iap’
compiling flash_if.c.。.
。.Srcflash_if.c(57): error: #20: identifier “USER_FLASH_LAST_PAGE_ADDRESS” is undefined
if (FlashAddress 《= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS)
。.Srcflash_if.c(91): error: #20: identifier “USER_FLASH_END_ADDRESS” is undefined
for (i = 0; (i 《 DataLength) && (*FlashAddress 《= (USER_FLASH_END_ADDRESS-4)); i++)
。.Srcflash_if.c: 0 warnings, 2 errors
compiling httpserver.c.。.
。.Srchttpserver.c(40): error: #5: cannot open source input file “lcd_log.h”: No such file or directory
#include “lcd_log.h”
。.Srchttpserver.c: 0 warnings, 1 error
compiling app.c.。.
。.userappapp.c(28): warning: #223-D: function “IAP_httpd_init” declared implicitly
IAP_httpd_init();
。.userappapp.c: 1 warning, 0 errors
“teach_http_iapteach_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_v5ARMARMCCBin’
Build target ‘teach_http_iap’
compiling httpserver.c.。.
linking.。.
teach_http_iapteach_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_iapteach_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_v5ARMARMCCBin’
Build target ‘teach_http_iap’
compiling httpserver.c.。.
。.Srchttpserver.c(210): error: #20: identifier “LOGIN_SIZE” is undefined
char *data, *ptr, filename[40], login[LOGIN_SIZE];
。.Srchttpserver.c(273): error: #20: identifier “USERID” is undefined
sprintf((char *)login,“username=%s&password=%s”,USERID,PASSWORD);
。.Srchttpserver.c(273): error: #20: identifier “PASSWORD” is undefined
sprintf((char *)login,“username=%s&password=%s”,USERID,PASSWORD);
。.Srchttpserver.c(210): warning: #550-D: variable “filename” was set but never used
char *data, *ptr, filename[40], login[LOGIN_SIZE];
。.Srchttpserver.c: 1 warning, 3 errors
“teach_http_iapteach_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”
再次编译运行,没有错误。将程序下载到开发板,断电重启(如果在下载时选择重启并运行,下载到flash则不需要)
二。程序测试
打开IE浏览器(必须IE),输入192.168.1.120,出现下面的页面
输入用户名,密码stm32,登录
上传bin文件成功升级。
到上面为止,HTTP模式的IAP升级已经完成,但点击是,我们每个一次复位开发板或者开发板上电的时候,都自动进入了IAP模式工作状态,重新代码无法正常进入的应用程序,不合乎常理的。我们希望设备在正常使用的时候直接运行应用程序,当我们需要IAP升级的时候才能进入升级模式。
该问题的解决方案:添加另外一个常用的(以下几个升级部分BUTTON_WAKEUP),与PA0相连接
进入IAP模式:
保持BUTTON_WAKEUP按下不取消
按下复位,等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程序! rn”);
while(1);
}
}
else
{
App_init();
/* USER CODE END 2 */
再将
/* USER CODE BEGIN WHILE */
while (1)
{
MX_LWIP_Process();
App_process();
/* USER CODE END WHILE */
改写成以下形式,多加了一个“ } ”,这是为了满足上个代码块中的其他的传输形式
/* 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_v5ARMARMCCBin‘
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_iapteach_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的程序中,我为它在闪烁中偏移了地址0x20000的大小,即128KB的空间。这就需要我们在生成app程序的时候,将地址地址改成0x8020000,大小改成E000。用计算器可以计算0x100000-0x20000 = 0xE0000。
在app程序的main函数中,需要添加一条中断移动表20000的代码
SCB-》VTOR = FLASH_BASE | 0x2000;//设置偏移量升级开启,HTTP模式的IAP远程最终完成。