最近弄了串口IAP升级,始终感觉升级很麻烦, 需要超级终端或者其他支持ymodem的软件, 但是为用户考虑, 如果升级最简单的方式就是把设备模拟为一个U盘来完成升级.
问题
如果弄U盘升级, 需要外加一个spi flash, 或者SD卡, 这样成本就增加了
不过工业常用的是加一个spi flash来存储日志之类的, 如果我不想加外部的器件的情况下,想完成模拟U盘升级, 有2条路可以选,
1 把stm32 内部flash来存储
我想过这样的方法, 也去试过,但是发现stm32的扇区大小不一样, 每个型号都不一样的,所以就造成了难点, 另外一个扇区太大, 想要把扇区的数据保存起来很麻烦
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) //扇区0起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) //扇区1起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) //扇区2起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) //扇区3起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) //扇区4起始地址, 64 Kbytes
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) //扇区5起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) //扇区6起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) //扇区7起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) //扇区8起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) //扇区9起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) //扇区10起始地址,128 Kbytes
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) //扇区11起始地址,128 Kbytes
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) //扇区12起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) //扇区13起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) //扇区14起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) //扇区15起始地址, 16 Kbytes
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) //扇区16起始地址, 64 Kbytes
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) //扇区17起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) //扇区18起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) //扇区19起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) //扇区20起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) //扇区21起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) //扇区22起始地址, 128 Kbytes
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) //扇区23起始地址, 128 Kbytes
2 把内部RAM来当作存储空间
这种方式看来可以, 因为stm32h750之类的mcu 有1M的RAM, 只有很小的ROM, 所以这里我用100K RAM来模拟存储空间
#ifndef __RAMDISK_H_
#define __RAMDISK_H_
#define STORAGE_CAPPACITY 1024*100
#define STORAGE_BLK_SIZ 512
#define STORAGE_BLK_NBR STORAGE_CAPPACITY / STORAGE_BLK_SIZ
#define MEDIA_DESCRIPTOR 0xf8
void ramdisk_write(int32_t blk_addr, uint8_t *buf, uint16_t size);
void ramdisk_read(int32_t blk_addr, uint8_t *buf, uint16_t size);
#endif
#include "ramdisk.h"
uint8_t RamDisk[STORAGE_BLK_NBR * STORAGE_BLK_SIZ];
void ramdisk_write(int32_t blk_addr, uint8_t *buf, uint16_t size)
{
memcpy((void *)(RamDisk + blk_addr), buf, size);
}
void ramdisk_read(int32_t blk_addr, uint8_t *buf, uint16_t size)
{
memcpy(buf, (void *)(RamDisk + blk_addr), size);
}
具体实施
1 思路
1 插入USB情况 程序初始化完成之后, 先格式化RAMDISK为FAT32格式, 然后检测USB有没有插入, 如果插入了就等待USB断开
USB断开之后去查找RAMDISK里面有没有update.binz这个文件, 如果有这个文件 直接写入到flash, 然后跳转执行
2 没插入USB, 如果3S内没插入USB那么就直接跳转到应用地址执行
2 代码实现
1 usbd_storage_if.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : usbd_storage_if.c
* @version : v1.0_Cube
* @brief : Memory management layer.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @brief Usb device.
* @{
*/
/** @defgroup USBD_STORAGE
* @brief Usb mass storage device module
* @{
*/
/** @defgroup USBD_STORAGE_Private_TypesDefinitions
* @brief Private types.
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Defines
* @brief Private defines.
* @{
*/
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x10000
#define STORAGE_BLK_SIZ 0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
#include "ramdisk.h"
/* USER CODE END PRIVATE_DEFINES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Macros
* @brief Private macros.
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_Variables
* @brief Private variables.
* @{
*/
/* USER CODE BEGIN INQUIRY_DATA_FS */
/** USB Mass storage Standard Inquiry Data. */
const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0' ,'1' /* Version : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */
/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Exported_Variables
* @brief Public variables.
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */
/**
* @}
*/
/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
* @brief Private functions declaration.
* @{
*/
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);
/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
/**
* @}
*/
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS,
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS,
STORAGE_Write_FS,
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief Initializes over USB FS IP
* @param lun:
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
return (USBD_OK);
/* USER CODE END 2 */
}
/**
* @brief .
* @param lun: .
* @param block_num: .
* @param block_size: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
return (USBD_OK);
/* USER CODE END 3 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
/* USER CODE BEGIN 5 */
return (USBD_OK);
/* USER CODE END 5 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
ramdisk_read(STORAGE_BLK_SIZ * blk_addr, buf, STORAGE_BLK_SIZ * blk_len);
return (USBD_OK);
/* USER CODE END 6 */
}
/**
* @brief .
* @param lun: .
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
ramdisk_write(STORAGE_BLK_SIZ * blk_addr, buf, STORAGE_BLK_SIZ * blk_len);
return (USBD_OK);
/* USER CODE END 7 */
}
/**
* @brief .
* @param None
* @retval .
*/
int8_t STORAGE_GetMaxLun_FS(void)
{
/* USER CODE BEGIN 8 */
return (STORAGE_LUN_NBR - 1);
/* USER CODE END 8 */
}
/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
注意是在STORAGE_BLK_SIZ 之后才#include "ramdisk.h"
因为这样会把之前定义的覆盖掉
main.c函数伪代码
void main(){
// 格式化fatfs
fatfs_init();
//ram_disk_test();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
LL_USART_EnableIT_RXNE(USART1);
LL_USART_EnableIT_PE(USART1);
dev_comctrl_init();
printf("init\r\n");
uint8_t old_usb_state = 0;
uint8_t over_time = 0;
uint8_t usb_input_state = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
dev_comctrl_handle();
#ifdef USE_RX_MODE
ymodem_rx_time_handle();
#endif
if(hUsbDeviceFS.dev_state != old_usb_state){
if(hUsbDeviceFS.dev_state== USBD_STATE_CONFIGURED){
usb_input_state = 1;
printf("usb 已经连接\r\n");
}else if(hUsbDeviceFS.dev_state== USBD_STATE_SUSPENDED){
printf("usb 断开成功\r\n");
system_usb_finish_read();
}else{
}
old_usb_state = hUsbDeviceFS.dev_state;
}
// 如果插入超时,
if(over_time++>3){
// 没检查到USB 直接运行APP
if(usb_input_state == 0){
printf("---system run -app\r\n");
iap_load_app(KAPP_ADDR);
printf("---system run -app error!!!!\r\n");
}
}
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
USB插入状态是通过hUsbDeviceFS.dev_state 来检查的
代码地址:
git: https://github.com/kirito6/stm32_HAL_RAMDISK_USB_IAP
csdn: