Skip to main content
dwillis
Associate
February 25, 2022
Solved

Flash programming - want to write a few words without erasing an entire page first, STM32G03x

  • February 25, 2022
  • 6 replies
  • 6486 views

I want to program a double word (a calibration value) at the top of internal flash (STM32G03x) without erasing the entire page first.

I understand that only 1's can be set to 0, not vice versa. It may be assumed that the address in question already contains all F's and that once written, it doesn't need to be written again.

I am able to erase a page and write a double word without problems as in the code below, but if I want to write a single value without having erased immediately prior, I get a flash error =8 (Flash SR = Bit 3 PROGERR: Programming error)

The question is - is there any way to unlock the MCU in such a way it's OK to program the single double word ? (the option bits are set to no protection)

{
 HAL_FLASH_Unlock();
 
 // Erase top 2K page (64K device)
 FLASH_EraseInitTypeDef eraseStruct =
 { .TypeErase = FLASH_TYPEERASE_PAGES, .Banks = FLASH_BANK_1, .Page = 31, .NbPages = 1 };
 
 uint32_t error;
 HAL_FLASHEx_Erase(&eraseStruct, &error); ///<< I don't want to do this!
 
 if (error)
 {
 __BKPT(0);
 }
 
 uint32_t address = 0x800FF00;
 uint64_t data = 0; 
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data) != HAL_OK)
 {
 uint32_t err = HAL_FLASH_GetError();
 __BKPT(0);
 }
 
 HAL_FLASH_Lock();
}

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

You can only program a double word at a time, and, due to the ECC, a double word can only be programmed once, even if that one time was all 0xFF's. You cannot knock 1s to 0s at will, you only have one shot.

PROGERR suggests the address was previously programmed after an erase.

6 replies

waclawek.jan
Super User
February 25, 2022

> if I want to write a single value without having erased immediately prior, I get a flash error =8

What do you mean by "single value" here? To what address do you want to write? Is it an address of a doubleword which hasn't been written after erase?

JW

dwillis
dwillisAuthor
Associate
February 25, 2022

Yes, the code above shows a 64 bit word write at 0x800FF00, i.e properly aligned. This code works if the page is erased immediately beforehand. But I want to be able to write it without the Erase() call, because the Erase() call erases the entire page, and I just want to clear some bits from their FF state at a single location (at the minimum granularity possible, 64 bits)..

MM..1
Chief III
February 25, 2022

I mean this work , but not after flash program software load and debug. You need power off and clean start, or clear some flash flags before prog.

dwillis
dwillisAuthor
Associate
February 25, 2022

Yes, I was hoping there might be a flag to set. Following your suggestion I tried setting the FLASH_ACR_PROGEMPTY flag in the ACR, to make it look as though the area is 'new' but that still gives me the PROGERR. Is there anyone who knows what it or they might be ? Or even if it is possible or not?

MM..1
Chief III
February 26, 2022

I dont mean random flag set , you need debug HAL_FLASH_Program and locate line with error return. Here you see for example PGERR flag is set before start prog.

Then you need clear it before call HAL_FLASH_Program.

Tesla DeLorean
Guru
February 25, 2022

Journal writes over sections of memory you have not written post erasure. Align your data with the word width of the flash-lines

The ECC means you can't knock-down '1' bits repeatedly within the same words

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
dwillis
dwillisAuthor
Associate
February 25, 2022

I'm sorry, I don't understand your answer, my data is aligned and my code works provided the page is erased immediately before i try writing it.

TDK
TDKBest answer
February 26, 2022

You can only program a double word at a time, and, due to the ECC, a double word can only be programmed once, even if that one time was all 0xFF's. You cannot knock 1s to 0s at will, you only have one shot.

PROGERR suggests the address was previously programmed after an erase.

"If you feel a post has answered your question, please click ""Accept as Solution""."
dwillis
dwillisAuthor
Associate
February 28, 2022

Thanks, that corresponds to what I am seeing. Back to the drawing board!

waclawek.jan
Super User
February 28, 2022

> With this you say , that incremental EEPROM emulation is here impossible?

What do you mean exactly by "incremental EEPROM emulation"?

The granularity of write is 64-bits, you cannot write less than that. And once you've written those 64 bits, regardless of what value (including all FFs), you cannot write them again without erasing the whole page.

The reason for this is, that by writing 64 bits, in reality 72 bits are written - 64 data bits visible/controlled by user, plus 8 invisible bits which are the error-check bits. For all-FF, the error-check bits are not FFs (I don't know what they actually are, the exact method is not published, but this follows from the fact that reading erased-and-unwritten area in FLASH actually causes ECC errors).

JW

dwillis
dwillisAuthor
Associate
February 28, 2022

Yes, this is correct. Previously, I had been explicitly writing all FFs to my Flash when programming the device. There is a reason for this - the image is CRC protected so I have to be certain what is in the device and hence blank areas are explicitly included in the linker file.

So although it looked 'erased', it in fact wasn't.

Meanwhile, I changed my linker .ld file to not fill unused memory, and tried the following experiment (on the now actually blank device) (unlock omitted for clarity)

The first program operation works (clears a single bit). The second operation (attempts to clear another bit at the same address) fails with PROGERR.

But if I move to another (64 bit) location, then I am able to write. i.,e. as @TDK and yourself state:- an address, once written, cannot be written again without erasing the entire sector.

I hope this clarifies things for anyone trying to emulate an EEPROM (which I'm not - but that's another story)

 uint32_t address = 0x800FF20;
 uint64_t data = 0xFFFFFFFFFFFFFFFE;
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data) != HAL_OK)
 {
 uint32_t err = HAL_FLASH_GetError();
 __BKPT(0);
 } //// WORKS!!
 
 data = 0xFFFFFFFFFFFFFFFC;
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data) != HAL_OK)
 {
 uint32_t err = HAL_FLASH_GetError();
 __BKPT(0);
 } /// FAILS!!!