2
\$\begingroup\$

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.

\$\endgroup\$
13
  • 2
    \$\begingroup\$ If you look at the disk image, you might be able to see what type of corruption is happening. (I recommend using HxD, a hex editor which can directly show you the bytes on a disk) \$\endgroup\$
    – user253751
    Oct 15, 2020 at 10:20
  • 1
    \$\begingroup\$ @user253751,Thanks for the recommendation to use HxD \$\endgroup\$
    – Chip115
    Oct 15, 2020 at 12:17
  • 1
    \$\begingroup\$ So it seems to me that your testing will not catch an issue where something goes wrong with addressing. What happens if there's a situation where the memory device always sees one of the address bit values stuck low (maybe there's a problem with the way you're sending the address to the device). You think you're writing & reading pages 0, 1, 2, 3, 4, 5, 6, 7, 8 - but say bit 2 is stuck low - then you'll actually be writing pages 0, 1, 2, 3, 0, 1, 2, 3 - your test won't catch that. But this kind of thing is exactly what could cause the symptoms you're seeing. \$\endgroup\$
    – brhans
    Oct 15, 2020 at 13:01
  • 3
    \$\begingroup\$ Your page parameter is a uint_16, but you're shifting it left 9 bits. You're effectively reducing your page address down to 7 bits. 128 pages x 256 bytes == 32k. Assuming your filesystem takes 20k of overhead (FAT tables) then once you write more than 12k to a file you'll wrap around and start overwriting the filesystem stuff and windows then will want to reformat it... \$\endgroup\$
    – brhans
    Oct 15, 2020 at 13:09
  • 1
    \$\begingroup\$ @brhans Yes you are right. I fixed uint16_t to uint32_t and it worked. Thanks! \$\endgroup\$
    – Chip115
    Oct 15, 2020 at 13:51

1 Answer 1

3
\$\begingroup\$

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();    
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.