How to correctly write 4 byte (Float) value to STM32F405 Flash memory
Hey. I would like some clarification regarding writing to Flash memory. Specificially, 4 bytes (float values).
I have the following code:
void FLASH_write_single_float(uint32_t address, float data_to_send) {
if (address < 0x080E0000 || address > 0x080FFFFF) {
printf("Out of sector 11 bounds\n");
return;
}
HAL_FLASH_Unlock();
FLASH_WaitForLastOperation(1000);
// Writing float as 32-bit word (4 bytes)
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *(uint32_t*)&data_to_send) == HAL_OK) {
printf("FLASH_WRITE_OK\n");
} else {
printf("FLASH_WRITE_FAIL\n");
}
FLASH_WaitForLastOperation(2000);
HAL_FLASH_Lock();
}
float FLASH_read_single_float(uint32_t address) {
taskENTER_CRITICAL();
float data_to_read = *((float*) address);
taskEXIT_CRITICAL();
return data_to_read;
}
void FLASH_erase_all() {
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t page_err;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Sector = FLASH_SECTOR_11;
EraseInitStruct.NbSectors = 1;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
HAL_FLASH_Unlock();
FLASH_WaitForLastOperation(2000);
HAL_FLASHEx_Erase(&EraseInitStruct, &page_err);
FLASH_WaitForLastOperation(2000);
HAL_FLASH_Lock();
FLASH_WaitForLastOperation(2000);
}
and in my main.c I do:
FLASH_erase_all();
// Write and read multiple floats using 4-byte aligned addresses
float value1 = 25.5;
uint32_t value1_address = SECTOR_11_START + 0; // Aligned to 4 bytes
FLASH_write_single_float(value1_address, value1);
float read_value1 = FLASH_read_single_float(value1_address);
printf("read_value1 float = %.2f \n", read_value1);
float value2 = 21.5;
uint32_t value2_address = SECTOR_11_START + 4; // Aligned to 4 bytes
FLASH_write_single_float(value2_address, value2);
float read_value2 = FLASH_read_single_float(value2_address);
printf("read_value2 float = %.2f \n", read_value2);
float value3 = 5.5;
uint32_t value3_address = SECTOR_11_START + 8; // Aligned to 4 bytes
FLASH_write_single_float(value3_address, value3);
float read_value3 = FLASH_read_single_float(value3_address);
printf("read_value3 float = %.2f \n", read_value3);
float value4 = 12.5;
uint32_t value4_address = SECTOR_11_START + 12; // Aligned to 4 bytes
FLASH_write_single_float(value4_address, value4);
float read_value4 = FLASH_read_single_float(value4_address);
printf("read_value4 float = %.2f \n", read_value4);
float value5 = 1.5;
uint32_t value5_address = SECTOR_11_START + 16; // Aligned to 4 bytes
FLASH_write_single_float(value5_address, value5);
float read_value5 = FLASH_read_single_float(value5_address);
printf("read_value5 float = %.2f \n", read_value5);
float value6 = 45.5;
uint32_t value6_address = SECTOR_11_START + 20; // Aligned to 4 bytes
FLASH_write_single_float(value6_address, value6);
float read_value6 = FLASH_read_single_float(value6_address);
printf("read_value6 float = %.2f \n", read_value6);
float value7 = 65.5;
uint32_t value7_address = SECTOR_11_START + 24; // Aligned to 4 bytes
FLASH_write_single_float(value7_address, value7);
float read_value7 = FLASH_read_single_float(value7_address);
printf("read_value7 float = %.2f \n", read_value7);
Everything seems to be fine according to the logs:
Program started
FLASH_WRITE_OK
read_value1 float = 25.50
FLASH_WRITE_OK
read_value2 float = 21.50
FLASH_WRITE_OK
read_value3 float = 5.50
FLASH_WRITE_OK
read_value4 float = 12.50
FLASH_WRITE_OK
read_value5 float = 1.50
FLASH_WRITE_OK
read_value6 float = 45.50
FLASH_WRITE_OK
read_value7 float = 65.50
However, when I try to change the addresses to which I am writing (not alligned to 4 bytes):
FLASH_erase_all();
// Write and read multiple floats using 4-byte aligned addresses
float value1 = 25.5;
uint32_t value1_address = SECTOR_11_START + 10;
FLASH_write_single_float(value1_address, value1);
float read_value1 = FLASH_read_single_float(value1_address);
printf("read_value1 float = %.2f \n", read_value1);
float value2 = 21.5;
uint32_t value2_address = SECTOR_11_START + 20;
FLASH_write_single_float(value2_address, value2);
float read_value2 = FLASH_read_single_float(value2_address);
printf("read_value2 float = %.2f \n", read_value2);
float value3 = 5.5;
uint32_t value3_address = SECTOR_11_START + 30;
FLASH_write_single_float(value3_address, value3);
float read_value3 = FLASH_read_single_float(value3_address);
printf("read_value3 float = %.2f \n", read_value3);
float value4 = 12.5;
uint32_t value4_address = SECTOR_11_START + 40;
FLASH_write_single_float(value4_address, value4);
float read_value4 = FLASH_read_single_float(value4_address);
printf("read_value4 float = %.2f \n", read_value4);
float value5 = 1.5;
uint32_t value5_address = SECTOR_11_START + 50;
FLASH_write_single_float(value5_address, value5);
float read_value5 = FLASH_read_single_float(value5_address);
printf("read_value5 float = %.2f \n", read_value5);
float value6 = 45.5;
uint32_t value6_address = SECTOR_11_START + 60;
FLASH_write_single_float(value6_address, value6);
float read_value6 = FLASH_read_single_float(value6_address);
printf("read_value6 float = %.2f \n", read_value6);
float value7 = 65.5;
uint32_t value7_address = SECTOR_11_START + 70;
FLASH_write_single_float(value7_address, value7);
float read_value7 = FLASH_read_single_float(value7_address);
printf("read_value7 float = %.2f \n", read_value7);
it no longer able to read the values properly :
Program started
ad_value1 float =FLASH_WRITE_FAIL
read_value1 float = -nan
FLASH_WRITE_OK
read_value2 float = 21.50
FLASH_WRITE_FAIL
read_value3 float = -nan
FLASH_WRITE_OK
read_value4 float = 12.50
FLASH_WRITE_FAIL
read_value5 float = -nan
FLASH_WRITE_OK
read_value6 float = 45.50
FLASH_WRITE_FAIL
read_value7 float = -nan
I would like to understand what is the reason behind this. I have tried going through the STM32F405 datasheets:
https://www.st.com/resource/en/datasheet/dm00037051.pdf
https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
But was not able to find the answers I am looking for. I hope I can get some clarifications here. Thanks in advance.
