STM32F103C8T6作为具有FAT12文件系统的闪存驱动器

开发设备时,通常需要将设置存储在工作程序外部。 无需使用特殊工具即可对其进行修改甚至更好。

考虑在最常见的STM F103微控制器中的存储选项。 著名的Blue Pill面包板也促进了流行。

图片
内置的闪存不仅允许使用内部闪存中的FAT12文件系统存储和修改设置,而且还可以组织固件更新。

根据文档,STM32F103C8T6具有64K闪存。 但是,几乎在所有STM32F103C8T6中都安装了128K。 各种来源也提到了这一点-他们通常会多出64K。 此“功能”使您可以将微控制器用作容量为128K-20K(系统需要FAT12)-固件大小的闪存驱动器。

许多尝试将此控制器用作闪存驱动器的发烧友都遇到了在FAT12文件系统模式下使用该控制器的问题。 用于删除/填充原来的磁盘映像。 但是,当与文件驱动器一起使用时,问题就开始了。

此问题在于访问扇区(块)的顺序不同。 加载磁盘映像后,会顺序进行记录,例如:

-记录块号1
-记录块号2
-记录块号3。

写入FAT12数据时,可以任意进行记录:

-记录第3块,
-记录块号1
-记录块号2。

并且,由于写入闪存需要擦除整个1K页,因此,在驱动器中使用512字节的扇区时(并且您不能使用其他扇区),如果使用随机访问,则将擦除相邻扇区中的信息。 为了防止这种情况的发生,以上示例使用了一个512字节的数组来存储相邻扇区。 并记录如下:

-确定页面开头的地址,
-记住邻近的领域,
-擦除页面,
-写一个记忆的领域,
-写入数据。

为了避免在没有需要的情况下进入铁的丛林,我在CubeMX中准备了该项目。

我将举一个通过HAL写入Flash的函数示例(usbd_storage_if.c)

//    flash void writeBuf (uint32_t page_addr, uint8_t *buf){ uint32_t erase_addr=get_erase_addr(page_addr); uint32_t buf_erase_addr; uint32_t buf32; if (page_addr != erase_addr) { buf_erase_addr=erase_addr; } else { buf_erase_addr=erase_addr+STORAGE_BLK_SIZ; } HAL_FLASH_Unlock(); //      set_buf_before_erase(buf_erase_addr); //       FLASH_EraseInitTypeDef EraseInitStruct; uint32_t PAGEError = 0; EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = erase_addr; EraseInitStruct.NbPages = 1; HAL_FLASHEx_Erase(&EraseInitStruct,&PAGEError); //    for (int i=0; i<STORAGE_BLK_SIZ/4;i++) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,buf_erase_addr,blk_buff[i]); buf_erase_addr+=4; } //   for (int i=0; i<STORAGE_BLK_SIZ/4;i++) { buf32=*(uint32_t *)&buf[i*4]; HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, page_addr,buf32); page_addr+=4; } HAL_FLASH_Lock(); } 

我得到的二进制文件大小约为20K,因此我的数据存储页定义为0x08006000(24K)。

我们进行编译(示例的源代码可在此处获取)。

我们连接:

 [ 8193.499792] sd 4:0:0:0: Attached scsi generic sg2 type 0 [ 8193.502050] sd 4:0:0:0: [sdb] 128 512-byte logical blocks: (65.5 kB/64.0 KiB) [ 8193.502719] sd 4:0:0:0: [sdb] Write Protect is off [ 8193.502722] sd 4:0:0:0: [sdb] Mode Sense: 00 00 00 00 [ 8193.503439] sd 4:0:0:0: [sdb] Asking for cache data failed [ 8193.503445] sd 4:0:0:0: [sdb] Assuming drive cache: write through [ 8193.523812] sdb: [ 8193.526914] sd 4:0:0:0: [sdb] Attached SCSI removable disk 

光盘确定了,一切都很好!

让我们开始形成分区并格式化磁盘。

在Linux上,从命令行非常简单:

 sudo fdisk /dev/sdb 



FAT12格式:

 sudo mkfs.fat /dev/sdb -F 12 

复制文件以进行测试:



但是,请不要忘记,根据文档,闪存重写周期数
保证只在100,000之内。例如,格式化和写入单个30K文件将需要(根据此示例的调试日志):

 00106 44 67 Write_FS blk_addr=003 0x08006600 

106个重写周期。

问题仍然存在-如何通过直接访问FAT12文件读取数据?
在下一篇文章中有关此内容。
感谢您的关注!

Source: https://habr.com/ru/post/zh-CN441660/


All Articles