2024-05-06 07:28 AM - last edited on 2024-05-07 09:47 AM by SofLit
Hi,
I am using the STM32H573I-DK eval board.
I can able to write and read the data in flash memory (sector 127). But after resetting or power cycle it does not retain the data. that sector fills with 0xFFFFFFFF only.
how do fix this issue?
Here is my code,
#define FLASH_STORAGE_1 0x081FE000
bool answer = true;
uint32_t PageError;
FLASH_EraseInitTypeDef flashErase;
HAL_FLASH_Unlock();
flashErase.TypeErase = FLASH_TYPEERASE_SECTORS;
flashErase.Sector = FLASH_SECTOR_127;
flashErase.NbSectors = 1;
flashErase.Banks = FLASH_BANK_2;
volatile HAL_StatusTypeDef status;
status = HAL_FLASHEx_Erase(&flashErase, &PageError);
if(status == HAL_OK){
for (uint32_t i = 0; i < size; i += 16)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWOD, FLASH_STORAGE_1 + i, (uint32_t)data) != HAL_OK)
{
answer = false;
break;
}
data += 16;
}}
HAL_FLASH_Lock();
Thanks
Mathan
Solved! Go to Solution.
2024-06-19 11:43 PM
Hi,
This is my code now. It is working fine. this can retain the stored value after reset and power cycle.
thanks
Mathan
static FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t FirstSector , NbOfSectors , BankNumber ,EndSector ;
uint32_t Address , SectorError, temp_value ;
uint32_t DRV_Get_Sector(uint32_t Address);
uint32_t DRV_Get_Bank(uint32_t Addr);
/******************************************************************************
* FUNCTION NAME: DRV_Write_Flash
*
* DESCRIPTION:
* write the data in particular internal flash memory location
*
* PARAMETERS: uint32_t address
* uint8_t *data
*
* RETURN VALUE: ErrorStatus SUCCESS
*
* NOTES:
*
*
******************************************************************************/
void DRV_Write_Flash(uint32_t address , uint8_t *data)
{
volatile uint32_t data_to_FLASH[(strlen((char*)data)/4) + (int)((strlen((char*)data) % 4) != 0)];
memset((uint8_t*)data_to_FLASH, 0, strlen((char*)data_to_FLASH));
strcpy((char*)data_to_FLASH, (char*)data);
volatile uint32_t data_length = (strlen((char*)data) / 4)
+ (int)((strlen((char*)data) % 4) != 0);
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Erase the user Flash area
Get the 1st sector to erase */
FirstSector = DRV_Get_Sector(address);
/* Get the number of sector to erase from 1st sector*/
NbOfSectors = DRV_Get_Sector(address) - FirstSector + 1;
/* Get the bank */
BankNumber = DRV_Get_Bank(address);
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Banks = BankNumber;
EraseInitStruct.Sector = FirstSector;
EraseInitStruct.NbSectors = NbOfSectors;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
{
/*
Error occurred while sector erase.
User can add here some code to deal with this error.
SectorError will contain the faulty sector and then to know the code error on this sector,
user can call function 'HAL_FLASH_GetError()'
*/
/* Infinite loop */
while (1)
{
Error_Handler();
}
}
/* Program the user Flash area word by word*/
volatile uint32_t index=0;
while (index < data_length)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uint32_t)data) == HAL_OK)
{
address = address + 16; /* increment to next quad word*/
index++;
}
else
{
/* Error occurred while writing data in Flash memory.
User can add here some code to deal with this error */
while (1)
{
Error_Handler();
}
}
}
HAL_FLASH_Lock();
}
void DRV_Read_Flash(uint32_t address , uint8_t* data)
{
*data = *(__IO uint32_t*)address;
}
/**
* @brief Gets the sector of a given address
* @PAram Addr: Address of the FLASH Memory
* @retval The sector of a given address
*/
uint32_t DRV_Get_Sector(uint32_t Address)
{
uint32_t sector = 0;
if((Address >= FLASH_BASE) && (Address < FLASH_BASE + FLASH_BANK_SIZE))
{
sector = (Address & ~FLASH_BASE) / FLASH_SECTOR_SIZE;
}
else if ((Address >= FLASH_BASE + FLASH_BANK_SIZE) && (Address < FLASH_BASE + FLASH_SIZE))
{
sector = ((Address & ~FLASH_BASE) - FLASH_BANK_SIZE) / FLASH_SECTOR_SIZE;
}
else
{
sector = 0xFFFFFFFF; /* Address out of range */
}
return sector;
}
/**
* @brief Gets the bank of a given address
* @PAram Addr: Address of the FLASH Memory
* @retval The bank of a given address
*/
uint32_t DRV_Get_Bank(uint32_t Addr)
{
uint32_t bank = 0;
if (READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_SWAP_BANK) == 0)
{
/* No Bank swap */
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
{
bank = FLASH_BANK_1;
}
else
{
bank = FLASH_BANK_2;
}
}
else
{
/* Bank swap */
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
{
bank = FLASH_BANK_2;
}
else
{
bank = FLASH_BANK_1;
}
}
return bank;
}
2024-06-19 08:54 AM - edited 2024-06-19 08:55 AM
Hello @Mathan Raja
This is due to a power loss during a Flash memory operation. If a reset or power down occurs while a Flash operation is in progress, such as programming or erasing, the contents of the Flash memory being accessed may become corrupted. This is because the Flash programming is interrupted, leading to potential corruption of the erased or programmed memory page.
2024-06-19 09:45 AM
How does this compile?
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWOD, FLASH_STORAGE_1 + i, (uint32_t)data) != HAL_OK)
Should get a syntax error.
What's the "data" structure look like here?
Strikes me that it in fact gets an error and exits early
Not sure what's supposed to get written and what actually does.
Instrument the code so you know if it succeeded, irrespective of subsequent actions.
Check the content before you reset. Don't reset until all write buffers have cleared.
Printing content to the console can provide validation.
2024-06-19 11:43 PM
Hi,
This is my code now. It is working fine. this can retain the stored value after reset and power cycle.
thanks
Mathan
static FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t FirstSector , NbOfSectors , BankNumber ,EndSector ;
uint32_t Address , SectorError, temp_value ;
uint32_t DRV_Get_Sector(uint32_t Address);
uint32_t DRV_Get_Bank(uint32_t Addr);
/******************************************************************************
* FUNCTION NAME: DRV_Write_Flash
*
* DESCRIPTION:
* write the data in particular internal flash memory location
*
* PARAMETERS: uint32_t address
* uint8_t *data
*
* RETURN VALUE: ErrorStatus SUCCESS
*
* NOTES:
*
*
******************************************************************************/
void DRV_Write_Flash(uint32_t address , uint8_t *data)
{
volatile uint32_t data_to_FLASH[(strlen((char*)data)/4) + (int)((strlen((char*)data) % 4) != 0)];
memset((uint8_t*)data_to_FLASH, 0, strlen((char*)data_to_FLASH));
strcpy((char*)data_to_FLASH, (char*)data);
volatile uint32_t data_length = (strlen((char*)data) / 4)
+ (int)((strlen((char*)data) % 4) != 0);
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Erase the user Flash area
Get the 1st sector to erase */
FirstSector = DRV_Get_Sector(address);
/* Get the number of sector to erase from 1st sector*/
NbOfSectors = DRV_Get_Sector(address) - FirstSector + 1;
/* Get the bank */
BankNumber = DRV_Get_Bank(address);
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Banks = BankNumber;
EraseInitStruct.Sector = FirstSector;
EraseInitStruct.NbSectors = NbOfSectors;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
{
/*
Error occurred while sector erase.
User can add here some code to deal with this error.
SectorError will contain the faulty sector and then to know the code error on this sector,
user can call function 'HAL_FLASH_GetError()'
*/
/* Infinite loop */
while (1)
{
Error_Handler();
}
}
/* Program the user Flash area word by word*/
volatile uint32_t index=0;
while (index < data_length)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, address, (uint32_t)data) == HAL_OK)
{
address = address + 16; /* increment to next quad word*/
index++;
}
else
{
/* Error occurred while writing data in Flash memory.
User can add here some code to deal with this error */
while (1)
{
Error_Handler();
}
}
}
HAL_FLASH_Lock();
}
void DRV_Read_Flash(uint32_t address , uint8_t* data)
{
*data = *(__IO uint32_t*)address;
}
/**
* @brief Gets the sector of a given address
* @PAram Addr: Address of the FLASH Memory
* @retval The sector of a given address
*/
uint32_t DRV_Get_Sector(uint32_t Address)
{
uint32_t sector = 0;
if((Address >= FLASH_BASE) && (Address < FLASH_BASE + FLASH_BANK_SIZE))
{
sector = (Address & ~FLASH_BASE) / FLASH_SECTOR_SIZE;
}
else if ((Address >= FLASH_BASE + FLASH_BANK_SIZE) && (Address < FLASH_BASE + FLASH_SIZE))
{
sector = ((Address & ~FLASH_BASE) - FLASH_BANK_SIZE) / FLASH_SECTOR_SIZE;
}
else
{
sector = 0xFFFFFFFF; /* Address out of range */
}
return sector;
}
/**
* @brief Gets the bank of a given address
* @PAram Addr: Address of the FLASH Memory
* @retval The bank of a given address
*/
uint32_t DRV_Get_Bank(uint32_t Addr)
{
uint32_t bank = 0;
if (READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_SWAP_BANK) == 0)
{
/* No Bank swap */
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
{
bank = FLASH_BANK_1;
}
else
{
bank = FLASH_BANK_2;
}
}
else
{
/* Bank swap */
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
{
bank = FLASH_BANK_2;
}
else
{
bank = FLASH_BANK_1;
}
}
return bank;
}