--Atualizado, veja abaixo--
Estou tentando escrever uma struct de tamanho em torno de 680 bytes para o Setor 1, Banco 2 do flash em um STM32H757XIH6. Sou bem novo nesse tipo de coisa, então estou construindo lentamente o código. Estou usando o driver STM32 HAL. O endereço deste setor é 0x08100000.
Aqui está o código:
typedef struct {
uint32_t data_header;
Parameter parameter[NUMBER_PARAMETERS];
int screen_paras[MAX_SCREENS][MAX_WIDGETS];
} Persistent_data;
void save_data() {
Persistent_data save_data;
uint32_t data_header = DATA_HEADER;
save_data.data_header = data_header;
memcpy(save_data.parameter, parameter, sizeof(save_data.parameter));
memcpy(save_data.screen_paras, screen_paras, sizeof(save_data.screen_paras));
size_t size = sizeof(Persistent_data);
uint32_t word_count = (size + 3) / 4; //32bit alignment
Flash_Write(FLASH_START_ADDRESS, (uint32_t*)&save_data, word_count);
}
HAL_StatusTypeDef Flash_Write(uint32_t address, uint32_t* data, uint32_t length) {
HAL_StatusTypeDef status = HAL_OK;
// Ensure address is within the flash range
if (address < FLASH_USER_START_ADDR || (address + length) > FLASH_USER_END_ADDR) {
return HAL_ERROR;
}
// Unlock the Flash
HAL_FLASH_Unlock();
// Erase the flash sector
FLASH_EraseInitTypeDef eraseInitStruct = {
.TypeErase = FLASH_TYPEERASE_SECTORS,
.Banks = FLASH_BANK_2,
.Sector = FLASH_SECTOR_1,
.NbSectors = 1,
.VoltageRange = FLASH_VOLTAGE_RANGE_3,
};
uint32_t sectorError = 0;
status = HAL_FLASHEx_Erase(&eraseInitStruct, §orError);
if (status != HAL_OK) {
HAL_FLASH_Lock();
return status;
}
// Write the data
for (int i = 0; i < length / 4; i++) { // Writing 32-bit words
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, data[i]);
if (status != HAL_OK) {
break;
}
address += 4; // Increment address by 4 bytes (32 bits)
}
// Lock the Flash
HAL_FLASH_Lock();
return status;
}
Quando tento salvar o save_data (com todos os seus membros), uma falha grave é gerada a partir da linhastatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, data[i]);
Rastreando mais adiante, ele chega *dest_addr = *src_addr;
em stm32h7xx_hal_flash.c. A partir daí, não tenho certeza de como interpretar a pilha de falhas. O próximo é<signal handler called>() at 0xffffffed
ffffffed: Failed to execute MI command:
-data-disassemble -s 4294967277 -e 4294967529 -- 3
Error message from debugger back end:
Cannot access memory at address 0xffffffec
Por favor, deixe-me saber se posso fornecer mais informações
-----Atualização 1:---- Atualizei o código para se adequar à palavra de 256 bits/32 bytes, conforme sugerido. Novos trechos de código:
typedef struct {
uint32_t data_header;
Parameter parameter[NUMBER_PARAMETERS];
int screen_paras[MAX_SCREENS][MAX_WIDGETS];
} Persistent_data;
void save_data() {
Persistent_data save_data;
uint32_t data_header = DATA_HEADER;
save_data.data_header = data_header;
memcpy(save_data.parameter, parameter, sizeof(save_data.parameter));
memcpy(save_data.screen_paras, screen_paras, sizeof(save_data.screen_paras));
size_t size = sizeof(Persistent_data);
uint32_t word_count = (size + 31) / 32; //32bit alignment
Flash_Write(FLASH_START_ADDRESS, (uint32_t*)&save_data, word_count);
}
void load_data() {
Persistent_data load_data;
size_t size = sizeof(Persistent_data);
uint32_t word_count = (size + 31) / 32; //align
Flash_Read(FLASH_START_ADDRESS, (uint32_t*)&load_data, word_count);
if (load_data.data_header == DATA_HEADER) {
memcpy(parameter, load_data.parameter, sizeof(parameter));
memcpy(screen_paras, load_data.screen_paras, sizeof(screen_paras));
}
}
HAL_StatusTypeDef Flash_Write(uint32_t address, uint32_t* data, uint32_t length) {
HAL_StatusTypeDef status = HAL_OK;
// Ensure address is within the flash range
if (address < FLASH_USER_START_ADDR || (address + length) > FLASH_USER_END_ADDR) {
return HAL_ERROR;
}
// Unlock the Flash
HAL_FLASH_Unlock();
// Erase the flash sector
FLASH_EraseInitTypeDef eraseInitStruct = {
.TypeErase = FLASH_TYPEERASE_SECTORS,
.Banks = FLASH_BANK_2,
.Sector = FLASH_SECTOR_1,
.NbSectors = 1,
.VoltageRange = FLASH_VOLTAGE_RANGE_3,
};
uint32_t sectorError = 0;
status = HAL_FLASHEx_Erase(&eraseInitStruct, §orError);
if (status != HAL_OK) {
HAL_FLASH_Lock();
return status;
}
//Write the data
for (int i = 0; i < length / 32; i++) { // Writing 32-byte (256 bit) words
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, (uint32_t)&data[i * 8]);
if (status != HAL_OK) {
break;
}
address += 32; // Increment address by 32 bytes (256 bits)
}
// Lock the Flash
HAL_FLASH_Lock();
return status;
}
/**
* @brief Read data from flash memory
* @param address Start address to read (must be 256-bit aligned)
* @param data Pointer to the buffer to store the read data
* @param length Number of bytes to read (must be a multiple of 32)
*/
void Flash_Read(uint32_t address, uint32_t* data, uint32_t length) {
if (address < FLASH_USER_START_ADDR || (address + length) > FLASH_USER_END_ADDR) {
return; // Out of bounds
}
for (uint32_t i = 0; i < length / 32; i++) { // Reading 32-byte (256-bit) words
// Read 32 bytes (256 bits) from flash starting at the given address
for (uint32_t j = 0; j < 8; j++) {
data[i * 8 + j] = *(__IO uint32_t*)(address + j * 4); // 4 bytes per uint32_t word
}
address += 32; // Increment address by 32 bytes (256 bits)
}
}
Novo problema: Quando leio os dados de volta, eles não estão corretos. O data_header não corresponde. Há dados lá, mas nenhum deles está certo. Poderia ter algo a ver com a maneira como referenciei/usei ponteiros? Ou a maneira como a memória é iterada?
Acho que o problema pode ser que você esteja tentando escrever em regiões sobrepostas, o que é proibido por esta postagem . Você sabe qual gravação está falhando? É sua primeira gravação ou a segunda?
Você está incrementando o endereço em 4 bytes quando deveria estar incrementando em 32 bytes, já que está escrevendo em pedaços de "FLASH_TYPEPROGRAM_FLASHWORD". Veja esta postagem ou esta outra postagem que estão aumentando os deslocamentos de gravação em 32 bytes em cada gravação.
Esta postagem define uma "PALAVRA" como 4 bytes, mas a postagem da série H7 que vinculei anteriormente tem isto:
Indicando que alguns dispositivos definem uma PALAVRA como 8 bytes, estranhamente.
Você pode tentar escrever em pedaços menores, como FLASH_TYPEPROGRAM_BYTE, se seu dispositivo permitir tal operação.