Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FX_IO_ERROR - LX_SYSTEM_INVALID_BLOCK #35

Open
erFalcon opened this issue Dec 3, 2023 · 35 comments
Open

FX_IO_ERROR - LX_SYSTEM_INVALID_BLOCK #35

erFalcon opened this issue Dec 3, 2023 · 35 comments

Comments

@erFalcon
Copy link

erFalcon commented Dec 3, 2023

Hello,

I am trying to install FileX + LevelX in an stm32h7 microcontroller using a nor custom driver. I do have in my hardware an AT45DB641 NOR memory.

I am working it as an stand alone and also with fault tolerant enable.

My flash chip does have 4096 blocks of 2048 bytes each. i can write and read on pages of 256 bytes each.

Right now i am being able to format and open the media after doing a full reset of my chip, as i understand, putting everything to 1 (0xFF).

I can run the example that stm32 provide about creating a file etc...

My issue happens the second time i do run the code, but this time without erasing the chip.

I am getting following error from levelx: LX_SYSTEM_INVALID_BLOCK

and from filex: FX_IO_ERROR.

My code is as follows:

nor_custom_driver

#ifndef LX_DIRECT_READ

#ifndef NOR_SECTOR_BUFFER_SIZE
#define NOR_SECTOR_BUFFER_SIZE 512
#endif

static ULONG nor_sector_memory[NOR_SECTOR_BUFFER_SIZE];
#endif

UINT lx_stm32_nor_custom_driver_initialize(LX_NOR_FLASH *nor_flash)
{
UINT ret = LX_SUCCESS;

ULONG total_blocks = 0;
ULONG words_per_block = 0;

/* USER CODE BEGIN Init_Section_0 */
total_blocks = _45DBXX_ACTUALBLOCKS;
words_per_block = _45DBXX_BLOCKBYTES / sizeof(ULONG);

nor_flash->lx_nor_flash_base_address = _45DBXX_STARTADD;

/* USER CODE END Init_Section_0 */

nor_flash->lx_nor_flash_total_blocks = total_blocks;
nor_flash->lx_nor_flash_words_per_block = words_per_block;

/* USER CODE BEGIN Init_Section_1 */

/* USER CODE END Init_Section_1 */

nor_flash->lx_nor_flash_driver_read = lx_nor_driver_read;
nor_flash->lx_nor_flash_driver_write = lx_nor_driver_write;

nor_flash->lx_nor_flash_driver_block_erase = lx_nor_driver_block_erase;
nor_flash->lx_nor_flash_driver_block_erased_verify = lx_nor_driver_block_erased_verify;

#ifndef LX_DIRECT_READ
nor_flash->lx_nor_flash_sector_buffer = nor_sector_memory;
#endif

/* USER CODE BEGIN Init_Section_2 */

/* USER CODE END Init_Section_2 */

return ret;

}

static UINT lx_nor_driver_write(ULONG *flash_address, ULONG *source, ULONG words)
{
UINT ret = LX_SUCCESS;

/* USER CODE BEGIN NOR_DRIVER_WRITE */

uint16_t size = words * sizeof(ULONG);			//	TRANSFORMAMOS LAS WORDS A BYTES
uint8_t writeBuffer[_45DBXX_BLOCKBYTES];
for (int i = 0; i < size; ++i)
{
	writeBuffer[i] = ((uint8_t *)source)[i];
}
uint16_t arrayElement = 0 ;
ULONG *localFlashAddress = flash_address;

while (size > 0)
{
    uint32_t chunk_size = (size > _45DBXX_PAGEBYTES) ? _45DBXX_PAGEBYTES : size; // Determine the size of the next chunk
    AT45dbxx_WritePage2(&writeBuffer[arrayElement], (uint16_t)chunk_size, (uint32_t)localFlashAddress);

    // Update the buffer and address for the next chunk
    arrayElement += (chunk_size);
    localFlashAddress += chunk_size ;
    size -= chunk_size;
}

/* USER CODE END  NOR_DRIVER_WRITE */

return ret;

}

