cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_FLASH_Program trigger error 0x40 (FLASH_FLAG_SIZERR)

sde c.1
Senior II

STM32G473CCT uses the HAL library for writing flash pages.

i have constructed some code to use the last FLASH page as NV memory.

bool eeprom_write8(uint16_t address, uint8_t data)
{
	return eeprom_write(address, &data, 1);
}
 
bool eeprom_write(uint16_t address, uint8_t *pdata, uint16_t size)
{
	static uint8_t ARRAY_ALLIGN(PageData,FLASH_PG_SIZE);
 
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_SIZERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PROGERR);
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_FASTERR);
	flash_status status = FLASH_OK;
 
	if((address+size) > EEPROM_SIZE){
		return false;
	}
 
	if(eeprom_page_data_changed(address,pdata,size)){
		// data changed ->
		// store page content in ram and do a page clear
		eeprom_storepage_and_erase(PageData);
		// update the data with the new data
		for(uint16_t n=0;n<size;n++){
			PageData[address+n]=*pdata;
			pdata++;
		}
		// write the updated page to the flash
		status = flash_page_write(FLASH_EEPROM_BASEADDR,(uint64_t*)PageData);
		if(status == FLASH_OK)	return true;
	}
 
	return false;
}
 
flash_status flash_page_write(uint32_t address, uint64_t *data) {
 
	HAL_StatusTypeDef ret;
	uint32_t flasherror;
 
	HAL_FLASH_Unlock();
	__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
 
	for(uint16_t n=0;n<(FLASH_PG_SIZE/8);n++){
		ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *data);
		if (ret != HAL_OK) {
			flasherror = HAL_FLASH_GetError();
			break;
		}
		data++;
		address+=8;
	}
	HAL_FLASH_Lock();
	if (ret != HAL_OK)	return FLASH_ERROR_WRITE;
	return FLASH_OK;
}

basically i do this

i use PageData as variable in RAM with size 4096 (1 page)

For each time that i want to write data to a flash location (this is occasionally) i do this :

a) PageData is updated with the information read from the last page and then the page is wiped in function eeprom_storepage_and_erase()

b) new data is updated in PageData at the correct index.

c) I write the full PageData variable into the last page with flash_page_write(FLASH_EEPROM_BASEADDR,(uint64_t*)PageData);

d) flash_page_write function overwrites the full page withh the hal function HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *data);

This seems to fail somewhere randomly in the for loop of flash_page_write() ) .

When it fails the HAL function fails and HAL_FLASH_GetError() returns 0x40 which is size error ?

How can this happen when data and address is still well within the boundary?

During debugging i found these locations when entering flash_page_write

PageData (0x20003660)

address (0x803f000)

 0693W00000WHbqWQAT.png0693W00000WHbt0QAD.png0693W00000WHbsHQAT.png0693W00000WHbs2QAD.png 

1 ACCEPTED SOLUTION

Accepted Solutions
sde c.1
Senior II

I found a solution, by disabling and enabling interrupt before page write.

Does anyone have any idea how an interrupt can cause size error and mess up the flash page writing?

This is what's changed :

__disable_irq();
	HAL_FLASH_Unlock();
 
	for(uint16_t n=0;n<(FLASH_PG_SIZE/8);n++){
		__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
		ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *data);
		if (ret != HAL_OK) {
			flasherror = HAL_FLASH_GetError();
			break;
		}
		data++;
		address+=8;
	}
	HAL_FLASH_Lock();
	__enable_irq();

View solution in original post

1 REPLY 1
sde c.1
Senior II

I found a solution, by disabling and enabling interrupt before page write.

Does anyone have any idea how an interrupt can cause size error and mess up the flash page writing?

This is what's changed :

__disable_irq();
	HAL_FLASH_Unlock();
 
	for(uint16_t n=0;n<(FLASH_PG_SIZE/8);n++){
		__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
		ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *data);
		if (ret != HAL_OK) {
			flasherror = HAL_FLASH_GetError();
			break;
		}
		data++;
		address+=8;
	}
	HAL_FLASH_Lock();
	__enable_irq();