# STM32 Mass Storage with 8K allocation unit size

I have an MSC/CDC Composite Device project that works with 4K allocation unit size for the mass storage. I am trying to convert this to use 8K allocation units instead, but the format does not complete successfully.

The flash memory is a QSPI flash (Cypress) with 32 4K sectors at the beginning, and 510 64K sectors afterwards. I want to use the 64K sectors because there are more of them. Unfortunately, I do not have 64K of RAM on the MCU (this is an STM32L443CCU) to cache the entire sector while I substitute new data. As such I have been using the 4K sectors as a backup area.

I cannot change the flash IC, or the microcontroller, so I have to use what I've got. If I use the 4K allocation unit size for mass storage, it works fine (it's slow, but it works). It cannot complete the format for the 8K allocation unit size.

Below are my functions for reading and writing, I would appreciate someone taking a fresh look over them to see if I missed something.

I have also updated the MSC_MEDIA_PACKET define to be 8192. I increased the heap and stack in the startup file, but I haven't seen any change in behaviour when doing that. Is there anything else I am forgetting?

Some defines first:

#define STORAGE_BLK_SIZ          8192
#define FLASH_MEMORY_PAGE_SIZE   256


int8_t STORAGE_Read_FS (uint8_t lun,
uint8_t *buf,
uint16_t blk_len)
{
uint32_t pages_to_read = STORAGE_BLK_SIZ * blk_len / FLASH_MEMORY_PAGE_SIZE;
uint8_t err_code;
uint32_t converted_block_addr = blk_addr * STORAGE_BLK_SIZ + 0x20000; // 0x20000 is where the 64K sectors start in flash

{
// Outta memory :(
return USBD_FAIL;
}
for (uint32_t i = 0; i < pages_to_read; i++)
{
if (err_code != HAL_OK)
{
return (USBD_FAIL);
}
}
return (USBD_OK);
}


The write function:

int8_t STORAGE_Write_FS (uint8_t lun,
uint8_t *buf,
uint16_t blk_len)
{

// 1. Convert address to match the start of 64K sectors
{
// Outta memory :(
return USBD_FAIL;
}
// 2. Figure out 64k sector that this address falls into
uint32_t start_64k_sector = (uint32_t)(converted_block_addr / 0x10000) * 0x10000;
// 3. Erase 4K sectors (starting at address 0x0) we need to store the 64K backup
for (uint8_t i = 0; i < (65536/4096); i++)
{
flashMemory_EraseSector(i * 4096);
}
// 4. Copy 64k sector, one 256 byte page at a time, and store in the 4K sectors
uint8_t buffer[256] = {0};
for (uint16_t i = 0; i < 256; i++)
{
flashMemory_WritePage(i * 256, buffer, 256);
}
// 5. Erase 64K sector
flashMemory_Erase64KSector(start_64k_sector);
// 6. Find location of data in 64k sector
uint8_t data_loc_64k_sector = (converted_block_addr - start_64k_sector)/STORAGE_BLK_SIZ;
// 7. a) Restore old data from 4K sectors, up until the point of new data
for (uint16_t i = 0; i < data_loc_64k_sector; i++)
{
for (uint16_t j = 0; j < (STORAGE_BLK_SIZ/256); j++)
{
flashMemory_ReadPage(i * STORAGE_BLK_SIZ + j * 256, buffer);
flashMemory_WritePage(start_64k_sector + i * STORAGE_BLK_SIZ + j * 256, buffer, 256);
}
}
// 7. b) Write new data
for (uint16_t j = 0; j < (STORAGE_BLK_SIZ/256); j++)
{
flashMemory_WritePage(start_64k_sector + data_loc_64k_sector * STORAGE_BLK_SIZ + j * 256, &buf[j * 256], 256);
}
// 7. c) Write all remaining old data after new data
for (uint16_t i = (data_loc_64k_sector + 1); i < (65536/STORAGE_BLK_SIZ); i++)
{
for (uint16_t j = 0; j < (STORAGE_BLK_SIZ/256); j++)
{
flashMemory_ReadPage(i * STORAGE_BLK_SIZ + j * 256, buffer);
flashMemory_WritePage(start_64k_sector + i * STORAGE_BLK_SIZ + j * 256, buffer, 256);
}
}

• Error is highly likely in code not shown. – Turbo J Apr 2 '18 at 18:46
• @TurboJ, I cannot post the entire project. The flashMemory functions were verified using the 4K sectors... They do not hardcode 4096 anywhere, so I don't know why that would affect it. – Catsunami Apr 2 '18 at 18:52
• @TurboJ, the mistake is in the posted code. I will answer when I verify the fix. – Catsunami Apr 2 '18 at 19:17
• What you need here is a flash translation layer. – duskwuff Apr 2 '18 at 19:18
• You have a whole lot of "sloppy typed" integer literals in this code. You have to realize that each such literal larger than 65535 means that you force the type implicitly to signed long. Only a matter of time until you get bugs caused by this. One solution is to never write "magic numbers" in your code, which you shouldn't be doing anyway. – Lundin Apr 6 '18 at 11:41