static UINT lx_nor_driver_block_erase(ULONG block, ULONG erase_count)
{

UINT ret = LX_SUCCESS;

/* USER CODE BEGIN NOR_DRIVER_BLOCK  */

uint32_t at45Block = (block * _45DBXX_BLOCKBYTES) + _45DBXX_STARTADD ;
AT45dbxx_EraseBlock(at45Block);


/* USER CODE END  NOR_DRIVER_BLOCK  */

return ret;

}

static UINT lx_nor_driver_block_erased_verify(ULONG block)
{
UINT ret = LX_SUCCESS;

/* USER CODE BEGIN NOR_DRIVER_VERIFY  */

// Buffer to store the read data
uint8_t readBuffer[_45DBXX_PAGEBYTES];

// Calculate the starting address in bytes
ULONG start_address = block * _45DBXX_BLOCKBYTES + _45DBXX_STARTADD;

// Read and verify the block in chunks
for (ULONG offset = 0; offset < _45DBXX_BLOCKBYTES; offset += _45DBXX_PAGEBYTES)
{
    // Calculate the current address within the block
    ULONG current_address = start_address + offset;

    // Read a chunk of data
    AT45dbxx_ReadPage2(readBuffer, _45DBXX_PAGEBYTES, current_address);

    // Verify that all bytes in the chunk are 0xFF
    for (ULONG i = 0; i < _45DBXX_PAGEBYTES; ++i)
    {
        if (readBuffer[i] != 0xFF)
        {
            ret = LX_ERROR; // Block is not fully erased
            break;
        }
    }

    // Break out of the loop if an error is detected
    if (ret != LX_SUCCESS)
    {
        break;
    }
}

/* USER CODE END  NOR_DRIVER_VERIFY  */

return ret;

}


UCHAR media_memory[512];
UCHAR media_buffer[512];
ULONG detected_errors;
UCHAR sratch_memory[4096];

/* Define FileX global data structures. */
FX_MEDIA nor_flash_disk;
FX_FILE fx_file;

ULONG fault_tolerant_memory[3072 / sizeof(ULONG)];

and my filex code is:

UINT MX_FileX_Init(VOID)
{
UINT ret = FX_SUCCESS;
/* USER CODE BEGIN MX_FileX_Init */

/* USER CODE END MX_FileX_Init */

/* Initialize FileX. */
fx_system_initialize();

/* USER CODE BEGIN MX_FileX_Init 1*/

/* USER CODE END MX_FileX_Init 1*/

return ret;
}

