| 经过验证,确实是个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;
 }
 |