--已更新,见下文--
我正在尝试将一个大小约为 680 字节的结构写入 STM32H757XIH6 中闪存的第 1 扇区、第 2 组。我对这种事情还很陌生,所以我正在慢慢地编写代码。我正在使用 STM32 HAL 驱动程序。该扇区的地址是 0x08100000。
代码如下:
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;
}
当我尝试保存 save_data (及其所有成员)时,该行会产生硬故障status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, data[i]);
进一步追踪它,它进入了*dest_addr = *src_addr;
stm32h7xx_hal_flash.c。从那里我不确定如何解释崩溃堆栈,接下来是<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
如果我可以提供更多信息,请告诉我
-----更新 1:---- 我已根据建议更新了代码以适应 256 位/32 字节字。新代码片段:
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)
}
}
新问题:当我读回数据时,它不正确。data_header 不匹配。那里有数据,但都不正确。这可能与我引用/使用指针的方式有关吗?或者与内存迭代的方式有关?
我认为问题可能是您试图在重叠区域进行写入,而根据这篇文章,这是被禁止的。您知道哪个写入失败了吗?是第一次写入还是第二次写入?
由于您以“FLASH_TYPEPROGRAM_FLASHWORD”块的形式写入,因此您以4 个字节递增地址,而您应以32 个字节递增。请参阅此帖子或其他帖子,它们在每次写入时将写入偏移量增加 32 个字节。
这篇文章将“WORD”定义为 4 个字节,但我之前链接的 H7 系列文章却有这样的内容:
奇怪的是,有些设备将一个字定义为 8 个字节。
如果您的设备允许这样的操作,您可以尝试写入较小的块,例如 FLASH_TYPEPROGRAM_BYTE。