void MX_FileX_Process()
{
/* USER CODE BEGIN fx_app_thread_entry 0 */

UINT status;
ULONG available_space_pre;
ULONG available_space_post;
ULONG bytes_read;
CHAR read_buffer[32];
CHAR data[] = "This is FileX working on STM32";

uint8_t err = 0 ;

err = 0x80;

 do{
	err = AT45dbxxx_Dataflash_ReadStatus(&_45DBXX_SPI);
 }while(err == 0x80);	

  AT45dbxx_EraseChip();

status =  fx_media_format(&nor_flash_disk,
						fx_stm32_levelx_nor_driver,   // Driver entry
						(VOID*)CUSTOM_DRIVER_ID, // Device info pointer
						(UCHAR*)media_memory,                 // Media buffer pointer
						sizeof(media_memory),         // Media buffer size
						"NOR_FLASH_DISK",             // Volume Name
						1,                            // Number of FATs
						32,                           // Directory Entries
						0,                            // Hidden sectors
						_45DBXX_ACTUALBLOCKS,      		  // Total sectors
						512,           // Sector size
						1,                            // Sectors per cluster
						1,                            // Heads
						1);                           // Sectors per track

 status =  fx_media_open(&nor_flash_disk, "FX_LX_NOR_DISK", fx_stm32_levelx_nor_driver,(VOID*)CUSTOM_DRIVER_ID , media_buffer, sizeof(media_buffer));

 status = fx_media_check(&nor_flash_disk, sratch_memory, 4096,
		FX_FAT_CHAIN_ERROR |
		FX_DIRECTORY_ERROR |
		FX_LOST_CLUSTER_ERROR, &detected_errors);

  status = fx_fault_tolerant_enable(&nor_flash_disk, fault_tolerant_memory, sizeof(fault_tolerant_memory));

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

  status =  fx_media_space_available(&nor_flash_disk, &available_space_pre);

  /* Check the get available state request status.  */
  if (status != FX_SUCCESS)
  {
    Error_Handler();
  }

  status =  fx_file_create(&nor_flash_disk, "STM32.TXT");

  /* Check the create status.  */
  if (status != FX_SUCCESS)
  {
    /* Check for an already created status. This is expected on the
    second pass of this loop!  */
    if (status != FX_ALREADY_CREATED)
    {
      /* Create error, call error handler.  */
      Error_Handler();
    }
  }
  status =  fx_file_open(&nor_flash_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_WRITE);

  status =  fx_file_seek(&fx_file, 0);

  status =  fx_file_write(&fx_file, data, sizeof(data));

  status =  fx_file_close(&fx_file);

  status = fx_media_flush(&nor_flash_disk);

  status =  fx_file_open(&nor_flash_disk, &fx_file, "STM32.TXT", FX_OPEN_FOR_READ);

  status =  fx_file_seek(&fx_file, 0);

  status =  fx_file_read(&fx_file, read_buffer, sizeof(data), &bytes_read);

  status =  fx_file_close(&fx_file);

  status =  fx_media_space_available(&nor_flash_disk, &available_space_post);

  status =  fx_media_close(&nor_flash_disk);

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

  while(1)
  {

// BSP_LED_Toggle(LED_GREEN);
// tx_thread_sleep(40);
}

}

I really dont understand what is happening, i am even doing a direct read with my memory functions and i am seeing that the text and file name is present in the memory... is this something someone can help me with?

@rahmanih
Copy link

rahmanih commented Dec 4, 2023

Hi @erFalcon,
the LX_SYSTEM_INVALID_BLOCK is thrown due to formatting issue.

Looking at the code above, there are 2 visible issues.

  • the NOR_SECTOR_BUFFER_SIZE should be as large as a physical block i.e 2048 in your case.
  • the Total sectors in the format command should be the logical sectors seen by FileX not the LevelX physical blocks _45DBXX_ACTUALBLOCKS. typically it should be:
    (TOTAL_FLASH_SIZE - PHYSICAL_BLOCK_SIZE)/512

you'll need to keep an empty physical sector for better wearleveling performance.

regards
Haithem.

@erFalcon
Copy link
Author

erFalcon commented Dec 5, 2023

hello @rahmanih thanks a lot for your time and commends,

i have tryed your recomendations but unfortunatelly i am still getting the same two errors, one from LX driver and one from FX driver.

Do you know, or do anyone know if there is a example or if someone has tryed to run this in a SPI interface and not in an QSPI interface?

I have a "similar" "filesystem" running in this hardware, based on the SPIFFS project (i say this in order to "clean" any doubt in my hardware), but this is a system that is "death" and i really need something like FileX and LevelX which is in constant development.

Hope to hear from you soon.

@rahmanih
Copy link

rahmanih commented Dec 14, 2023

@erFalcon
Copy link
Author

@rahmanih
Copy link

Hello @rahmanih, thanks for your commends.

The issue is happening in the:

https://github.com/azure-rtos/levelx/blob/268e4edf9721beb8560a2d740e650bccb14e3270/common/src/lx_nor_flash_open.c#L410

This means that the some blocks are not fully 0xFFFFFFFF, does your nor flash contain any previous data?
if is the case you'll need to erase it before the format operation.

@erFalcon
Copy link
Author

Hello @rahmanih, thanks for your commends.
The issue is happening in the:
https://github.com/azure-rtos/levelx/blob/268e4edf9721beb8560a2d740e650bccb14e3270/common/src/lx_nor_flash_open.c#L410

