📜 ⬆️ ⬇️

STM32F103C8T6 as a flash drive with FAT12 file system

When developing devices, it is often necessary to store settings outside the work program. It is even better to be able to modify them without using special tools.

Consider the option of storage in perhaps the most common STM F103 series microcontrollers. The prevalence was also contributed by the well-known Blue Pill breadboard

image
Its flash allows not only to store and modify the settings using the FAT12 file system in the internal flash, but also to organize the firmware update.
')
According to the documentation in STM32F103C8T6 there is 64K flash memory. However, almost all STM32F103C8T6 installed 128K. This is also mentioned in different sources - usually put on 64K more. Such a “feature” allows you to use a microcontroller as a 128K - 20K flash drive (FAT12 system needs) - the size of the firmware.

Many enthusiasts who tried to use this controller as a flash drive faced the problem of using it in the FAT12 file system mode. Use to remove / fill the disk image turned out. But when working with a file drive, problems started.

This problem consists in a different sequence of access to sectors (blocks). When loading a disk image, recording occurs sequentially, for example:

-record block number 1,
- record of block 2,
-record block number 3.

When writing data FAT12 recording can occur arbitrarily:

- writing unit №3,
-record block number 1,
-record block number 2.

And, since writing into flash requires erasing the entire 1K page, when using 512 byte sectors in the drive (and using other sector sizes fails), if random access is used, the information in the adjacent sector is erased. To prevent this from happening, in the example above, an array of 512 bytes is used to store the neighboring sector. And the recording should be as follows:

- we define the address of the beginning of the page,
- we remember the neighboring sector,
- erase the page,
- we write the remembered sector,
- write data.

In order not to go deep into the wilds of iron without the required need, I prepared a project in CubeMX.

I will give an example of the function of writing to flash via HAL (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(); } 

The size of the binary file turned out to be about 20K, so I have a data memory page with 0x08006000 (24K).

Compile (example sources can be found here).

We connect:

 [ 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 

The disc is determined, everything is fine!

Let's start forming the partition and formatting our disk.

On Linux, this is quite simple from the command line:

 sudo fdisk /dev/sdb 



formatted in FAT12:

 sudo mkfs.fat /dev/sdb -F 12 

Copy the file for the test:



However, we should not forget that according to the documentation, the number of flash rewriting cycles
guaranteed only within 100,000. For example, formatting and writing one file will take 30K (according to the debug log of this example):

 00106 44 67 Write_FS blk_addr=003 0x08006600 

106 rewrite cycles.

That's all. Thanks for attention!

Source: https://habr.com/ru/post/441660/


All Articles