打印

stm32f4xx_flash.c的函数FLASH_GetStatus是否有BUG ?

[复制链接]
4599|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nicholasldf|  楼主 | 2013-8-27 16:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
FLASH_Status FLASH_GetStatus(void)
{
  FLASH_Status flashstatus = FLASH_COMPLETE;
  
  if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY)
  {
    flashstatus = FLASH_BUSY;
  }
  else
  {  
    if((FLASH->SR & FLASH_FLAG_WRPERR) != (uint32_t)0x00)
    {
      flashstatus = FLASH_ERROR_WRP;
    }
    else
    {
      /*
      这句是否应该是if((FLASH->SR & (uint32_t)0xE0) != (uint32_t)0x00)才对啊
      OPERR: Operation error和EOP: End of operation是在中断使能时(ERRIE = 1EOPIE =1)才置位的
      假设EOP位为1,将返回FLASH_ERROR_PROGRAM,EOP为1不代表编程出错吧
      */
      if((FLASH->SR & (uint32_t)0xEF) != (uint32_t)0x00)
      {
        flashstatus = FLASH_ERROR_PROGRAM;
      }
      else
      {
        if((FLASH->SR & FLASH_FLAG_OPERR) != (uint32_t)0x00)
        {
          flashstatus = FLASH_ERROR_OPERATION;
        }
        else
        {
          flashstatus = FLASH_COMPLETE;
        }
      }
    }
  }
  /* Return the FLASH Status */
  return flashstatus;
}
沙发
cjhk| | 2013-8-27 18:59 | 只看该作者
不是很了解   楼主   帮你顶一个   看看别人的意见   应该有答案的

使用特权

评论回复
板凳
nicholasldf|  楼主 | 2013-8-28 20:43 | 只看该作者
香水城:lol在哪

使用特权

评论回复
地板
nicholasldf|  楼主 | 2013-8-29 13:49 | 只看该作者
经过验证,确实是个BUG。在FLASH测试函数中打开OPERR和EOP中断,,但是NVIC中不使能,,这样不会响应FLASH中断,
但是FLASH操作结束后,会响应的设置OPERR和EOP标志位。

库的版本是V1.1.0,11-January-2013
不敢100%肯定,只敢99%确定是BUG,所以欢迎各位STM32er验证。

/*
Flash read and write test example
- 对扇区11进行擦除,然后写入1024字节的数据
*/
void Flash_Read_Write_Test(void)
{
        uint32_t data, i, address ;
        FLASH_Status status;
        FlagStatus FStatus;
       
        //查看扇区写保护状态
        data = FLASH_OB_GetWRP();
        while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
        USART_SendData(USART3, data);
        //查看扇区读保护级别状态
        FStatus = FLASH_OB_GetRDP();
        while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
        USART_SendData(USART3, FStatus);
       
        //清除扇区11的写保护
        FLASH_OB_Unlock();
        FLASH_OB_WRPConfig(OB_WRP_Sector_11, DISABLE);
        status = FLASH_OB_Launch();
        FLASH_OB_Lock();
        if(FLASH_COMPLETE != status)
                return;
       
        //准备写数据
        FLASH_Unlock();
       
        //打开OPERR和EOP中断,FLASH_Status FLASH_GetStatus(void)函数将出现BUG
        FLASH_ITConfig(FLASH_IT_ERR|FLASH_IT_EOP, ENABLE);
       
        //擦除扇区11  
          FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
                  FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
          status = FLASH_EraseSector(FLASH_Sector_11, VoltageRange_3);
        if(FLASH_COMPLETE != status)
                return;
        //读数据,验证扇区11是否被擦除
        address = 0x080E0000;//扇区11首地址
        for(i=0; i<256*4; i++){
                data = *((uint8_t*)address + i);
                //输出到串口
                  while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
                    USART_SendData(USART3, data);
        }
       
        //写数据
        address = 0x080E0000;//扇区11首地址
        for(i=0; i<256; i++){
                /* Clear pending flags (if any) */
                  FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
                  FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
                data = i<<24 | i<<16 | i<<8 | i;
                status = FLASH_ProgramWord(address + i*4, data);//写一个字
                //status = FLASH_ProgramHalfWord(Address + i*2, uint16_t Data);//写一个半字
                //status = FLASH_ProgramByte(Address + i, uint8_t Data);//写一个字节
                if(FLASH_COMPLETE != status)
                        break;
        }
       
        FLASH_Lock();
       
        //读数据,验证是否写正确
        address = 0x080E0000;//扇区11首地址
        for(i=0; i<256*4; i++){
                data = *((uint8_t*)address + i);
                //输出到串口
                  while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
                    USART_SendData(USART3, data);
        }
}

修正的FLASH_GetStatus函数
/**
  * @brief  Returns the FLASH Status.
  * @param  None
  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PROGRAM,
  *                       FLASH_ERROR_WRP, FLASH_ERROR_OPERATION or FLASH_COMPLETE.
  */
FLASH_Status FLASH_GetStatus(void)
{
  FLASH_Status flashstatus = FLASH_COMPLETE;
  
  if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY)
  {
    flashstatus = FLASH_BUSY;
  }
  else
  {  
    if((FLASH->SR & FLASH_FLAG_WRPERR) != (uint32_t)0x00)
    {
      flashstatus = FLASH_ERROR_WRP;
    }
    else
    {
          /*
          此处是否有BUG?应该是if((FLASH->SR & (uint32_t)0xE0) != (uint32_t)0x00)
          当PGSERR、PGPERR、PGAERR有至少1个不为0时,则表示FLASH_ERROR_PROGRAM
          OPERR和EOP只有当ERRIE = 1,EOPIE =1时才会设置,并且OPERR表示操作错误,
          EOP表示编程或擦除操作成功完成
          在使能中断情况下,可能是个BUG,未使能中断时,没有问题
          
          经过验证,通过FLASH_ITConfig(FLASH_IT_ERR|FLASH_IT_EOP, ENABLE)打开中断,
          发现在EOP置1的情况下,此处返回FLASH_ERROR_PROGRAM
          */
      if((FLASH->SR & (uint32_t)0xE0) != (uint32_t)0x00)
      {
        flashstatus = FLASH_ERROR_PROGRAM;
      }
      else
      {
        if((FLASH->SR & FLASH_FLAG_OPERR) != (uint32_t)0x00)
        {
          flashstatus = FLASH_ERROR_OPERATION;
        }
        else
        {
          flashstatus = FLASH_COMPLETE;
        }
      }
    }
  }
  /* Return the FLASH Status */
  return flashstatus;
}

使用特权

评论回复
5
nicholasldf|  楼主 | 2013-8-29 23:21 | 只看该作者
无人确认吗

使用特权

评论回复
6
zchong| | 2014-6-13 13:17 | 只看该作者
看手册,开中断的时候的确有些问题,之所以无人确认,是因为大部分应用没有必要开flash的中断,也就是使用的时候不会遇到这个问题。

使用特权

评论回复
7
飞鹰嵌入式| | 2015-3-28 16:14 | 只看该作者
我试了试确实是这样的,楼主威武啊!

使用特权

评论回复
8
搞IT的| | 2015-3-29 10:43 | 只看该作者
具体的楼主可以将程序跑一边吧。。。。

使用特权

评论回复
9
cowboy2014| | 2015-3-30 17:03 | 只看该作者
nicholasldf 发表于 2013-8-29 13:49
经过验证,确实是个BUG。在FLASH测试函数中打开OPERR和EOP中断,,但是NVIC中不使能,,这样不会响应FLASH ...

我自己也用过写flash,看了你的帖子我自己再去试试

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

261

帖子

10

粉丝