cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 - FileX and MSC - Windows read wrong data

Dams
Associate III

Hi, 

I'm on a applicaiton involving USBX MSC and FileX. 
The final memory for the application is a NOR flash so I also use LevelX.

Acutally, I'm working on a nucleo-U575ZI-Q without NOR flash so I use NOR Simulator on LevelX.

My problem is that a file created with FileX is detected by windows, have the right number of bytes but data are wrong.

My program do this:

1) FileX format the device
2) FileX create the file STM32.TXT and put the data "This is FileX working on STM32". I can see this data on the RAM

3) FileX close and open the file STM32.TXT and I can read the text

4) FileX close the media.

5) USBX open the media and on Windows I see the file STM32.TXT but data are not correct. It's like if this data comes from another part on my RAM.

Dams_0-1760544703605.png

When the device is connected to a computer, I can create new file, write on it then unplug / plug USB and the new file is still here. I can also edit STM32.TXT.

Has somebody an idea about why FileX can read right data but windows doesn't read right data even if the device is mounted.

Thanks for help !

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hi Dmitry,

Thanks for the clue.
My mistake was on the USBX functions USBD_STORAGE_Write and USBD_STORAGE_Read on the glue (wrong interpretation of number_blocks)

It's now working well.

 

Regards, 

Dams

 

 

View solution in original post

19 REPLIES 19
DmitryR
Senior

Hello Dams,

 

what I should tell you first of all. As you are accessing FileX from two independent processes, USBX and internal make sure there is no collision between them.

Then, from your words it looks like that the USBX can write FileX properly but cannot read it properly. In this case it would be handy to see what glue code have you written for USBX read request.

 

Regards,

Dmitry

Hi Dmitry,

Thanks for the clue.
My mistake was on the USBX functions USBD_STORAGE_Write and USBD_STORAGE_Read on the glue (wrong interpretation of number_blocks)

It's now working well.

 

Regards, 

Dams

 

 

FBL
ST Employee

Hi @Dams @DmitryR 

So, you confirm the key is to correctly interpret the block size and total sector count used in USBX match those reported by FileX media (fx_media_bytes_per_sector and fx_media_total_sectors)?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Dams
Associate III

Hi, 

Yes theses variables looks right, the mounted device has the right size.
My final NOR chip has a sector size of 4096 bits. So in LevelX I change sector size to 4096  (and increase some buffer, stack and pool size to avoid hard fault)  

Dams_0-1760628714444.png

I'm still with the emulated NOR in RAM.
Everything works well with sector size of 512 or 1024 but since 2048 It does't works.
Windows detect a USB device and ask me to insert a disk in the drive.
With FileX only: I can create a file and read it. I see the file and the texte on my RAM. It seems to have a new block each 0x1000 (=4096) as asked.
With USBX only: windows detect a drive and ask me to format it with 4096o. It works fine and I can create a file with some texte and on RAM I also see block of 0x1000.

It seems that after 1024 bits of sector size, FIlexX ans USBX doesn't works together.

Have you got a idea where is the problem ?

About the sector size, can you confirme I need to set it to 4096 if my NOR has a sector of 4096 bits ?

 

Thanks in advance for feed back.

 

Regards, 

Dams

 

 

 

Hello Dams,

 

Yes, sector size setting in the LevelX may not be less that physical sector size. Otherwise the system may try to erase a chunk that is less than a physical sector that is impossible. And once again, could you please post you code?

 

With best regards,

Dmitry

Dams
Associate III

Hi Dmitry, 

Please find below my code:

Conf cube U5 FileX LevelX USBX.png

 

main.c:

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */
  MX_FileX_Init();
  MX_USBX_Device_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	USBX_Device_Process(NULL);
  }
  /* USER CODE END 3 */
}

app_filex.c:

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "main.h"
#include "lx_stm32_nor_simulator_driver.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
FX_MEDIA        nor_flash_disk;
FX_FILE         fx_file;
extern LX_NOR_FLASH emulated_nor_flash;

uint32_t media_memory[LX_NOR_SIMULATOR_SECTOR_SIZE];
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */
/**
  * @brief  Application FileX Initialization.
  * @PAram  None
  * @retval int
  */
