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