cancel
Showing results for 
Search instead for 
Did you mean: 

Why must I erase before programming an unused flash page?

carleslsregner
Visitor

Hello I am forced to erase the entire flash page when I write into an address of the flash page. Why is that? I have never used this page... 

I understand that if the flash has been already used, it cannot be rewritten... but why when the page is always '1'?

Thanks a lot. 

4 REPLIES 4
carleslsregner
Visitor
	for(uint32_t i = flash_start_i_log; i < flash_start_i_log+0x800; i+= 8 )
	{
		if (flash_read_data(i) != 0xFFFFFFFF)
		{
			debug2 = 1;
		}
	}

I check the entire page. Nothing has been written on the page. I have to erase ¿nothing? at the very begining... why is that?  

carleslsregner
Visitor
/**
 * @brief The function's role is to save the log data into the log page/s.
 */
mid_error_t flash_save_loop_2(const uint8_t * data_in, bool urgent)
{

	if(HAL_FLASH_Unlock() != HAL_OK)
	{
		return MID_ERROR_GENERAL;
	}

	HAL_Delay(100);
	static uint8_t debug2 = 0;

	for(uint32_t i = flash_start_i_log; i < flash_start_i_log+0x800; i+= 8 )
	{
		if (flash_read_data(i) != 0xFFFFFFFF)
		{
			debug2 = 1;
		}
	}

	if(debug2)
	{
		flash_erase_page_by_address(flash_start_i_log);
	}

	/**
	 * first we check if the next position to write is valid.
	 * If it is not valid, we need to erase the page and start from the beginning.
	 */
	if (flash_next_i_log > 	flash_end_i_log)
	{
		flash_next_i_log = flash_start_i_log;
	}

	if (flash_read_data(flash_next_i_log) != 0xFFFFFFFF)
	{
		flash_erase_page_by_address(flash_next_i_log);
	}

	//flash_erase_page_by_address(flash_next_i_log);


	/**
	 * now we write the data.
	 */
	for (uint8_t f_i = 0; f_i < size_of_log_struct_in_flash; f_i += 8)
	{
		uint8_t auxdata[8] =
		{ 0 };
		if(urgent)
		{
			memcpy(auxdata, &data_in[f_i],
					(size_of_log_struct_in_flash - f_i) >= 8 ?
							8 : (size_of_log_struct_in_flash - f_i));
			if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
					flash_next_i_log + f_i,
					(uint64_t) auxdata[0] | ((uint64_t) auxdata[1] << 8)
							| ((uint64_t) auxdata[2] << 16)
							| ((uint64_t) auxdata[3] << 24)
							| ((uint64_t) auxdata[4] << 32)
							| ((uint64_t) auxdata[5] << 40)
							| ((uint64_t) auxdata[6] << 48)
							| ((uint64_t) auxdata[7] << 56)) != HAL_OK)
			{
				flash_erase_page_by_address(flash_next_i_log);
				return MID_ERROR_GENERAL ;
			}

		}
		else
		{
			uint64_t aux_data = 	((uint64_t) auxdata[0])
									| (((uint64_t) auxdata[1] << 8))
									| (((uint64_t) auxdata[2] << 16))
									| (((uint64_t) auxdata[3] << 24))
									| (((uint64_t) auxdata[4] << 32))
									| (((uint64_t) auxdata[5] << 40))
									| (((uint64_t) auxdata[6] << 48))
									| (((uint64_t) auxdata[7] << 56));
			if (HAL_FLASH_Program((uint32_t)FLASH_TYPEPROGRAM_DOUBLEWORD,
					(uint32_t)flash_next_i_log + (uint32_t)f_i,
					aux_data
			) != HAL_OK)
			{
				debug += 10;
				flash_erase_page_by_address(flash_next_i_log);
				return MID_ERROR_GENERAL;
			}
		}
	}

	HAL_Delay(10);

	if(HAL_FLASH_Lock() != HAL_OK)
	{
		return MID_ERROR_GENERAL;
	}

    flash_next_i_log += size_of_log_struct_in_flash;

	if (flash_next_i_log > 	flash_end_i_log)
	{
		flash_next_i_log = flash_start_i_log;
	}
	return MID_ERROR_OK; // everything went ok
}

This is just a loop that keeps storing the log data. 

Danish1
Lead III

Many stm32 FLASH memories come with error-correction-coding (ECC) bits as well as the data bits you can program from 1 to 0. The Reference Manual for stm32g0x0 says that FLASH is organised as 64 data bits and 8 ECC bits. The advantage is that ST don't need to scrap a device simply because a single bit somewhere in the FLASH can't be programmed.

When erased, the data bits and ECC bits are all 1. This is a special case and there is special logic that recognises this pattern.

As soon as you write a 0 to any of the bits in a 64-bit line, the correct pattern is written to ECC so that if any one bit in the 72 of data+ECC is wrong, *that* bit is corrected on each and every read. If you wanted to zero other bits in that line, it would need a different ECC pattern, most likely requiring some 0 bits to be changed to 1; you can't do that without erasing the entire 2kbyte page.

Also I think if you write all 1s to your data bits, a different pattern is written to the ECC because the ECC decoding is more efficient this way. It is up to you to not write where you want things to remain 1.


@Danish1 wrote:

 

Also I think if you write all 1s to your data bits, a different pattern is written to the ECC because the ECC decoding is more efficient this way. It is up to you to not write where you want things to remain 1.


Never. I am not crazy. I know erase is not the same as writing '1'. Thanks :)