Skip to main content
Visitor II
May 6, 2024
Solved

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

  • May 6, 2024
  • 3 replies
  • 1895 views

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

    This topic has been closed for replies.
    Best answer by Mathan Raja

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

     

    3 replies

    Technical Moderator
    June 19, 2024

    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.

    Graduate II
    June 19, 2024

    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.

    Mathan RajaAuthorAnswer
    Visitor II
    June 20, 2024

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