cancel
Showing results for 
Search instead for 
Did you mean: 

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

dwillis
Associate II

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

12 REPLIES 12

@TDK​ With this you say , that incremental EEPROM emulation is here impossible?

Or you only declare that after erase and write FFFF... impossible next write , what is true?

@dwillis​ Why you dont use incremental writing with last valid? One disadvantage here is slow down code for search last writed value, but it works without erase to page full.

> 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

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!!!