900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > HAL库U盘升级 STM32F407 CUBEMX:FATFS + USB_HOST + USB_OTG_FS

HAL库U盘升级 STM32F407 CUBEMX:FATFS + USB_HOST + USB_OTG_FS

时间:2022-03-07 13:03:06

相关推荐

HAL库U盘升级 STM32F407 CUBEMX:FATFS + USB_HOST + USB_OTG_FS

一、测试平台:

MCU:STM32F407VET6

固件库:CUBEMX

IDE:MDK

二、实验目的:

将U盘里面的bin文件插入要升级的设备,通过BootLoader来进行升级

在这是用板载的LED灯来显示升级情况:

不进行升级:LED灯是灭的状态

升级成功:LED灯以100ms在闪烁

接下来先进行BootLoader的配置以及程序编写,再配置APP

三、BootLoader:

1 下载器配置

2 时钟源配置

3 LED配置

4 串口配置 开启全局中断

5 USB_OTG_FS配置

6 USB_HOST配置

7 FATFS配置

8 时钟树配置 48M是用来操作U盘的,所以必须要有

9 工程配置

10 生成工程

11 创建两个空白文件文件

BootLoader.h

#ifndef __BOOTLOADER_H#define __BOOTLOADER_H#include "stm32f4xx_hal.h"#include "usb_host.h"#include "fatfs.h"#include "usart.h"#define ADDR_FLASH_SECTOR_0((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */#define ADDR_FLASH_SECTOR_1((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */#define ADDR_FLASH_SECTOR_2((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */#define ADDR_FLASH_SECTOR_3((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */#define ADDR_FLASH_SECTOR_4((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */#define ADDR_FLASH_SECTOR_5((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */#define ADDR_FLASH_SECTOR_6((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */#define ADDR_FLASH_SECTOR_7((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */#define ADDR_FLASH_SECTOR_8((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */#define ADDR_FLASH_SECTOR_9((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */#define RAM_BUFFER_SIZE((uint32_t)30*1024) /*KBytes*/#define filename "LED.bin"#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_4 /* Start @ of user Flash area */#define FLASH_USER_END_ADDRADDR_FLASH_SECTOR_4 + 0x10000uint32_t FLASH_Erase_Write(void);static uint32_t GetSector(uint32_t Address);void jumpToApp(void);void UP_Data(void);#endif

BootLoader.c

