Improve Write and Read flash on stm32G030 using a Struct array
Budget: $30 – $250 NZD
I am looking for an improved method to write and then read values to from a struct to store and retrieve from the internal flash the current routine works but is unwieldly to maintain. I aa looking for a method to write then read the Struct directly from Flash without going through each variable in the struct.
typedef struct{
uint8_t Acknowledge_Window :8;
uint8_t Output_Active_Time :8;
uint8_t Ready_wait_Time :8;
uint8_t Retry_Count :8;
uint8_t Busy_Tail :8;
uint8_t Pole_Response_Time :8;
uint8_t Pole_Wait_Time :8;
uint8_t Radio_Option :8;
uint8_t CCDI_Wait_Time :8;
uint8_t P25_Ring_Codes :8;
uint8_t P25_Dial_Codes :8;
uint32_t P25_Dest_ID :32;
uint16_t Serial_number :16;
uint8_t Station_Pre_Code :8;
uint8_t Acknowledge_Code :8;
uint16_t Station_Code :12;
uint8_t Reset_Code :4;
uint8_t Radio_Type :4;
uint8_t Outputs_for_Command_1 :5;
uint8_t Outputs_for_Command_2 :5;
uint8_t Outputs_for_Command_3 :5;
uint8_t Outputs_for_Command_4 :5;
uint8_t Outputs_for_Command_5 :5;
uint8_t Outputs_for_Command_6 :5;
uint8_t Outputs_for_Command_7 :5;
uint8_t Outputs_for_Command_8 :5;
uint8_t Outputs_for_Command_9 :5;
uint8_t Outputs_for_Command_A :5;
uint8_t Outputs_for_Command_B :5;
uint8_t Outputs_for_Command_C :5;
uint8_t Outputs_for_Command_D :5;
uint8_t Outputs_for_Command_E :5;
uint8_t Outputs_for_Command_F :5;
}settings_t;
settings_t theSettings;
void factory_reset(){
uint64_t data;
uint32_t address=0x0800F800;
HAL_FLASH_Unlock(); // Unlock the flash memory for write access
// Erase the page that contains the specified address
FLASH_EraseInitTypeDef erase_init;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Page = 31; // Round down to page boundary
erase_init.NbPages = 1;
uint32_t page_error;
HAL_FLASHEx_Erase(&erase_init, &page_error);
data = ((uint64_t)0xFFFFFFFFFFFFFFFF);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address , data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 8, data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 16, data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 24, data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 32, data);
HAL_FLASH_Lock(); // Lock the flash memory to prevent accidental writes
}
void write_to_flash()
{
uint64_t data;
uint32_t address=0x0800F800;
HAL_FLASH_Unlock(); // Unlock the flash memory for write access
// Erase the page that contains the specified address
FLASH_EraseInitTypeDef erase_init;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Page = 31; // Round down to page boundary
erase_init.NbPages = 1;
uint32_t page_error;
HAL_FLASHEx_Erase(&erase_init, &page_error);
// Write the data to the specified address this is a 64bit number
// Write the data to the specified address this is a 64bit number
data = ((uint64_t) theSettings.Acknowledge_Window) +
((uint64_t) theSettings.Output_Active_Time << 8) +
((uint64_t) theSettings.Ready_wait_Time << 16) +
((uint64_t) theSettings.Retry_Count << 24) +
((uint64_t) theSettings.Busy_Tail << 32) +
((uint64_t) theSettings.Pole_Response_Time << 40) +
((uint64_t) theSettings.Pole_Wait_Time << 48) +
((uint64_t) theSettings.Radio_Option << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
data = ((uint64_t) theSettings.CCDI_Wait_Time) +
((uint64_t) theSettings.P25_Ring_Codes << 8) +
((uint64_t) theSettings.P25_Dial_Codes << 16) +
((uint64_t) theSettings.P25_Dest_ID << 24)+
((uint64_t) theSettings.Radio_Type << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 8, data);
data = ((uint64_t) theSettings.Serial_number) +
((uint64_t) theSettings.Station_Pre_Code << 16) +
((uint64_t) theSettings.Acknowledge_Code << 24) +
((uint64_t) theSettings.Station_Code << 32) +
((uint64_t) theSettings.Reset_Code << 48) +
((uint64_t) theSettings.Outputs_for_Command_1 << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 16, data);
data = ((uint64_t) theSettings.Outputs_for_Command_2) +
((uint64_t) theSettings.Outputs_for_Command_3 << 8) +
((uint64_t) theSettings.Outputs_for_Command_4 << 16) +
((uint64_t) theSettings.Outputs_for_Command_5 << 24) +
((uint64_t) theSettings.Outputs_for_Command_6 << 32) +
((uint64_t) theSettings.Outputs_for_Command_7 << 40) +
((uint64_t) theSettings.Outputs_for_Command_8 << 48) +
((uint64_t) theSettings.Outputs_for_Command_9 << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 24, data);
data = ((uint64_t) theSettings.Outputs_for_Command_A)+
((uint64_t) theSettings.Outputs_for_Command_B << 8) +
((uint64_t) theSettings.Outputs_for_Command_C << 16) +
((uint64_t) theSettings.Outputs_for_Command_D << 24) +
((uint64_t) theSettings.Outputs_for_Command_E << 32) +
((uint64_t) theSettings.Outputs_for_Command_F << 40) ;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 32, data);
HAL_FLASH_Lock(); // Lock the flash memory to prevent accidental writes
}
void Cmd::read_flash() {
// Flash routeens
uint64_t * startmemory = (uint64_t * ) 0x0800F800;
uint8_t flashtransfer[4];
uint32_t SettingsAddress = 0x0800F800;
theSettings.Acknowledge_Window = * (uint8_t * ) SettingsAddress++;
theSettings.Output_Active_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Ready_wait_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Retry_Count = * (uint8_t * ) SettingsAddress++;
theSettings.Busy_Tail = * (uint8_t * ) SettingsAddress++;
theSettings.Pole_Response_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Pole_Wait_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Radio_Option = * (uint8_t * ) SettingsAddress++;
theSettings.CCDI_Wait_Time = * (uint8_t * ) SettingsAddress++;
theSettings.P25_Ring_Codes = * (uint8_t * ) SettingsAddress++;
theSettings.P25_Dial_Codes = * (uint8_t * ) SettingsAddress++;
flashtransfer[0] = * (uint8_t * ) SettingsAddress++;
flashtransfer[1] = * (uint8_t * ) SettingsAddress++;
flashtransfer[2] = * (uint8_t * ) SettingsAddress++;
flashtransfer[3] = * (uint8_t * ) SettingsAddress++;
theSettings.P25_Dest_ID = flashtransfer[0] | (flashtransfer[1] << 8) | (flashtransfer[2] << 16) | (flashtransfer[3] << 24);
theSettings.Radio_Type = * (uint8_t * ) SettingsAddress++;
flashtransfer[1] = * (uint8_t * ) SettingsAddress++;
flashtransfer[0] = * (uint8_t * ) SettingsAddress++;
theSettings.Serial_number = flashtransfer[0] | (flashtransfer[1] << 8);
theSettings.Station_Pre_Code = * (uint8_t * ) SettingsAddress++;
theSettings.Acknowledge_Code = * (uint8_t * ) SettingsAddress++;
flashtransfer[0] = * (uint8_t * ) SettingsAddress++;
flashtransfer[1] = * (uint8_t * ) SettingsAddress++;
theSettings.Station_Code = flashtransfer[0] | (flashtransfer[1] << 8);
theSettings.Reset_Code = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_1 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_2 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_3 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_4 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_5 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_6 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_7 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_8 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_9 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_A = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_B = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_C = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_D = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_E = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_F = * (uint8_t * ) SettingsAddress++;
}
typedef struct{
uint8_t Acknowledge_Window :8;
uint8_t Output_Active_Time :8;
uint8_t Ready_wait_Time :8;
uint8_t Retry_Count :8;
uint8_t Busy_Tail :8;
uint8_t Pole_Response_Time :8;
uint8_t Pole_Wait_Time :8;
uint8_t Radio_Option :8;
uint8_t CCDI_Wait_Time :8;
uint8_t P25_Ring_Codes :8;
uint8_t P25_Dial_Codes :8;
uint32_t P25_Dest_ID :32;
uint16_t Serial_number :16;
uint8_t Station_Pre_Code :8;
uint8_t Acknowledge_Code :8;
uint16_t Station_Code :12;
uint8_t Reset_Code :4;
uint8_t Radio_Type :4;
uint8_t Outputs_for_Command_1 :5;
uint8_t Outputs_for_Command_2 :5;
uint8_t Outputs_for_Command_3 :5;
uint8_t Outputs_for_Command_4 :5;
uint8_t Outputs_for_Command_5 :5;
uint8_t Outputs_for_Command_6 :5;
uint8_t Outputs_for_Command_7 :5;
uint8_t Outputs_for_Command_8 :5;
uint8_t Outputs_for_Command_9 :5;
uint8_t Outputs_for_Command_A :5;
uint8_t Outputs_for_Command_B :5;
uint8_t Outputs_for_Command_C :5;
uint8_t Outputs_for_Command_D :5;
uint8_t Outputs_for_Command_E :5;
uint8_t Outputs_for_Command_F :5;
}settings_t;
settings_t theSettings;
void factory_reset(){
uint64_t data;
uint32_t address=0x0800F800;
HAL_FLASH_Unlock(); // Unlock the flash memory for write access
// Erase the page that contains the specified address
FLASH_EraseInitTypeDef erase_init;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Page = 31; // Round down to page boundary
erase_init.NbPages = 1;
uint32_t page_error;
HAL_FLASHEx_Erase(&erase_init, &page_error);
data = ((uint64_t)0xFFFFFFFFFFFFFFFF);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address , data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 8, data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 16, data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 24, data);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 32, data);
HAL_FLASH_Lock(); // Lock the flash memory to prevent accidental writes
}
void write_to_flash()
{
uint64_t data;
uint32_t address=0x0800F800;
HAL_FLASH_Unlock(); // Unlock the flash memory for write access
// Erase the page that contains the specified address
FLASH_EraseInitTypeDef erase_init;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Page = 31; // Round down to page boundary
erase_init.NbPages = 1;
uint32_t page_error;
HAL_FLASHEx_Erase(&erase_init, &page_error);
// Write the data to the specified address this is a 64bit number
// Write the data to the specified address this is a 64bit number
data = ((uint64_t) theSettings.Acknowledge_Window) +
((uint64_t) theSettings.Output_Active_Time << 8) +
((uint64_t) theSettings.Ready_wait_Time << 16) +
((uint64_t) theSettings.Retry_Count << 24) +
((uint64_t) theSettings.Busy_Tail << 32) +
((uint64_t) theSettings.Pole_Response_Time << 40) +
((uint64_t) theSettings.Pole_Wait_Time << 48) +
((uint64_t) theSettings.Radio_Option << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
data = ((uint64_t) theSettings.CCDI_Wait_Time) +
((uint64_t) theSettings.P25_Ring_Codes << 8) +
((uint64_t) theSettings.P25_Dial_Codes << 16) +
((uint64_t) theSettings.P25_Dest_ID << 24)+
((uint64_t) theSettings.Radio_Type << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 8, data);
data = ((uint64_t) theSettings.Serial_number) +
((uint64_t) theSettings.Station_Pre_Code << 16) +
((uint64_t) theSettings.Acknowledge_Code << 24) +
((uint64_t) theSettings.Station_Code << 32) +
((uint64_t) theSettings.Reset_Code << 48) +
((uint64_t) theSettings.Outputs_for_Command_1 << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 16, data);
data = ((uint64_t) theSettings.Outputs_for_Command_2) +
((uint64_t) theSettings.Outputs_for_Command_3 << 8) +
((uint64_t) theSettings.Outputs_for_Command_4 << 16) +
((uint64_t) theSettings.Outputs_for_Command_5 << 24) +
((uint64_t) theSettings.Outputs_for_Command_6 << 32) +
((uint64_t) theSettings.Outputs_for_Command_7 << 40) +
((uint64_t) theSettings.Outputs_for_Command_8 << 48) +
((uint64_t) theSettings.Outputs_for_Command_9 << 56);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 24, data);
data = ((uint64_t) theSettings.Outputs_for_Command_A)+
((uint64_t) theSettings.Outputs_for_Command_B << 8) +
((uint64_t) theSettings.Outputs_for_Command_C << 16) +
((uint64_t) theSettings.Outputs_for_Command_D << 24) +
((uint64_t) theSettings.Outputs_for_Command_E << 32) +
((uint64_t) theSettings.Outputs_for_Command_F << 40) ;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address + 32, data);
HAL_FLASH_Lock(); // Lock the flash memory to prevent accidental writes
}
void Cmd::read_flash() {
// Flash routeens
uint64_t * startmemory = (uint64_t * ) 0x0800F800;
uint8_t flashtransfer[4];
uint32_t SettingsAddress = 0x0800F800;
theSettings.Acknowledge_Window = * (uint8_t * ) SettingsAddress++;
theSettings.Output_Active_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Ready_wait_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Retry_Count = * (uint8_t * ) SettingsAddress++;
theSettings.Busy_Tail = * (uint8_t * ) SettingsAddress++;
theSettings.Pole_Response_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Pole_Wait_Time = * (uint8_t * ) SettingsAddress++;
theSettings.Radio_Option = * (uint8_t * ) SettingsAddress++;
theSettings.CCDI_Wait_Time = * (uint8_t * ) SettingsAddress++;
theSettings.P25_Ring_Codes = * (uint8_t * ) SettingsAddress++;
theSettings.P25_Dial_Codes = * (uint8_t * ) SettingsAddress++;
flashtransfer[0] = * (uint8_t * ) SettingsAddress++;
flashtransfer[1] = * (uint8_t * ) SettingsAddress++;
flashtransfer[2] = * (uint8_t * ) SettingsAddress++;
flashtransfer[3] = * (uint8_t * ) SettingsAddress++;
theSettings.P25_Dest_ID = flashtransfer[0] | (flashtransfer[1] << 8) | (flashtransfer[2] << 16) | (flashtransfer[3] << 24);
theSettings.Radio_Type = * (uint8_t * ) SettingsAddress++;
flashtransfer[1] = * (uint8_t * ) SettingsAddress++;
flashtransfer[0] = * (uint8_t * ) SettingsAddress++;
theSettings.Serial_number = flashtransfer[0] | (flashtransfer[1] << 8);
theSettings.Station_Pre_Code = * (uint8_t * ) SettingsAddress++;
theSettings.Acknowledge_Code = * (uint8_t * ) SettingsAddress++;
flashtransfer[0] = * (uint8_t * ) SettingsAddress++;
flashtransfer[1] = * (uint8_t * ) SettingsAddress++;
theSettings.Station_Code = flashtransfer[0] | (flashtransfer[1] << 8);
theSettings.Reset_Code = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_1 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_2 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_3 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_4 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_5 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_6 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_7 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_8 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_9 = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_A = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_B = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_C = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_D = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_E = * (uint8_t * ) SettingsAddress++;
theSettings.Outputs_for_Command_F = * (uint8_t * ) SettingsAddress++;
}