2022-11-07 05:37 AM
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)
Solved! Go to Solution.
2022-11-08 12:40 AM
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();
2022-11-08 12:40 AM
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();