This means that the some blocks are not fully 0xFFFFFFFF, does your nor flash contain any previous data? if is the case you'll need to erase it before the format operation.

hello @rahmanih,

i do call the AT45dbxx_EraseChip(); function before mounting for the first time, at this moment, the system does run all ok, but when i turn it off, turn it on again and this time i do not call the mentioned function, i get the mentioned error. I understand all have to be 0xFF at the first mount, but it is happening to me at the second mount.

@rahmanih
Copy link

Could you please confirm that the application scenario is as following:

  1. Erase NOR Flash
  2. Format the Nor Flash
  3. Open the NOR flash Fx media
  4. Write Data on the media
  5. Close FX media
  6. turn off
  7. Turn On
  8. go to step 2

@erFalcon
Copy link
Author

Yes, i can confirm that is what i am doing, and thats how it is failling.

@rahmanih
Copy link

rahmanih commented Dec 14, 2023

Could you please confirm that the application scenario is as following:

  1. Erase NOR Flash
  2. Format the Nor Flash
  3. Open the NOR flash Fx media
  4. Write Data on the media
  5. Close FX media
  6. turn off
  7. Turn On
  8. go to step 2

Yes, i can confirm that is what i am doing, and thats how it is failling.

then that's clear, you are formatting the NOR flash in step2 without erasing it thus the error.
I suggest that you try to call the fx_media_open() first, it will fail than you erase the NOR flash and format it.
then after turn off/on the fx_media_open() will succeed since there is valid filesystem already.

@erFalcon
Copy link
Author

i dont understand.

I do this:

Erase NOR Flash
Format the Nor Flash
Open the NOR flash Fx media
Write Data on the media
Close FX media
turn off
Turn On

then i do:

Format the Nor Flash
Open the NOR flash Fx media
Write Data on the media
Close FX media

but in this case it fails at format and i cannot use it anymore.

should i only format the media only once? after erasing it? Then everytime i do turn on the mcu, i only do open the media?

@rahmanih
Copy link

rahmanih commented Dec 14, 2023

should i only format the media only once? after erasing it? Then everytime i do turn on the mcu, i only do open the media?

exactly.

@erFalcon
Copy link
Author

i would give it a shoot and let you know the result. Thanks a lot for your help! Hopefully this was the mistake!

@erFalcon
Copy link
Author

It still not working,

but what i have saw is, after formating it, using it, and after turning off/on but before trying to open the media (without erasing and formating) i am trying to read from the start address of my flash and i do this:

AT45dbxx_ReadPage2(read_data, 256, 0x40000);
AT45dbxx_ReadPage2(read_data, 256, 0x40800);
AT45dbxx_ReadPage2(read_data, 256, 0x41000);
AT45dbxx_ReadPage2(read_data, 256, 0x41800);
AT45dbxx_ReadPage2(read_data, 256, 0x42000);
AT45dbxx_ReadPage2(read_data, 256, 0x42800);
AT45dbxx_ReadPage2(read_data, 256, 0x43000);
AT45dbxx_ReadPage2(read_data, 256, 0x43800);
AT45dbxx_ReadPage2(read_data, 256, 0x44000);
AT45dbxx_ReadPage2(read_data, 256, 0x44800);
AT45dbxx_ReadPage2(read_data, 256, 0x45000);
AT45dbxx_ReadPage2(read_data, 256, 0x45800);
AT45dbxx_ReadPage2(read_data, 256, 0x46000);
AT45dbxx_ReadPage2(read_data, 256, 0x46800);

what i am seeing here is that, i am reading the first 256 bytes (page 1) of each block, and what i see here is, block 1 has data, block 2 has 0, and so on...

May i configuring something wrong for this behaivour? take in count that 0x40000 is my StartAddress (nor_flash->lx_nor_flash_base_address = _45DBXX_STARTADD;)

@rahmanih
Copy link

well you can't know exactely how and where do FileX/LevelX store the data, so having empty blocks is expected.
did check that the erase command is correctly working? i.e all blocks are 0xFFFFFFFF?

@erFalcon
Copy link
Author

