如何解决STM32 FLASH错误:FLASH_FLAG_PGPERR

STM32 FLASH error: FLASH_FLAG_PGPERR & FLASH_FLAG_PGSERR

  • 0. 简介
  • 1. 问题原因
  • 2. FLASH_FLAG_PGPERR & FLASH_FLAG_PGSERR 错误含义
  • 3. Debug
  • 3.1 上电debug 查找 FLASH->SR何时被置位
  • 3.2 追踪FLASH->CR
  • 3.3 问题解决
  • 0. 简介

    在STM32F429 上用FLASH 模拟 EEPROM,工程是STM32CubeIDE里面创建和生成的。调试时发现第一次写FLASH时总是出错,第二次及之后再写FLASH则没问题。

    1. 问题原因

    写FLASH之前会擦除FLASH Sector,第一次擦除时出错。进一步跟踪,发现是调用FLASH_WaitForLastOperation 时返回错误。以下是HAL库里FLASH_WaitForLastOperation的源码。

    HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
    { 
      uint32_t tickstart = 0U;
      
      /* Clear Error Code */
      pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
      
      /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
         Even if the FLASH operation fails, the BUSY flag will be reset and an error
         flag will be set */
      /* Get tick */
      tickstart = HAL_GetTick();
    
      while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET) 
      { 
        if(Timeout != HAL_MAX_DELAY)
        {
          if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
          {
            return HAL_TIMEOUT;
          }
        } 
      }
    
      /* Check FLASH End of Operation flag  */
      if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != RESET)
      {
        /* Clear FLASH End of Operation pending bit */
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
      }
    #if defined(FLASH_SR_RDERR)  
      if(__HAL_FLASH_GET_FLAG((FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \
                               FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR | FLASH_FLAG_RDERR)) != RESET)
    #else
      if(__HAL_FLASH_GET_FLAG((FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | \
                               FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR)) != RESET)  // **这里出错**
    #endif /* FLASH_SR_RDERR */
      {
        /*Save the error code*/
        FLASH_SetErrorCode();
        return HAL_ERROR;
      }
    
      /* If there is no error flag set */
      return HAL_OK;
      
    }  
    

    发现在__HAL_FLASH_GET_FLAG 时, FLASH_FLAG_PGPERR 和 FLASH_FLAG_PGSERR置位了。所以会返回擦除失败。
    但是 FLASH_SetErrorCode 里又会reset 这两位,所以第二次擦除成功。

    2. FLASH_FLAG_PGPERR & FLASH_FLAG_PGSERR 错误含义

    在查看STM32F4参考手册发现:
    FLASH_FLAG_PGSERR : Programming sequence error
    FLASH_FLAG_PGPERR : Programming parallelism error


    原因可能是 FLASH->CR 里的 PSIZE设置错误。

    3. Debug

    3.1 上电debug 查找 FLASH->SR何时被置位


    发现在上电后初始化时钟时, 即执行到 HAL_Init();,FLASH->SR 的 bit6&7 就会被置位,而到此时,执行的都是 cubemx自动生成的 HAL库代码。

    3.2 追踪FLASH->CR


    上电之后, FLASH->CR只有bit31置位,其他均为0.查看FLASH->CR寄存器说明


    PSIZE = 0 时对应的是8位, 而STM32F429是32位,所以应该将 PSIZE设置为 0b10。
    设置后继续debug

    FLASH->SR bit6 的错误没了,但 bit7错误 Programming sequence error 还在。
    PGSERR: Programming sequence error
    Set by hardware when a write access to the Flash memory is performed by the code while the
    control register has not been correctly configured.

    FLASH->CR配置不正确,查看下来只有 CR 的 bit0 有可能。

    3.3 问题解决

    将 FLASH->CR bit0 置1.

    以上,在初始化时,正确配置 FLASH->CR的 PSIZE 和 PG,则消除 FLASH->SR的 bit6&7 错误。

    注:上述未经过稳定性测试。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 如何解决STM32 FLASH错误:FLASH_FLAG_PGPERR

    发表评论