Skip to main content
AD�?b
Senior
February 10, 2021
Solved

STM32F746G-DISCO, FLASH

  • February 10, 2021
  • 19 replies
  • 4850 views

Why does flasch memory lose saved data after being read and written after power off?

Andrzej

This topic has been closed for replies.
Best answer by KnarfB

> Do you erase it? No

Programming can only flip 1 bits to 0 bits. Erase is needed for the other way round. Why do you expect it to work without erase?

19 replies

KnarfB
Super User
February 10, 2021

Sorry leader, but this is too little information. I'm using 20+ of those boards for years and they never did that to me.

AD�?b
AD�?bAuthor
Senior
February 11, 2021

Hi

I want:

1.Read the value from FLASH after power on

2. After aborting, save the current value in FLASH

I am doing:

1. my variable is uint32_t total_time; // save to FLASH in 87

2. I read total_time = * (__ IO uint32_t *) FLASH_SECTOR_4; // reading from FLASH at 180

3.unlock FLASH HAL_FLASH_Unlock (); // FLASH unlock for writing in 181

4. in the interrupt I write the variable

void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin) // interrupt for writing to FLASH

{ if (GPIO_Pin == STOP_Pin)

HAL_FLASH_Program (FLASH_TYPEPROGRAM_WORD, FLASH_SECTOR_3, total_time); // saving to FALSH

} in 1005

Almost every time I read a different recorded value after turning on the power.

Andrzej

I include main.c

KnarfB
Super User
February 11, 2021

FLASH_SECTOR_4 != FLASH_SECTOR_3 ?

AD�?b
AD�?bAuthor
Senior
February 11, 2021

I changed:

total_time = * (__ IO uint32_t *) FLASH_SECTOR_3; // reading from FLASH It still does not work

Tesla DeLorean
Guru
February 11, 2021

Do you erase it? Do you look at the error codes?

How about you write incrementally, deeper into the sector, so you don't have to erase at every cycle ?

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
KnarfB
Super User
February 12, 2021

Keep in mind that flash wears out easily. Max. number of guaranteed cycles (10k) is in the data sheets. There is a EEPROM emulation library, see AN4894 "EEPROM emulation techniques and software for STM32 microcontrollers" and X-CUBE-EEPROM library doing some wear-leveling and other house keeping with a more user oriented API.

AD�?b
AD�?bAuthor
Senior
February 12, 2021

I will only write one uint32_t during power off. It is enough for 10 years.

Tesla DeLorean
Guru
February 13, 2021

Something along the lines of this should work

/* Uncomment the following define to select the FLASH Dual Bank mode,
 or keep it commented to select the FLASH Single Bank mode */
 
#define DUAL_BANK
 
/* Base address of the Flash sectors */
#if defined(DUAL_BANK)
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base address of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base address of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base address of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base address of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base address of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base address of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base address of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base address of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base address of Sector 11, 128 Kbytes */
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base address of Sector 12, 16 Kbytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base address of Sector 13, 16 Kbytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base address of Sector 14, 16 Kbytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base address of Sector 15, 16 Kbytes */
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base address of Sector 16, 64 Kbytes */
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base address of Sector 17, 128 Kbytes */
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base address of Sector 18, 128 Kbytes */
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base address of Sector 19, 128 Kbytes */
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base address of Sector 20, 128 Kbytes */
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base address of Sector 21, 128 Kbytes */
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base address of Sector 22, 128 Kbytes */
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base address of Sector 23, 128 Kbytes */
#else
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 32 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08008000) /* Base address of Sector 1, 32 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08010000) /* Base address of Sector 2, 32 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x08018000) /* Base address of Sector 3, 32 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08020000) /* Base address of Sector 4, 128 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08040000) /* Base address of Sector 5, 256 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08080000) /* Base address of Sector 6, 256 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x080C0000) /* Base address of Sector 7, 256 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08100000) /* Base address of Sector 8, 256 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x08140000) /* Base address of Sector 9, 256 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x08180000) /* Base address of Sector 10, 256 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x081C0000) /* Base address of Sector 11, 256 Kbytes */
#endif /* DUAL_BANK */
 
uint32_t ReadValue(void)
{
 return(*(uint32_t *)ADDR_FLASH_SECTOR_3);
}
 
void WriteValue(uint32_t Value)
{
 FLASH_EraseInitTypeDef EraseInitStruct = {0};
 uint32_t SECTORError = 0;
 
 if (ReadValue() == Value) return; // Already at current value
 
 /* Unlock the Flash to enable the flash control register access *************/
 HAL_FLASH_Unlock();
 
 /* Fill EraseInit structure*/
 EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
 EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
 EraseInitStruct.Sector = FLASH_SECTOR_3;
 EraseInitStruct.NbSectors = 1;
 
 /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
 you have to make sure that these data are rewritten before they are accessed during code
 execution. If this cannot be done safely, it is recommended to flush the caches by setting the
 DCRST and ICRST bits in the FLASH_CR register. */
 if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
 {
 ErrorHandler();
 }
 
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, ADDR_FLASH_SECTOR_3, Value) != HAL_OK)
 {
 ErrorHandler();
 }
 
 /* Lock the Flash to disable the flash control register access (recommended
 to protect the FLASH memory against possible unwanted operation) *********/
 HAL_FLASH_Lock();
} // sourcer32@gmail.com

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
AD�?b
AD�?bAuthor
Senior
February 14, 2021

What is the difference between working with one bank or two banks.

I have uint32_t to write. Does it have any purpose?

Tesla DeLorean
Guru
February 14, 2021

It affects the addressing, the banks can be placed end-to-end or side-to-side, the latter being wider, improving the fetching/caching efficiency.

Try the Reference Manual for insight into the flash geometry and functionality.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..