i just did that "find" because i have check in which blocks it normally "fail" and is in one of the first 10 blocks, always.

When i call the function: AT45dbxx_EraseChip(); it puts every single byte as 0xFF, same when i call the eraseblock, it put 2048 bytes as 0xFF each starting from the calculed address based on the block given from LevelX.

What i am starting to guess is that if when formating, if it is working in good way. since seems like it is writting "0", because i am very sure that the flash chip have all bytes as 0xFF and then there are bytes that are not.

@SimonTechv
Copy link

I have the same problem. I am using the board: STM32F412ZG Discovery with n25q128 nor flash. I found out that this is due to accessing the wrong address exceeding the size of the NOR memory. Moreover, this only works if lx_nor_flash_total_blocks is used equal to the maximum number of subsectors, in my case it is 4096 blocks with a size of 1024 words per block.

@erFalcon
Copy link
Author

I would try to give this a shoot with your recomendation @SimonTechv . I have had to work my filesystem within other way, but with your recomendation maybe i can make it work now.

Thanks for your thoughs and i would let you know if this works for me, hopefully.

@SimonTechv
Copy link

@erFalcon Yesterday I came to the conclusion that the number of blocks for levelx should be 1 less than their countable number. Suppose there are 1024 blocks of 4096 bytes in memory, then the number of blocks for levelx will be listed as 1023. The documentation doesn't go into too much detail about the configuration options. So far, the throughput for sequential data recording does not exceed 2.5 KB/s for my configuration.

@erFalcon
Copy link
Author

In my case i am going to launch a configuration with 4095 blocks of 2048 bytes each and then i would share the result.

Something that may also make a conflict with any filesystem is, to provide a different "start" address than the actual start 0x00, i have noted that in the SPIFFS, where i was starting not at address 0x00.

I am not worried about "speed" but about stability.

Thanks a lot for your commends, i would let you know my result

@rahmanih
Copy link

rahmanih commented Feb 14, 2024

@erFalcon, @SimonTechv
the number of blocks exposed to FileX, when formatting, should be 1 less than those actually counted by levelx.
https://learn.microsoft.com/en-us/azure/rtos/levelx/chapter5#nor-filex-integration

@SimonTechv
Copy link

@rahmanih This note only applies to FileX integration. If I'm wrong, please explain in more detail.

@erFalcon
Copy link
Author

@erFalcon, @SimonTechv the number of blocks exposed to FileX, when formatting, should be 1 less than those actually counted by levelx. https://learn.microsoft.com/en-us/azure/rtos/levelx/chapter5#nor-filex-integration

Thanks a lot for your clarification in that particular!

@rahmanih This note only applies to FileX integration. If I'm wrong, please explain in more detail.

As i understand, if the SPI Flash chip does have 4096 blocks, and you provide all of them to the LevelX driver, then when providing the LevelX driver to the FileX Formating/Mounting, you have to use 4095, 1 less than the count used in LevelX.

Ofcourse if you are not using FileX, you can avoid this part, but i understand the goal is to integrate all, your chip with LevelX and also with FileX.

@SimonTechv
Copy link

@erFalcon, If I do not use a file system and my memory contains 4096 blocks if we count from 1, then according to my assumption (I analyzed the code a little) I should specify the number 4095 for the number of blocks. When integrating with FileX, this number should decrease to 4094. (This is just my guess, since I could not understand the cause of the error with going beyond the flash address space by 1 block)

@erFalcon
Copy link
Author

What i still not understand is, if i check the STM32 example for an STM32U5G which uses "lx_stm32_nor_custom_driver", in the LevelX implementation, it does define the sector buffer size as 512, and then it creates the nor_sector_memory array with that buffer as number of elements.

Then it does initialize and provides to levelX the blocksize and total blocks, which is 64K for block size and 2048 for total blocks. then block size is converted to words, which is necesary for levelx.

