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?