STM32F407内部FLASH做U盘

FLASH内部结构

Table 5. Flash module organization (STM32F40x and STM32F41x)
Block Name Block base addresses Size
Main memory
Sector 0 0x0800 0000 - 0x0800 3FFF 16 Kbytes
Sector 1 0x0800 4000 - 0x0800 7FFF 16 Kbytes
Sector 2 0x0800 8000 - 0x0800 BFFF 16 Kbytes
Sector 3 0x0800 C000 - 0x0800 FFFF 16 Kbytes
Sector 4 0x0801 0000 - 0x0801 FFFF 64 Kbytes
Sector 5 0x0802 0000 - 0x0803 FFFF 128 Kbytes
Sector 6 0x0804 0000 - 0x0805 FFFF 128 Kbytes
.............................
Sector 11 0x080E 0000 - 0x080F FFFF 128 Kbytes
System memory 0x1FFF 0000 - 0x1FFF 77FF 30 Kbytes
OTP area  0x1FFF 7800 - 0x1FFF 7A0F 528 bytes
Option bytes 0x1FFF C000 - 0x1FFF C00F 16 bytes

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
  uint32_t n,ii;
  uint32_t Address = 0;
  if(blk_addr < BLOCK1_VA_ADDR)
  {
    Address = BLOCK1_PY_ADDR;
  }
  else if(blk_addr < BLOCK2_VA_ADDR)
  {
    Address = BLOCK2_PY_ADDR;
    blk_addr -= BLOCK1_VA_ADDR;
  }
  else if(blk_addr < BLOCK3_VA_ADDR)
  {
    Address = BLOCK3_PY_ADDR;
    blk_addr -= BLOCK2_VA_ADDR;
  }
  else if(blk_addr < BLOCK4_VA_ADDR)
  {
    Address = BLOCK4_PY_ADDR;
    blk_addr -= BLOCK3_VA_ADDR;
  }
  else
  {
    return (USBD_FAIL);
  }
  
  for(n = 0;n < blk_len;n++)
  {
    for(ii = 0;ii<STORAGE_BLK_SIZ;ii++)
    {
      buf[ii] = (*(__IO uint8_t*)(Address + ((n + blk_addr) * STORAGE_BLK_SIZ) + ii));
    }
  }
  return (USBD_OK);
  /* USER CODE END 6 */
}

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
  uint32_t n,ii,index,erase_flag = 0;
  uint32_t Address = 0, FLASH_SECTOR = 5, SectorError = 0;
  // 地址转换
  if(blk_addr < BLOCK1_VA_ADDR)
  {
    Address = BLOCK1_PY_ADDR;
    FLASH_SECTOR = 5;
  }
  else if(blk_addr < BLOCK2_VA_ADDR)
  {
    Address = BLOCK2_PY_ADDR;
    blk_addr -= BLOCK1_VA_ADDR;
    FLASH_SECTOR = 6;
  }
  else if(blk_addr < BLOCK3_VA_ADDR)
  {
    Address = BLOCK3_PY_ADDR;
    blk_addr -= BLOCK2_VA_ADDR;
    FLASH_SECTOR = 7;
  }
  else if(blk_addr < BLOCK4_VA_ADDR)
  {
    Address = BLOCK4_PY_ADDR;
    blk_addr -= BLOCK3_VA_ADDR;
    FLASH_SECTOR = 8;
  }
  else
  {
    return (USBD_FAIL);
  }
  // 判断是否是可用块
  index = 0;
  erase_flag = 0;
  for(n = 0;n < blk_len;n++)
  {
    for(ii = 0;ii<STORAGE_BLK_SIZ;ii++)
    {
      RAM_DISK[index] = (*(__IO uint8_t*)(Address + ((n + blk_addr) * STORAGE_BLK_SIZ) + ii));
      if(RAM_DISK[index] != 0xff)
      {
        erase_flag = 1;
        break;
      }
      index++;
    }
  }
  // 如果已经使用,全部读出来后,擦除
  HAL_FLASH_Unlock();
  if(erase_flag)
  {
    // 读出来
    for(n = 0;n < (32 * 1024); ++n)
    {
      RAM_DISK[n] = (*(__IO uint8_t*)(Address + n));
    }
    // 擦除
    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
    EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
    EraseInitStruct.Sector = FLASH_SECTOR;
    EraseInitStruct.NbSectors = 1;
    if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
    {
      return (USBD_FAIL);
    }
    // 修改数据
    for(n = 0;n < blk_len;n++)
    {
      for(ii = 0;ii<STORAGE_BLK_SIZ;ii++)
      {
        RAM_DISK[(blk_addr + n) * STORAGE_BLK_SIZ + ii] = buf[n * STORAGE_BLK_SIZ + ii];
      }
    }
    // 回写
    for(n = 0;n < (32 * 1024); ++n)
    {
      if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, Address + n, RAM_DISK[n]) != HAL_OK)
      {
        return (USBD_FAIL);
      }
    }
  }
  else
  {
    // 写入
    for(n = 0;n < blk_len;n++)
    {
      for(ii = 0;ii<STORAGE_BLK_SIZ;ii++)
      {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, Address + ((n + blk_addr) * STORAGE_BLK_SIZ) + ii, buf[n * STORAGE_BLK_SIZ + ii]);
      }
    }
  }
  HAL_FLASH_Lock();
  return (USBD_OK);
  /* USER CODE END 7 */
}

本例使用Sector 5/6/7/8共4 Sector,每Sector 会用前面32K,这样一共就能模拟128K的U盘,每个block为512B,逻辑上共256 Block。

在读的时候,直接根据blk_add判断使用的哪些block,然后对应到物理地址Sector,然后直接读取,这部分没问题。

在写的时候,当写入(写入包括FAT表部分和DATA部分)时,先判断blk_add和blk_len,把blk_add*512B*blk_len的数据读出来,判断是否全为0XFF,如果全部为0XFF,则直接写。否则已经使用,需要擦除再写。

那么问题来了:

当所要写入的区域需要擦除的时候,此时因为每个Sector只使用前面32K,所以得先把原有的32K读到SRAM,然后把128K的Sector擦除,在读出来的32K数据中,改写需要写入的数据,然后再把32K回写到Sector中。那么,FAT表得改写,数据也得改写,而且FAT表和数据不一定在同一Sector中,此时就需要多次擦除,这不但效率慢(擦除过程需要时间),而且操作频繁,FLASH是有寿命的。

所以,这种方法是不可取的,本人接触不久,水平有限,暂时没有想到什么好方法,还请各路大神指点迷津。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值