My concern comes in the app_filex (FileX implementation) where FileX does use as sector size 512. And here is where i mix things. Whats the difference in FileX/LevelX between sectors (512 bytes per sector) and blocks(64Kilobytes per block). because this is something until today i still do not understand. As far as i can see, 512 bytes sector size is something like "logical" an the 64Kb per block is something like "phisical" ?. Because at the end, in this example, the total sectors numbers is 262144 but the block count is 2048.

can you @rahmanih provide some guidance on this? Thanks!

@erFalcon
Copy link
Author

Unfortunate i have found same issue as before, i can format and mount the filesystem for the first time, but the second time, i get the IO error when trying to open the media.

@SimonTechv
Copy link

@erFalcon
I also encountered a similar problem, however, when testing for fault tolerance. After a sudden reset while recording, I intermittently get the error LX_INVALID_BLOCK. To make sure the driver was working correctly, I tested it and found no recording errors. Perhaps LevelX has some restrictions that are not indicated in the documentation.

@m1ndbr34ker
Copy link

Hello everyone,

I have previously posted in the wrong (old?) thread so here is a summary of my problem, which sounds similar to what is discussed here. Though I am not using FileX + LevelX in standalone, but with ThreadX.

I can use the media (NOR Flash over SPI) without any problems if I have written files or have it formatted in the same session. But when I restart the microcontroller (STMH5), it can read the file names of previously created files, but fails in reading their properties. The file handle then either has 0 or max value for each variable. This means that I can "open" files, but cannot read them if they have been created before a shutdown.
Similarly, at the beginning the same kind of problem appeared with opening the media, though that kind of disappeared after formatting it 10 or so times.

As this is discussed here a lot, my size settings are:
Flash Blocks: 4096 Bytes (1024 Words)
Flash Size: 256 Blocks = 2MB
FileX Sector Size: 512
FileX Total Sectors: Size/512 = 4096
LevelX Total Blocks: Size/Block Size = 512

Not sure if this is the same problem, but have you checked what your file or media handles look like when/after your opening them?

For clarity: My steps are:
For Media (This works now but failed at the first few starts):

  1. Erasing Chip
  2. Formatting
  3. Opening
  4. Reading/Writing Files
  5. Turn Off
  6. Turn On
  7. Go To 3

And for Files (Still not working properly):

  1. Opening Media
  2. Creating File
  3. Writing File
  4. Close File for Write
  5. Open For Read
  6. Reading File
  7. Turn Off
  8. Turn On
  9. Go to 5

@m1ndbr34ker
Copy link

And by the way, have any of you tried to erase and format the media for like 10-20 times and see if it works properly then? Still not sure if my code is the issue (and it's not a proper solution) but this solved my media issue with 3 different devices already.

@rahmanih
Copy link

Hi @m1ndbr34ker,

after step 4. do you call the fx_media_flush() ?

regards
haithem.

@m1ndbr34ker
Copy link

@rahmanih No I do not. Though I also not have fault tolerance enabled. Are these two not correlated?

@SimonTechv
Copy link

SimonTechv commented Mar 13, 2024

I performed fault tolerance testing on a real device for NOR memory. LevelX does not meet the requirements. The developers do not respond to requests for information about the problem.

@rahmanih
Copy link

@rahmanih No I do not. Though I also not have fault tolerance enabled. Are these two not correlated?

you need to do it, to make filex update the filesystem on the nor flash.

@m1ndbr34ker
Copy link

Thanks for the quick response. I'll update the code right away.

Is that also necessary when a new media is formatted or is that a separate issue?

@rahmanih
Copy link

I performed fault tolerance testing on a real device for NOR memory. LevelX does not meet the requirements. The developers do not respond to requests for information about the problem.

hi @SimonTechv
LevelX doesn't manage fault tolerance it is FileX who does.

@SimonTechv
Copy link

I performed fault tolerance testing on a real device for NOR memory. LevelX does not meet the requirements. The developers do not respond to requests for information about the problem.

hi @SimonTechv
LevelX doesn't manage fault tolerance it is FileX who does.

How should I deal with flash memory translation level errors?

@ALABSTM ALABSTM assigned ZAOUSTM and unassigned ZAOUSTM May 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants