xjtu2011 发表于 2019-4-2 15:58

stm32 IAP FLASH 擦除失败

请教大家,在STM32L431的板子上加入IAP升级引导工程后,原本APP程序中的flash擦写时,擦除总是出错,为什么?具体实验过的现象和疑问有:
如果是IAP程序的问题,但屏蔽掉flash操作功能部分,IAP+APP结构的程序,不管在线调试还是不在线都可以正常运行,这样IAP好像没有问题。
如果是flash擦写函数的问题,那么仅烧写APP程序时,又能正常操作flash。
试图修改IAP和APP两个工程的flash区域配置,两个工程不管有没有flash 交叉,都存在擦除失败的问题。
这问题到底在哪儿?
flash操作的函数如下,先擦除一页,再写数据:
void fsh_putbuf(uint32 adr, uint32 *buf, uint16 len)    //每页写入都是从起始位置写
{
uint32_t prog_bit = 0;
   
DIS_INT;
HAL_FLASH_Unlock();

   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGSERR|FLASH_FLAG_WRPERR);

FirstPage = GetPage(adr);

NbOfPages = 1;

BankNumber = 1;
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Banks       = BankNumber;
EraseInitStruct.Page      = FirstPage;
EraseInitStruct.NbPages   = NbOfPages;


if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)
{
    while (1)
    {
//      __set_FAULTMASK(1);//发出复位请求前,先把FAULTMASK 置位。防止从SYSRESETREQ 被置为有效,到复位发生器执行复位命令期间,处理器响应中断请求。
//      HAL_NVIC_SystemReset();
    }
}

//flash每次写入64bit,8个字节
uint64 d1;
uint64 d2;

if(len % 8==0){
    len = len / 8;
}
else
{ len = len / 8+1;}

while(len--)
{   
    d1 = *(buf++);
    d2 = *(buf++);
   
    d1=d1|(d2<<32);
   
    FLASH_Program_DoubleWord(adr, d1);
    prog_bit = FLASH_CR_PG;
    adr += 8;               
}
      if (prog_bit != 0)
    {
      CLEAR_BIT(FLASH->CR, prog_bit);
    }
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGSERR|FLASH_FLAG_WRPERR);

HAL_FLASH_Lock();
EN_INT;
}

xjtu2011 发表于 2019-4-2 16:06

补充一下,当前IAP仅仅实现了程序的跳转功能。程序能按照APP的输出运行,说明跳转应该是对的

香水城 发表于 2019-4-2 17:00

没看明白你到底擦哪里的flash? IAP区还是APP区?

页擦除时,此刻CPU没法访问FLASH的。

确认下页地址是否正确;

擦除函数的写法可以参考下cube库中的void FLASH_PageErase(uint32_t Page, uint32_t Banks)

eydj2008 发表于 2025-6-10 09:24

我的也是L431CBT6 擦除不成功,但是STLINK又行!
//=======================================================================================
type_bool EraseFlashSector(void)
{
    uint32_t uFirstSector = 16;
    uint32_t uNumOfSectors = 1;//64-uFirstSector;

    static FLASH_EraseInitTypeDef EraseInitStruct;
   
   
    if (HAL_FLASH_Unlock() != HAL_OK)
    {
      return false;
    }
   
    FLASH->SR |= FLASH_FLAG_SR_ERRORS;//clr
   
    FLASH->SR |= FLASH_FLAG_FASTERR;
   
    SET_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_FSTPG));
   
   
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Banks = FLASH_BANK_1;
    EraseInitStruct.Page = uFirstSector;
    EraseInitStruct.NbPages = uNumOfSectors;

    uint32_t uErr;
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &uErr) != HAL_OK)
      return false;

    return true;
}

eydj2008 发表于 2025-6-10 09:26

我也看了 没有进入低功耗模式 ,现在频率是32MHZ    FLASH_LATENCY_1,一擦就报 FLASH_SR_PGSERR

eydj2008 发表于 2025-6-10 09:27

香水城 发表于 2019-4-2 17:00
没看明白你到底擦哪里的flash? IAP区还是APP区?

页擦除时,此刻CPU没法访问FLASH的。


我是从G431移植过来的,看不出什么问题, 电源也是正常的。 还有什么细节吗

七毛钱 发表于 2025-6-10 15:35

在擦除和写入Flash时,必须所有中断被禁用。

powerantone 发表于 2025-6-10 17:00

擦除失败可能导致写入操作失败。

stormwind123 发表于 2025-6-10 17:00

在擦除和写入操作之前,Flash访问权限是否已正确配置。

两只袜子 发表于 2025-6-10 17:30

DIS_INT和EN_INT宏是否禁用和启用了所有中断。

flycamelaaa 发表于 2025-6-10 18:00

Flash配置错误?代码中配置了EraseInitStruct,但需要确认GetPage(adr)函数是否正确返回了目标页的页号。

probedog 发表于 2025-6-10 20:09

地址对齐和长度的问题?

classroom 发表于 2025-6-10 22:00

电源电压是否稳定,避免电压波动导致操作失败。

jcky001 发表于 2025-6-10 22:00

优化擦除和写入顺序,在擦除操作之后,确保等待擦除完成,再进行写入操作。
页: [1]
查看完整版本: stm32 IAP FLASH 擦除失败