【STM32CubeMx】基于LWIP协议栈的LAN远程IAP固件升级

最近要完成stm32F107的这个升级固件任务,做个自己的学习记录,也和各位分享一下

一、概括综述

工程主要所需软件:STM32CubeMx,keil5,STM32CubeProgrammer

辅助软件:串口助手,wireshark,tftpd64

本次介绍的是基于STM32F107的LWIP协议栈通过TFTP的文件传输协议进行IAP程序升级。采用的PHY层芯片是LAN8742A,将单片机搭建为TFTP服务器,PC端作为客户端对其下发升级固件。在进行此项工程编写之前,需要了解单片机FLASH操作相关知识,我就最简单实现IAP升级功能,主要将FLASH分成两个部分,一部分作为BootLoader区,一部分作为功能实现的APP区。在这里理论知识就不讲了,主要讲我实操是怎么完成的,看这一文基本可以解决你的问题实现功能。

二、创建工程

本次因为使用到LWIP协议栈,去官网下载源码移植较为繁琐,所以直接使用STM32CubeMx进行代码生成,BootLoade区r和APP区需要分成两个工程去编写,最主要的是BootLoader区的引导升级。CubeMx配置如下:

RCC配置:

开启ETH的连接,GPIO配置如下:(具体需要根据自己的原理图配置)

还有一个IO是ETH_RST复位引脚,需要单独配置,可以设为输出模式,用来拉高拉低复位LAN8742A芯片,此处我设置的是:

如果需要看串口的话,可以看单片机芯片资源随意配置一个USART,串口这里就不多讲了,我这里选择的是USART3:

接下来就是LWIP的配置直接贴图

配置静态IP,注意要和PC端同一网段

其他默认就好,生成keil5工程打开

查好芯片数据手册,设置BootLoader区大小(ps:最好要完整的页,F107这里一页为2k即0x800)

在main函数里添加函数

就可以ping通了

三、具体实现TFTP传输固件,以及IAP升级

具体TFTP实现简单文件传输,需要重写tftpserver函数,重写open,close,read和write的文件操作但CubeMx生成的代码中并未包含具体的例子。在lwip的开发master分支中,官方提交了有关tftp的示例代码,我们可以对此参考编写。

https://git.savannah.gnu.org/cgit/lwip.git/commit/?id=0be3e35bf2780feed59e09fd08954f80bd7b4c7e

使用TFTP传输文件我使用的有两种方法,第一种就是比较多人使用的tftpd64

https://bitbucket.org/phjounin/tftpd64/downloads/

 另外一种就是使用Windows自带的TFTP客户端服务

在main函数中添加TFTP服务器初始化函数 

成功现象:

可以用wireshark捕获数据流查看

 STM32CubeProgrammer查看烧录成功

APP区,总的FLASH大小为128K即0x20000,剩余留给APP的大小为0x20000-0xB000=0x15000

添加这条命令才会在对应文件夹中生成.bin文件 

C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe  --bin -o  ..\OBJ\APP.bin ..\OBJ\AAP.axf

在main函数开始加入这句代码

SCB->VTOR = FLASH_BASE | 0xB000; /* Vector Table Relocation in Internal FLASH. */

如果需要从APP区再跳回去BootLoader区,这里套用正点原子的图,实现的就是④步骤

#define Bootloader_ADDR		0x08000000

static void JumpToBootloader(void)
{
 uint32_t i=0;
 void (*SysMemBootJump)(void); /* 声明一个函数指针 */

 /* 关闭全局中断 */
 __disable_irq(); 

 /* 关闭滴答定时器,复位到默认值 */
 SysTick->CTRL = 0;
 SysTick->LOAD = 0;
 SysTick->VAL = 0;

 /* 设置所有时钟到默认状态,使用 HSI 时钟 */
 HAL_RCC_DeInit();

 /* 关闭所有中断,清除所有中断挂起标志 */
 for (i = 0; i < 8; i++)
 {
 NVIC->ICER[i]=0xFFFFFFFF;
 NVIC->ICPR[i]=0xFFFFFFFF;
 }

 /* 使能全局中断 */
 __enable_irq();	//解除中断屏蔽

 /* 跳转到系统 BootLoader,首地址是 MSP,地址+4 是复位中断服务程序地址 */
 SysMemBootJump = (void (*)(void)) (*((uint32_t *) (Bootloader_ADDR + 4)));

 /* 设置主堆栈指针 */
 __set_MSP(*(uint32_t *)Bootloader_ADDR);
SCB->VTOR = FLASH_BASE | 0x0000;
 /* 跳转到系统 BootLoader */
 SysMemBootJump(); 
}

四、问题记录

1、ping不通,请求超时或者是无法访问主机

检查你的网卡设置,手动配置与单片机同一网段

软件复位ETH_RST,然后复位单片机

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
	HAL_Delay(60);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);
	HAL_Delay(60);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
	HAL_Delay(60);
	
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin : PB14 */
  GPIO_InitStruct.Pin = GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

2、接收数据无法写入flash,hal库自带的flash操作函数是有问题的,flash擦除的时候需要加适当延时和清除标志位

int8_t FLASH_If_Erase(uint32_t StartSector)
{
	HAL_FLASH_Unlock();   //解锁
  uint32_t FlashAddress;
 
  FlashAddress = StartSector;

  /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
     be done by word */ 
 
  while (FlashAddress <= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS)
  {
		if (FLASH_PageErase(FlashAddress) == HAL_OK)
    {
			FLASH_WaitForLastOperation(50000);            	//等待上次操作完成
			CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
      FlashAddress += FLASH_PAGE_SIZE;
    }
		else
		{
			return (1);
		}
	}
	HAL_FLASH_Lock();   //上锁
  return (0);
}

四、重点关注,需要读懂的.c文件

 

六、过程中使用的软件分享

此次BootLoader所占空间其实偏大,但因为本人算是初学者,不会怎么去优化内存大小,如有不妥之处望指正谅解!

SerialDebug

https://gitee.com/Weli572872916/SerialDebug

wireshark

https://www.wireshark.org/download.html

  • 38
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值