Electronic – STM32, mass storage device. how to properly erase memory sectors

cstm32usb

I want to organize a USB stick based on STM32F105RBT + AT45DB041.
Problem: after reconnecting the device to a PC, windows7 asks to format the disk.

Problem identification algorithm:

  1. Connect to PC
  2. Format the USB flash drive (formatting is completed successfully)
  3. Write any file to a USB flash drive
  4. Disconnect the USB flash drive from the PC
  5. Connect device to PC
    Result: Windows asks to format the USB flash drive

Everything works fine if:
Size of file (-files) <= 12KB
(After reconnecting the USB flash drive to the PC, the file opens successfully, the data is not damaged)

SPI memory AT45DB041 has a total of 2048 pages of 264 bytes each. Writing / reading is performed at 256 bytes per page. Writing a 512 byte block requires two pages of memory.

I am sure that the problem is in the procedure for erasing memory sectors, in the STORAGE_Write_FS function, but I don’t understand where I went wrong?

    int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
    {
      /* USER CODE BEGIN 7 */
      AT45dbxx_ErasePage(blk_addr*2);
      AT45dbxx_ErasePage(blk_addr*2+1);
      AT45dbxx_WritePage(buf, 256, (uint16_t)blk_addr*2);
      AT45dbxx_WritePage(buf+256, 256, (uint16_t)blk_addr*2+1);
      return (USBD_OK);
    
      /* USER CODE END 7 */
    }

void AT45dbxx_ErasePage(uint16_t page)
{
    page = page << AT45dbxx.Shift; // AT45dbxx.Shift = 9 For 264 byte per page 
    AT45dbxx_Resume();
    AT45dbxx_WaitBusy();
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_RESET);
    AT45dbxx_Spi(AT45DB_PGERASE); // CMD 0x81
    AT45dbxx_Spi((page >> 16) & 0xff);
    AT45dbxx_Spi((page >> 8) & 0xff);
    AT45dbxx_Spi(page & 0xff);
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_SET);
    AT45dbxx_WaitBusy();
}

void AT45dbxx_WritePage(uint8_t *Data,uint16_t len,uint16_t page)
{
    page = page << AT45dbxx.Shift;  // AT45dbxx.Shift = 9 For 264 byte per page 
    AT45dbxx_Resume();
    AT45dbxx_WaitBusy();
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_RESET);
    AT45dbxx_Spi(AT45DB_MNTHRUBF1);  // CMD 0x82
    AT45dbxx_Spi((page >> 16) & 0xff);
    AT45dbxx_Spi((page >> 8) & 0xff);
    AT45dbxx_Spi(page & 0xff);
    HAL_SPI_Transmit(&_45DBXX_SPI,Data,len,100);
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_SET);
    AT45dbxx_WaitBusy();    
}

Functions for working with memory work correctly in the entire range of pages. The flash drive is formatted using windows before recording.

Best Answer

I fixed uint16_t page to uint32_t page and it worked. Thanks!

void AT45dbxx_ErasePage(uint32_t page)
{
    page = page << AT45dbxx.Shift; // AT45dbxx.Shift = 9 For 264 byte per page 
    AT45dbxx_Resume();
    AT45dbxx_WaitBusy();
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_RESET);
    AT45dbxx_Spi(AT45DB_PGERASE); // CMD 0x81
    AT45dbxx_Spi((page >> 16) & 0xff);
    AT45dbxx_Spi((page >> 8) & 0xff);
    AT45dbxx_Spi(page & 0xff);
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_SET);
    AT45dbxx_WaitBusy();
}
void AT45dbxx_WritePage(uint8_t *Data,uint16_t len,uint32_t page)
{
    page = page << AT45dbxx.Shift;  // AT45dbxx.Shift = 9 For 264 byte per page 
    AT45dbxx_Resume();
    AT45dbxx_WaitBusy();
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_RESET);
    AT45dbxx_Spi(AT45DB_MNTHRUBF1);  // CMD 0x82
    AT45dbxx_Spi((page >> 16) & 0xff);
    AT45dbxx_Spi((page >> 8) & 0xff);
    AT45dbxx_Spi(page & 0xff);
    HAL_SPI_Transmit(&_45DBXX_SPI,Data,len,100);
    HAL_GPIO_WritePin(_45DBXX_CS_GPIO,_45DBXX_CS_PIN,GPIO_PIN_SET);
    AT45dbxx_WaitBusy();    
}