cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WB HAL_FLASH writing only once for each register!?!

SKrus.1
Associate

Hello everyone,

in the last few days, I have been looking at a storage method. The goal of the application is to save the individual environment calibration of BSEC algorithm from BME680 in a non-volatile memory of the uC.

My uint8 to uint64_t shifter works very well and reliably. Also, the method to read the flash registers works without limitations.

When writing the data, the same error occurs over and over again. The write operation is only successful if this register has never been written before. Flashing the Chip changed nothing. 

If the register has already been written once, the write command

HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, StartPageAddress, data64[byte] );
 
 
/*
*Function from stm32wbxx_hal_flash.c
*/
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
  HAL_StatusTypeDef status;
 
  /* Check the parameters */
  assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
  assert_param(IS_ADDR_ALIGNED_64BITS(Address));
  assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
 
  /* Process Locked */
  __HAL_LOCK(&pFlash);
 
  /* Reset error code */
  pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
 
  /* Verify that next operation can be proceed */
  status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
 
  if (status == HAL_OK)
  {
    if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
    {
      /* Check the parameters */
      assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
 
      /* Program double-word (64-bit) at a specified address */
      FLASH_Program_DoubleWord(Address, Data);
    }
    else
    {
      /* Check the parameters */
      assert_param(IS_FLASH_FAST_PROGRAM_ADDRESS(Address));
 
      /* Fast program a 64 row double-word (64-bit) at a specified address */
      FLASH_Program_Fast(Address, (uint32_t)Data);
    }
 
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
 
    /* If the program operation is completed, disable the PG or FSTPG Bit */
    CLEAR_BIT(FLASH->CR, TypeProgram);
  }
 
  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);
 
  /* return status */
  return status;
}

returns with HAL_FLASH_GetError() = 0x8 (HAL_ERROR). Inside the command, this is caused by the second wait-function:

FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE)

The surprising thing is that I can change the memory via the memory monitor at will, even after it has already been written once. Currently, I try to write to Flash_Register 0x0802F810 and its following.

The error occurs with different boards and different registers and can be repeated unambiguously. The HAL_FLASHEx_OBGetConfig (standard) can be found in the attached picture.

0693W000006FbxTQAS.pngI have already gone through several fora and tried to put in workarounds, but unfortunately without success. Does anyone know this problem or has an idea of how to solve it?

Thanks for your help!

uint32_t Flash_Write_Data (uint32_t StartPageAddress, uint8_t * data, uint8_t _len)
{
	uint8_t SIZE_REGISTER = 8;
	uint32_t number = 0;
	uint8_t length = 0;
	FLASH_EraseInitTypeDef EraseInitStruct ={0};
 
	/*
	* Calculate how many uint64_t variables needed
	*/
	if (_len % SIZE_REGISTER != 0){
		number = _len/8+1;
	}else{
		number = _len/8;
	}
	/*
	 * Calculate internal iterator to handle arrays with < 8 byte
	 */
	if(_len >= 8){
		length = 8;
 
	}else{
		length = _len;
	}
 
	/* Unlock the Flash to enable the flash control register access */
	HAL_FLASH_Unlock();
 
 
	  /* Fill EraseInit structure*/
 
	  EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
	  EraseInitStruct.Page = StartPageAddress;
	  EraseInitStruct.NbPages     = (_len/FLASH_PAGE_SIZE) +1;
	  uint32_t PAGEError = 0;
 
 
 
	  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
	  /*
	  * Erasing checked and succeeded -> Registers are deleted correctly!!! Error must be caused due writing to each register
	 */
 
	 if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)
	  {
	    	 HAL_FLASH_Lock();
	    	 return HAL_FLASH_GetError ();
	  }
 
	/*
	 * Initialize the Variable to store register value in 8-Byte size
	 */
	uint64_t data64[number];
	HAL_StatusTypeDef status;
 
	for(int byte = 0; byte < number; byte++)
	{
		/*
		 * Prepare the BYTE-value to a uint64_t for DOUBLEWORD  storing
		 */
		data64[byte]  = (uint64_t)(* data);
		data++;
		for(int rep=1; rep < (length); rep++){
			data64[byte] |= ((uint64_t)* data) << (8*rep);
			data++;
 
		}
 
		/*
		 * !!!!!Write DATA to flash here!!!!! -> Failed with 0x8 if register has ever been written before
		 */
		status|=HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, StartPageAddress, data64[byte] );
 
	    StartPageAddress += SIZE_REGISTER;
	}
	 HAL_FLASH_Lock();
 
	 return HAL_FLASH_GetError();
 
}

0 REPLIES 0