UINT MX_FileX_Init(void)
{
  UINT ret = FX_SUCCESS;
  /* USER CODE BEGIN MX_FileX_Init */
  CHAR data[] = "This is FileX working on STM32";
  ULONG bytes_read;
  CHAR read_buffer[32];

  /* USER CODE END MX_FileX_Init */

  /* Initialize FileX.  */
  fx_system_initialize();

  /* USER CODE BEGIN MX_FileX_Init 1*/
  /* Format the NOR flash as FAT */
  ret =  fx_media_format(&nor_flash_disk,
                            fx_stm32_levelx_nor_driver,   			// Driver entry
                            (VOID*)LX_NOR_SIMULATOR_DRIVER_ID, 		// Device info pointer
							( UCHAR *)media_memory,
							sizeof(media_memory),
                            "STM32_NOR_DISK",             			// Volume Name
                            1,                            			// Number of FATs
                            32,                           			// Directory Entries
                            0,                            			// Hidden sectors
							LX_NOR_SIMULATOR_FLASH_SIZE/LX_NOR_SIMULATOR_SECTOR_SIZE,      // Total sectors
							LX_NOR_SIMULATOR_SECTOR_SIZE,                          // Sector size
							8,                           			// Sectors per cluster
                            1,                            			// Heads
                            1);                           			// Sectors per track
  /* Check if the format status */
  if (ret != FX_SUCCESS)
  {
    Error_Handler();
  }

  /* Open the NOR driver */
  ret =  fx_media_open(&nor_flash_disk, "STM32_NOR_DISK",
		    fx_stm32_levelx_nor_driver, (VOID*)LX_NOR_SIMULATOR_DRIVER_ID,
			( UCHAR *)media_memory,sizeof(media_memory));
  if (ret != FX_SUCCESS)
  {
    Error_Handler();
  }

  /* Create a file called STM32.TXT in the root directory.  */
  ret =  fx_file_create(&nor_flash_disk, "STM32.TXT");
  if (ret != FX_SUCCESS)
  {
    Error_Handler();
  }

  /* Open the test file.  */
  ret =  fx_file_open(&nor_flash_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_WRITE);
  if (ret != FX_SUCCESS)
  {
    Error_Handler();
  }

  /* Seek to the beginning of the test file.  */
  ret =  fx_file_seek(&fx_file, 0);
  if (ret != FX_SUCCESS)
  {
    Error_Handler();
  }


  /* Write a string to the test file.  */
  ret =  fx_file_write(&fx_file, data, sizeof(data));

   if (ret != FX_SUCCESS)
   {
     Error_Handler();
   }

   /* Close the test file.  */
   ret =  fx_file_close(&fx_file);
   if (ret != FX_SUCCESS)
   {
     Error_Handler();
   }

   ret = fx_media_flush(&nor_flash_disk);
   if (ret != FX_SUCCESS)
   {
     Error_Handler();
   }


  /* Open the test file.  */
  ret =  fx_file_open(&nor_flash_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_READ);

  /* Check the file open status.  */
  if (ret != FX_SUCCESS)
  {
	Error_Handler();
  }

  /* Seek to the beginning of the test file.  */
  ret =  fx_file_seek(&fx_file, 0);
  if (ret != FX_SUCCESS)
  {
	Error_Handler();
  }

  /* Read the first 28 bytes of the test file.  */
  ret =  fx_file_read(&fx_file, read_buffer, sizeof(data), &bytes_read);
  if ((ret != FX_SUCCESS) || (bytes_read != sizeof(data)))
  {
	Error_Handler();
  }

  /* Close the test file.  */
  ret =  fx_file_close(&fx_file);

  /* Check the file close status. */
  if (ret != FX_SUCCESS)
  {
	/* Error closing the file, call error handler. */
	Error_Handler();
  }


   ret =fx_media_cache_invalidate(&nor_flash_disk);
   if (ret != FX_SUCCESS)
   {
     /* Error performing file seek, call error handler.  */
     Error_Handler();
   }


   ret =fx_media_close(&nor_flash_disk);
   if (ret != FX_SUCCESS)
   {
     /* Error performing file seek, call error handler.  */
     Error_Handler();
   }

  /* USER CODE END MX_FileX_Init 1*/

  return ret;
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

 

 

ux_device_msc.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    ux_device_msc.c
  * @author  MCD Application Team
  * @brief   USBX Device applicative file
  ******************************************************************************
   * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "ux_device_msc.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "main.h"
#include "lx_stm32_nor_simulator_driver.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
__attribute__ ((section (".usb_data"))) volatile uint8_t etx_buffer[LX_NOR_SIMULATOR_FLASH_SIZE];
extern LX_NOR_FLASH emulated_nor_flash;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  USBD_STORAGE_Activate
  *         This function is called when insertion of a storage device.
  * @PAram  storage_instance: Pointer to the storage class instance.
  * @retval none
  */
VOID USBD_STORAGE_Activate(VOID *storage_instance)
{
  /* USER CODE BEGIN USBD_STORAGE_Activate */
  UX_PARAMETER_NOT_USED(storage_instance);
  UINT status;
  CHAR name[] = "no name";

  status = _lx_nor_flash_open(&emulated_nor_flash,name,lx_stm32_nor_simulator_initialize);
  if (status != LX_SUCCESS)
  {
	  Error_Handler();
  }


  /* USER CODE END USBD_STORAGE_Activate */

  return;
}

/**
  * @brief  USBD_STORAGE_Deactivate
  *         This function is called when extraction of a storage device.
  * @PAram  storage_instance: Pointer to the storage class instance.
  * @retval none
  */
VOID USBD_STORAGE_Deactivate(VOID *storage_instance)
{
  /* USER CODE BEGIN USBD_STORAGE_Deactivate  */
  UINT status;
  UX_PARAMETER_NOT_USED(storage_instance);
  status = _lx_nor_flash_close(&emulated_nor_flash);
  if (status != LX_SUCCESS)
  {
	  Error_Handler();
  }
  /* USER CODE END USBD_STORAGE_Deactivate */

  return;
}

/**
  * @brief  USBD_STORAGE_Read
  *         This function is invoked to read from media.
  * @PAram  storage_instance : Pointer to the storage class instance.
  * @PAram  lun: Logical unit number is the command is directed to.
  * @PAram  data_pointer: Address of the buffer to be used for reading or writing.
  * @PAram  number_blocks: number of sectors to read/write.
  * @PAram  lba: Logical block address is the sector address to read.
  * @PAram  media_status: should be filled out exactly like the media status
  *                       callback return value.
  * @retval status
  */
UINT USBD_STORAGE_Read(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
                       ULONG number_blocks, ULONG lba, ULONG *media_status)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Read */
  UX_PARAMETER_NOT_USED(storage_instance);
  UX_PARAMETER_NOT_USED(lun);
  //UX_PARAMETER_NOT_USED(data_pointer);
  //UX_PARAMETER_NOT_USED(number_blocks);
  //UX_PARAMETER_NOT_USED(lba);
  UX_PARAMETER_NOT_USED(media_status);

  while(number_blocks > 0){
	  if(_lx_nor_flash_sector_read(&emulated_nor_flash,lba,data_pointer) != LX_SUCCESS){
		  Error_Handler();
	  }
	  lba++;
	  data_pointer = data_pointer + LX_NOR_SIMULATOR_SECTOR_SIZE;
	  number_blocks--;
  }
  status = UX_STATE_NEXT;
  /* USER CODE END USBD_STORAGE_Read */

  return status;
}

