cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H573 Flash Memory did not retain the data after reset and power cycle

Mathan Raja
Associate III

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,

 

 

MathanRaja_0-1714994451040.png
#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

1 ACCEPTED SOLUTION

Accepted Solutions
Mathan Raja
Associate III

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;
}

 

View solution in original post

3 REPLIES 3
Saket_Om
ST Employee

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.

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Mathan Raja
Associate III

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;
}