举报
在STM32H743中,由于Flash存储器的物理特性,擦除操作的最小单位是128KB的扇区,而写入操作需要确保目标区域已被擦除(即全为0xFF)。因此,在扇区中间写入数据时,必须采取特定策略来保留其他数据。以下是详细的解决方案:
#define SECTOR_SIZE (128 * 1024)
uint8_t buffer[SECTOR_SIZE];
memcpy(buffer, (void*)SECTOR_START_ADDR, SECTOR_SIZE);uint32_t target_offset = 0x2000; // 中间地址示例
memcpy(buffer + target_offset, new_data, new_data_size);使用HAL库擦除目标扇区:
FLASH_EraseInitTypeDef erase;
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
erase.Banks = FLASH_BANK_1; // 根据实际使用的Bank选择
erase.Sector = SECTOR_NUMBER;
erase.NbSectors = 1;
uint32_t sector_error;
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase(&erase, §or_error);
HAL_FLASH_Lock();HAL_FLASH_Program函数:HAL_FLASH_Unlock();
for (uint32_t i = 0; i < SECTOR_SIZE; i += 8) {
uint64_t data = *(uint64_t*)(buffer + i);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, SECTOR_START_ADDR + i, data);
}
HAL_FLASH_Lock();__disable_irq();
// 执行Flash操作
__enable_irq();void update_flash_sector(uint32_t sector_addr, uint32_t offset, uint8_t *data, uint32_t size) {
// 备份原始数据
uint8_t backup[SECTOR_SIZE];
memcpy(backup, (void*)sector_addr, SECTOR_SIZE);
// 修改备份数据
memcpy(backup + offset, data, size);
// 擦除扇区
FLASH_EraseInitTypeDef erase = {0};
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
erase.Sector = GET_SECTOR_NUMBER(sector_addr); // 根据地址获取扇区号
erase.NbSectors = 1;
uint32_t sector_error;
HAL_FLASH_Unlock();
if (HAL_FLASHEx_Erase(&erase, §or_error) != HAL_OK) {
// 处理错误
}
// 写回数据
for (uint32_t i = 0; i < SECTOR_SIZE; i += 8) {
uint64_t word = *(uint64_t*)(backup + i);
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, sector_addr + i, word) != HAL_OK) {
// 处理错误
}
}
HAL_FLASH_Lock();
}在STM32H743中,由于Flash擦除的最小单位为128KB扇区,局部更新数据必须通过备份-修改-擦除-写回的流程实现。虽然无法绕过物理擦除限制,但通过合理的软件设计和数据管理策略(如双缓冲、磨损均衡),可以有效减少数据丢失风险并延长Flash寿命。对于频繁更新的场景,建议结合外部存储器或优化存储结构以提升系统鲁棒性。
举报
更多回帖