/**
  * @brief  USBD_STORAGE_Write
  *         This function is invoked to write in media.
  * @PAram  storage_instance : Pointer to the storage class instance.
  * @PAram  lun: Logical unit number is the command is directed to.
  * @PAram  data_pointer: Address of the buffer to be used for reading or writing.
  * @PAram  number_blocks: number of sectors to read/write.
  * @PAram  lba: Logical block address is the sector address to read.
  * @PAram  media_status: should be filled out exactly like the media status
  *                       callback return value.
  * @retval status
  */
UINT USBD_STORAGE_Write(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
                        ULONG number_blocks, ULONG lba, ULONG *media_status)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Write */
  UX_PARAMETER_NOT_USED(storage_instance);
  UX_PARAMETER_NOT_USED(lun);
  //UX_PARAMETER_NOT_USED(data_pointer);
  //UX_PARAMETER_NOT_USED(number_blocks);
  //UX_PARAMETER_NOT_USED(lba);
  UX_PARAMETER_NOT_USED(media_status);

  while(number_blocks > 0){
 	  if(_lx_nor_flash_sector_write(&emulated_nor_flash,lba,data_pointer) != LX_SUCCESS){
 		 Error_Handler();
 	  }
 	  lba++;
 	  data_pointer = data_pointer + LX_NOR_SIMULATOR_SECTOR_SIZE;
 	  number_blocks--;
   }
  status = UX_STATE_NEXT;
  /* USER CODE END USBD_STORAGE_Write */

  return status;
}

/**
  * @brief  USBD_STORAGE_Flush
  *         This function is invoked to flush media.
  * @PAram  storage_instance : Pointer to the storage class instance.
  * @PAram  lun: Logical unit number is the command is directed to.
  * @PAram  number_blocks: number of sectors to read/write.
  * @PAram  lba: Logical block address is the sector address to read.
  * @PAram  media_status: should be filled out exactly like the media status
  *                       callback return value.
  * @retval status
  */
UINT USBD_STORAGE_Flush(VOID *storage_instance, ULONG lun, ULONG number_blocks,
                        ULONG lba, ULONG *media_status)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Flush */
  UX_PARAMETER_NOT_USED(storage_instance);
  UX_PARAMETER_NOT_USED(lun);
  UX_PARAMETER_NOT_USED(number_blocks);
  UX_PARAMETER_NOT_USED(lba);
  UX_PARAMETER_NOT_USED(media_status);
  /* USER CODE END USBD_STORAGE_Flush */

  return status;
}