#include "BootLoader.h"extern ApplicationTypeDef Appli_state;FRESULT res;static FLASH_EraseInitTypeDef EraseInitStruct;uint8_t RAM_Buffer[RAM_BUFFER_SIZE];uint32_t APP_Size;uint32_t FirstSector = 0, NbOfSectors = 0, Address = 0;uint32_t SectorError = 0;__IO uint32_t data32 = 0 , MemoryProgramStatus = 0;uint8_t errorcode;uint32_t *p;uint8_t SystemUpdateFlag = 0, state = 0;uint16_t t = 0;typedef void (*pFunction)(void);pFunction Jump_To_Application;uint32_t JumpAddress;int fputc(int ch, FILE *f)//用来打印信息的 便于观察{HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 100);return ch;}uint32_t FLASH_Erase_Write(void)//FLASH擦写{uint32_t i = 0;HAL_FLASH_Unlock();FirstSector = GetSector(FLASH_USER_START_ADDR);NbOfSectors = GetSector(FLASH_USER_END_ADDR) - FirstSector + 1;EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;EraseInitStruct.Sector = FirstSector;EraseInitStruct.NbSectors = NbOfSectors;if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK){errorcode = HAL_FLASH_GetError();//擦除失败的扇区printf("errorcode %d", errorcode);Error_Handler();}__HAL_FLASH_DATA_CACHE_DISABLE();__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();__HAL_FLASH_DATA_CACHE_RESET();__HAL_FLASH_INSTRUCTION_CACHE_RESET();__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();__HAL_FLASH_DATA_CACHE_ENABLE();printf("HAL_OK\r\n");Address = FLASH_USER_START_ADDR;while (Address < FLASH_USER_END_ADDR){p = (uint32_t *)&RAM_Buffer[i];if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, *p) == HAL_OK)//FLASH写入{Address = Address + 4;i = i + 4;}else{printf("Address-error\r\n");Error_Handler();}}HAL_FLASH_Lock(); Address = FLASH_USER_START_ADDR;//校验MemoryProgramStatus = 0x0;printf("CHEAK\r\n");while (Address < FLASH_USER_END_ADDR){data32 = *(__IO uint32_t*)Address;if (data32 != *(uint32_t*)RAM_Buffer){MemoryProgramStatus++;}Address = Address + 4;}printf("CHEAK-finish\r\n");return HAL_OK;}static uint32_t GetSector(uint32_t Address)//获取扇区{uint32_t sector = 0;if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0)){sector = FLASH_SECTOR_0; }else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1)){sector = FLASH_SECTOR_1; }else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2)){sector = FLASH_SECTOR_2; }else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3)){sector = FLASH_SECTOR_3; }else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4)){sector = FLASH_SECTOR_4; }else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5)){sector = FLASH_SECTOR_5; }else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6)){sector = FLASH_SECTOR_6; }else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7)){sector = FLASH_SECTOR_7; }else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8)){sector = FLASH_SECTOR_8; }else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9)){sector = FLASH_SECTOR_9; }else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10)){sector = FLASH_SECTOR_10; }else /* (Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11) */{sector = FLASH_SECTOR_11;}return sector;}void jumpToApp(){if (((*(__IO uint32_t*)FLASH_USER_START_ADDR) & 0x2FFE0000 ) == 0x20000000){printf("ADDR == 0x20000000\r\n");JumpAddress = *(__IO uint32_t*) (FLASH_USER_START_ADDR + 4);Jump_To_Application = (pFunction) JumpAddress;__set_MSP(*(__IO uint32_t*) FLASH_USER_START_ADDR);__HAL_UART_DISABLE(&huart3);//关闭相应中断__HAL_RCC_USB_OTG_FS_CLK_DISABLE();__HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_TC);__HAL_UART_DISABLE_IT(&huart3, UART_IT_RXNE);Jump_To_Application();}printf("ADDR != 0x20000000\r\n");}void UP_Data(void){if(state == 0){if(t < ){if(SystemUpdateFlag == 0 && Appli_state == APPLICATION_READY){printf("APPLICATION_READY\r\n");SystemUpdateFlag = 1;t = 2000;state = 1;res = f_mount(&USBHFatFS, (TCHAR const*)USBHPath, 0);if(res != FR_OK){printf("U盘挂载失败 %d\r\n", res);Error_Handler();}else{printf("U盘挂载成功\r\n");}res = f_open(&USBHFile, filename, FA_READ);if(res != FR_OK){printf("打开U盘文件失败 %d\r\n", res);Error_Handler();}else{printf("打开U盘文件成功\r\n");}res = f_read(&USBHFile, RAM_Buffer, sizeof(RAM_Buffer), (void *)&APP_Size);if(res != FR_OK){printf("读取U盘文件失败 %d\r\n", res);Error_Handler();}else{printf("读取U盘文件成功\r\n");}if((0<APP_Size) && (APP_Size<FLASH_USER_END_ADDR)){printf("FLASH_Erase\r\n");FLASH_Erase_Write();jumpToApp();}else{printf("APP_Size错误\r\n");}f_close(&USBHFile);//FATFS_UnLinkDriver(USBHPath);}else{printf("%d\r\n", t);t++;HAL_Delay(1);}if(state == 0 && t > 2000)//超过2s 读取U盘失败{state = 1;printf("DISCONNECT\r\n");jumpToApp();}}}}

四、APP:

1 APP程序只进行LED闪烁,只配置这三个功能就够了

2 时钟树配置

3 工程配置

4 接下来是APP程序

(1)main.c 只放LED闪烁的功能

(2)中断偏移地址 这个地址要和BootLoader程序里面flash的起始地址要一样

(3)魔术棒配置

D:\software\keil5\path \ARM\ARMCLANG\bin\fromelf.exe --bin --output ./APP/LED.bin ./APP/APP.axf

详细说明

D:\software\keil5\path \ARM\ARMCLANG\bin\fromelf.exe

formelf.exe是Keil自带的格式工具软件,其路径在你电脑的Keil安装盘的对应位置;

不要以为这里啥也没有,这里是有一个空格的;

--bin

输出bin文件的命令语句;

空格;

--output

输出文件的命令语句,也可以写成简写的形式:-o;

空格;

./APP/LED.bin

APP是我用于存放输出bin文件的文件夹(系统默认此路径从工程文件开始算起),LED.bin是我生成的bin文件;

空格;

./APP/APP.axf

APP是用于存放axf输入文件的文件夹,生成bin文件前,要先生成axf输入文件;

配置好后点击OK,编译一下工程,bin文件就生成了

添加全局变量 USER_VECT_TAB_ADDRESS

,USER_VECT_TAB_ADDRESS

变量前面有个逗号 英文的

将生成的bin文件放到U盘里

五、实验现象:

BootLoader第一次下载是最好是进行一下全片擦除,之后使用扇区擦除

(1)没有检测到U盘现象

蓝色是电源指示灯,红框才是实验灯(红色的)

串口打印信息

两秒没有检测到U盘打印的信息

没有检测到U盘

(2)检测到U盘现象

红色LED以100ms的时间在闪烁

升级成功现象

串口打印信息

检测到U盘

六、文件篇:

U盘升级STM32F407(文件篇)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。