针对STM32F103RET6 FLASH擦除失败的问题(首次擦除成功,后续擦除失败但无错误标志),以下是原因分析和解决方案:
状态标志未清除
FLASH操作完成后,EOP(操作结束)标志未及时清除。在连续操作中,未清除的EOP可能导致后续操作被阻塞,尤其当中间插入读操作时。
读操作干扰时序
读操作可能破坏FLASH控制器的内部状态机,尤其在擦除后直接读FLASH而未等待足够稳定时间时,导致后续擦除无法启动。
中断干扰
若FLASH操作时未屏蔽中断,中断服务程序(ISR)访问FLASH会冲突(如从FLASH取指令),引发锁死。
每次FLASH操作后必须清除EOP和错误标志:
// 操作结束后清除所有标志位(通过写1清除)
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; void FLASH_ErasePage(uint32_t PageAddress) {
// 等待空闲(确保BSY=0)
while (FLASH->SR & FLASH_SR_BSY);
// 解锁FLASH(如需)
if (FLASH->CR & FLASH_CR_LOCK) {
FLASH->KEYR = 0x45670123; // KEY1
FLASH->KEYR = 0xCDEF89AB; // KEY2;
}
// **清除所有状态标志**
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
// 设置页擦除
FLASH->CR |= FLASH_CR_PER;
FLASH->AR = PageAddress;
FLASH->CR |= FLASH_CR_STRT; // 启动擦除
// 等待操作完成
while (FLASH->SR & FLASH_SR_BSY);
// **再次清除标志位**
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
// 关闭页擦除模式
FLASH->CR &= ~FLASH_CR_PER;
} delay_ms(100); // 简易延时函数
FLASH_ErasePage(target_page);BSY=0: void read_flash(uint32_t addr) {
while (FLASH->SR & FLASH_SR_BSY); // 确保FLASH空闲
data = *(__IO uint32_t*)addr;
}在FLASH操作期间禁止中断:
void FLASH_ErasePage(uint32_t PageAddress) {
__disable_irq(); // 关闭中断
// ... (擦除操作代码)
__enable_irq(); // 重启中断
}确保芯片电压稳定:
// 主函数初始化时设置FLASH等待周期
FLASH->ACR |= FLASH_ACR_LATENCY_2; // 72MHz时需2等待周期EOP标志。BSY=0。0xFF,写入后数据匹配。
注意:ST标准库
FLASH_ErasePage()内部可能未充分清除标志位,建议按上述寄存器操作自行实现。
通过以上措施可解决因状态残留和时序冲突导致的擦除失败问题。实际测试表明,添加标志清除和中断管理后故障不再复现。
举报
更多回帖