/**
  * @brief  USBD_STORAGE_Status
  *         This function is invoked to obtain the status of the device.
  * @PAram  storage_instance : Pointer to the storage class instance.
  * @PAram  lun: Logical unit number is the command is directed to.
  * @PAram  media_id: is not currently used.
  * @PAram  media_status: should be filled out exactly like the media status
  *                       callback return value.
  * @retval status
  */
UINT USBD_STORAGE_Status(VOID *storage_instance, ULONG lun, ULONG media_id,
                         ULONG *media_status)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Status */
  UX_PARAMETER_NOT_USED(storage_instance);
  UX_PARAMETER_NOT_USED(lun);
  UX_PARAMETER_NOT_USED(media_id);
  UX_PARAMETER_NOT_USED(media_status);
  /* USER CODE END USBD_STORAGE_Status */

  return status;
}

/**
  * @brief  USBD_STORAGE_Notification
  *         This function is invoked to obtain the notification of the device.
  * @PAram  storage_instance : Pointer to the storage class instance.
  * @PAram  lun: Logical unit number is the command is directed to.
  * @PAram  media_id: is not currently used.
  * @PAram  notification_class: specifies the class of notification.
  * @PAram  media_notification: response for the notification.
  * @PAram  media_notification_length: length of the response buffer.
  * @retval status
  */
UINT USBD_STORAGE_Notification(VOID *storage_instance, ULONG lun, ULONG media_id,
                               ULONG notification_class, UCHAR **media_notification,
                               ULONG *media_notification_length)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Notification */
  UX_PARAMETER_NOT_USED(storage_instance);
  UX_PARAMETER_NOT_USED(lun);
  UX_PARAMETER_NOT_USED(media_id);
  UX_PARAMETER_NOT_USED(notification_class);
  UX_PARAMETER_NOT_USED(media_notification);
  UX_PARAMETER_NOT_USED(media_notification_length);
  /* USER CODE END USBD_STORAGE_Notification */

  return status;
}

/**
  * @brief  USBD_STORAGE_GetMediaLastLba
  *         Get Media last LBA.
  * @PAram  none
  * @retval last lba
  */
ULONG USBD_STORAGE_GetMediaLastLba(VOID)
{
  ULONG LastLba = 0U;

  /* USER CODE BEGIN USBD_STORAGE_GetMediaLastLba */
  LastLba =  (LX_NOR_SIMULATOR_FLASH_SIZE / LX_NOR_SIMULATOR_SECTOR_SIZE) - 1;
  /* USER CODE END USBD_STORAGE_GetMediaLastLba */

  return LastLba;
}

/**
  * @brief  USBD_STORAGE_GetMediaBlocklength
  *         Get Media block length.
  * @PAram  none.
  * @retval block length.
  */
ULONG USBD_STORAGE_GetMediaBlocklength(VOID)
{
  ULONG MediaBlockLen = 0U;

  /* USER CODE BEGIN USBD_STORAGE_GetMediaBlocklength */
  MediaBlockLen = LX_NOR_SIMULATOR_SECTOR_SIZE;
  /* USER CODE END USBD_STORAGE_GetMediaBlocklength */

  return MediaBlockLen;
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

 

I'm still stuck on the problem, FileX and USBX works well with simulated NOR of 512 or 1024 bits but it doesn't work with 4096 bits.

With 4096 bits:
 - USBX only, windows ask me to format the device and I can create file.
 - FileX only: can format, create file, write and read it

I think problem comes from Cube configuration but I don't know where...

Please let me know if you have an idea.

Regards, 

Dams

 

 

 

 

 

Hello Dams,

 

do you have a mechanism to guarantee that you FX initialization finishes before USBX starts?

 

With best regards,

Dmitry

Dams
Associate III

 

Hello Dmitry, 

 

Thanks for your response.
In MX_FileX_Init() I use "fx_media_close(&nor_flash_disk)​" at the end of the function, before USBX is called.
In USBX I call the "_lx_nor_flash_open(&emulated_nor_flash,name,lx_stm32_nor_simulator_initialize)" when the USB is connected. If the previous session is not closed, the program fail (I test it by connect / disconnect USB cable).

Here the program works only if Sector Size is 512 or 1024..

I take a look to example "Fx_NoR_Write_Read_File" on SMT32U5G9J-DK2 and FileX initialisation seems to be similar.

 

Regards,

Dams, 

 

Hi Dams,

 

the only thing I can suppose now is that there is a problem in supporting large sector sizes with emulator. If emulator works fine with 512 sector size than I think you may try start working with the real flash.

 

With best regards,

Dmitry