STM32F407+USB在线升级

USB和文件系统移植成功后,就可以开始主函数的书写

首先主函数里面需要循环调用USBH_Process函数,它的作用是:用于实现USB主机通信的核心状态机处理,该函数必须被循环调用,而且调用频率越快越好,以便及时处理各种事务

其次,当设备检测到USB的插入后,会自动跳转到USH_User_App函数,此时我们需要在该函数中加入程序升级的代码,具体思路如下:读.bin文件,然后下载到指令地址,最后跳转到指令地址运行。

最后,总体实现代码如下所示。

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"  
#include "sdio_sdcard.h"    
#include "ff.h"  
#include "string.h"
#include "usbh_usr.h" 
#include "flash.h"

//首先对内部Flash空间进行划分,前128K用于存储BootLoader程序,后面的空间用于存储App程序。
#define IAP_SIZE                           ((uint32_t)0x60000)   /* 128Kbytes as IAP size */
#define APPLICATIONADDRESS                 ((uint32_t)0x08060000) /* User start code space */
#define APPLICATIONSIZE                    ((uint32_t)0x080E0000)
#define BUF_SIZE	128

u8 buf[BUF_SIZE+5];

USBH_HOST  USB_Host;
USB_OTG_CORE_HANDLE  USB_OTG_Core;
int writeNewProgram(void);

typedef  void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;

//跳转到App程序运行 
void jumpToApp(void)
{
	if ( ( ( * ( __IO uint32_t * ) APPLICATIONADDRESS ) & 0x2FFE0000 ) == 0x20000000 ) //检查栈顶地址是否有数据,FLASH写入成功
	{
		printf("正在跳转运行程序\r\n");
		JumpAddress = *(__IO uint32_t*) (APPLICATIONADDRESS + 4);//用户代码区第二个字为程序开始地址(复位地址)
		Jump_To_Application = (pFunction) JumpAddress;//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		MSR_MSP(*(vu32*)APPLICATIONADDRESS);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		
		RCC_AHB2PeriphClockCmd( RCC_AHB2Periph_OTG_FS , DISABLE);  //必须失能USB,不然后续代码会因为USB卡死
		
		Jump_To_Application();
	}
}

//U盘插入以后,实现用户需要实现的功能
//返回值:0,正常
//       1,有问题
u8 USH_User_App(void)
{ 
	u8 result=0;
	printf("USB设备连接成功\r\n");	
	if(!writeNewProgram())
		jumpToApp();
	
	while(HCD_IsDeviceConnected(&USB_OTG_Core))//只要U盘是连接状态,则一直执行while循环
	{	
		
	}
	
	printf("USB设备连接中\r\n");	 
	return result;
} 

int writeNewProgram(void)
{
    FRESULT result;
    FIL fil;
	FATFS fs;
	int isFinish = 0;
	int bytesread;
	char *fileName="LED.bin";
	
	uint32_t startaddress = APPLICATIONADDRESS;
    uint32_t endaddress = APPLICATIONSIZE;
	
    printf("start write new program");
	result=f_mount(&fs,"0:",1); 	//重新挂载U盘
	printf("f_mount %d\r\n",result);
	
    result = f_open(&fil,fileName, FA_READ );//打开程序文件
	printf("f_open %d\r\n",result);
	
    if(result)
    {
        printf("open %s error\r\n",fileName);
		isFinish=1;
    }
    else
    {
        printf("open %s sucess\r\n",fileName);
    }
 
    printf("start program\r\n");
    while( startaddress < endaddress && isFinish == 0)
    {
        result = f_read(&fil, buf,BUF_SIZE, (UINT*)&bytesread);//读取128Bytes数据
        if(result)
        {
            printf("read address  error\r\n");
			isFinish=1;
            break;
        }
        else
        {
            printf("read address sucess ,data is :%d\r\n",bytesread);
        }
		if(STMFLASH_Write(startaddress,(uint32_t *)buf,bytesread/4))
		{
			 printf("STMFLASH_Write err\r\n");
		}
		else
		{
			 printf("STMFLASH_Write OK\r\n");
		}
		
		startaddress += bytesread;
		
        if( bytesread < BUF_SIZE )//如果读取数据长度错误或者读取完毕
        {
            break;
        }
		
    }
	
    result = f_close(&fil);
    if(result)
    {
        printf("close %s error:%d\r\n",fileName,result);
    }
    else
    {
        printf("close %s sucess\r\n",fileName);
    }
    printf("end write program\r\n");
	result=f_mount(NULL,"0:",0); 
    return isFinish;
}

int main(void)
{        
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	
	//初始化USB主机
  	USBH_Init(&USB_OTG_Core,USB_OTG_FS_CORE_ID,&USB_Host,&USBH_MSC_cb,&USR_Callbacks);  
	while(1)
	{
		USBH_Process(&USB_OTG_Core, &USB_Host);//用于实现USB主机通信的核心状态机处理,该函数必须被循环调用,而且调用频率越快越好,以便及时处理各种事务
	
	}
}





链接:https://pan.baidu.com/s/18uUT0wrLKnioZBnBwAgD6w
提取码:生日

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F407模拟U盘固件升级是通过将STM32F407单片机作为一个虚拟的U盘设备,在电脑上进行固件升级操作的过程。 首先,我们需要连接STM32F407开发板和电脑,通过USB接口将STM32F407连接到电脑上。 然后,在STM32F407的固件中,需要实现USB设备功能,并设置为虚拟U盘设备。这需要使用STM32CubeMX软件进行配置,选择USB Device模块,并配置为Mass Storage设备模式。 接着,需要在固件中编写相应的应用程序,实现固件升级的功能。这包括接收来自电脑的固件升级文件,将文件数据保存在STM32F407的存储器中。 在固件中,还需要实现固件校验的功能,确保升级文件的完整性和正确性。可以通过计算文件的CRC校验码,并将其与预先计算好的校验码进行比较。 在固件升级的过程中,首先用户需要将电脑上的固件升级工具运行起来,并选择固件升级的选项。然后,电脑会识别STM32F407模拟的U盘设备,并将升级文件传输到STM32F407上。 在固件传输完成后,STM32F407会进行固件校验,确认升级文件的完整性和正确性。如果校验通过,STM32F407会将升级文件写入Flash存储器中,完成固件升级。 最后,在固件升级完成后,STM32F407会重新启动,加载新的固件程序,并开始运行。 总的来说,STM32F407模拟U盘固件升级是通过将STM32F407作为虚拟U盘设备,在电脑上进行固件升级的过程,需要实现USB设备功能和固件校验功能,确保升级文件的完整性和正确性。这种方案可以方便快捷地进行固件升级,提高开发效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值