2025-10-07 3:45 AM
Hello,
I am trying to set up an external flash memory (MX25V1635F) on a Nucleo-U575ZI-Q.
I have successfully used the low-level drivers (LLD) from the manufacturer Macronix and integrated them into the Levelx functions:
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 = 32;
words_per_block = 16384;
nor_flash->lx_nor_flash_base_address = 0;
/* 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_read(ULONG *flash_address, ULONG *destination, ULONG words)
{
UINT ret = LX_SUCCESS;
/* USER CODE BEGIN NOR_READ */
uint32 byte_addr = (uint32)(*flash_address);
uint32 byte_len = words * sizeof(ULONG);
if (CMD_READ(byte_addr, (uint8*)destination, byte_len) != FlashOperationSuccess){
ret = LX_ERROR;
}
/* USER CODE END NOR_READ */
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 */
uint32 byte_addr = (uint32)(*flash_address);
uint32 byte_len = words * sizeof(ULONG);
// Programmer page par page (Max 256 bytes)
uint32 offset = 0;
uint32 chunk;
while (offset < byte_len)
{
if ((byte_len - offset) > 256)
{
chunk = 256;
}
else
{
chunk = byte_len - offset;
}
if (CMD_PP(byte_addr + offset, ((uint8*)source) + offset, chunk) != FlashOperationSuccess)
{
ret = LX_ERROR;
break;
}
offset += chunk;
}
/* USER CODE END NOR_DRIVER_WRITE */
return ret;
}
static UINT lx_nor_driver_block_erased_verify(ULONG block)
{
UINT ret = LX_SUCCESS;
/* USER CODE BEGIN NOR_DRIVER_VERIFY */
uint32 byte_addr = block * NOR_SECTOR_SIZE;
uint8 buffer[256];
for (int offset = 0; offset < NOR_SECTOR_SIZE; offset += 256)
{
if (CMD_READ(byte_addr + offset, buffer, 256) != FlashOperationSuccess)
return LX_ERROR;
for (int i = 0; i < 256; i++)
{
if (buffer[i] != 0xFF)
return LX_ERROR;
}
}
/* USER CODE END NOR_DRIVER_VERIFY */
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 byte_addr = block * NOR_SECTOR_SIZE;
for (ULONG i = 0; i < erase_count; i++)
{
if (CMD_SE(byte_addr) != FlashOperationSuccess)
{
ret = LX_ERROR;
break;
}
byte_addr += NOR_SECTOR_SIZE;
}
/* USER CODE END NOR_DRIVER_BLOCK */
return ret;
}
I can read the values I wrote to my flash in debug mode using these functions.
Here are my settings in the ioc :
When I try to format my flash memory:
lx_stm32_nor_custom_driver_initialize(&nor_flash);
MX_FileX_Init();
/* Format the NOR flash as FAT */
status = fx_media_format(&nor_flash_disk,
fx_stm32_levelx_nor_driver, // Driver entry
(VOID*)NOR_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
TOTAL_SECTOR_LOGICAL, // Total sectors
SECTOR_SIZE_LOGICAL, // Sector size
8, // Sectors per cluster
1, // Heads
1); // Sectors per track
/* Check if the format status */
if (status != FX_SUCCESS)
{
Error_Handler();
}
/* Open the SPI NOR Flash disk driver. */
status = fx_media_open(&nor_flash_disk, "FX_LX_NOR_DISK", fx_stm32_levelx_nor_driver,(VOID*)NOR_CUSTOM_DRIVER_ID , media_memory, sizeof(media_memory));
/* Check the media open status. */
if (status != FX_SUCCESS)
{
Error_Handler();
}
The code encounters an error on line 677 of the lx_nor_flash_open.c file:
/* Determine if the sector is free. */
else if (block_word == LX_NOR_PHYSICAL_SECTOR_FREE)
{
/* A free entry when there are still used sectors implies that the sector was allocated and a power interruption
took place prior to writing the new logical sector number into the list. */
/* Is this the first time? */
if (nor_flash -> lx_nor_flash_diagnostic_mapping_invalidated)
{
/* No, this is a potential format error, since this should only happen once in a given
NOR flash format. */
_lx_nor_flash_system_error(nor_flash, LX_SYSTEM_INVALID_FORMAT);
/* Return an error. */
return(LX_ERROR);
}
Do you have any recommendations?
2025-10-07 4:02 AM
i just changed :
uint32 byte_addr = (uint32)(*flash_address);
by :
uint32 byte_addr = (uint32)(flash_address);
in my read and write functions.
and i think it's working.
Do you think it was my issue ?
2025-10-07 5:46 AM
Hello @RemiNao ,
Certainly, this is indeed the cause of the problem. However, you can confirm it by carefully checking the prototype of the CMD_READ function.
It is essential that the first parameter of this function is of type uint32. Verifying this ensures that the data type you are passing matches what is expected, specifically avoiding passing a pointer where an integer value is required.
Regards,
Maher