客户用国民技术-N32G030做的一个项目想用FLASH的最末页保存4个字节的用户数据,基于数据量很小,为了尽量减少对FLASH的擦写次数:采用动态地址读写,每次有数据变更则读写地址后移4字节直到写完一整页后再擦除一次FLASH页后从页起始开始写入4个字节。为了进一步减少对FLASH的擦写次数同时方便编程,想通过PVD检测,每次用户断电后进入PVD中断先复位所有IO时钟以减少电流消耗,再检查数据写入请求标志是否将RAM数据写入FLASH,但是PVD检测的最高电压是2.4V,在电压下降到2V之前还有大概50毫秒的时间具体见下图波形:
目前在FLASH没有擦除的情况下数据保存是没有问题的,客户问题:这么做会不会存在隐患,如果一页写满需要擦除FLASH页则这个时间和电压能不能保证正常工作。
以下附上源代码:
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] This function handles the PVD Output interrupt request defined in main.h .
*/
void PVD_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_LINE16) != RESET)
{
/* Clear the Key Button EXTI line pending bit */
EXTI_ClrITPendBit(EXTI_LINE16);
RCC->APB2PRST |= 0xD69D;
if (0xA5==ee_request)WriteEepData();
while (1);
}
}
uint16_t FindEepData(void)
{
uint16_t page_offset;
for (page_offset=0;page_offset<FLASH_PAGE_SIZE/4-1;page_offset++)
{
if (*((uint32_t*)EEPROM_BLOCK+page_offset+1)==0xFFFFFFFF)break;
}
return page_offset;
}
void LoadEepData(void)
{
uint8_t rbuff[4];
uint16_t page_offset = FindEepData();
*(uint32_t*)rbuff = *((uint32_t*)EEPROM_BLOCK+page_offset);
PC_TXVOLUME = rbuff[0]!=0xFF?rbuff[0]:0x05;
PC_TXVSPEED = rbuff[1]!=0xFF?rbuff[1]:0x05;
PC_TXPWH8 = rbuff[2]!=0xFF?rbuff[2]:0;
PC_TXPWL8 = rbuff[3]!=0xFF?rbuff[3]:0;
}
void SYN6658_Config(void)
{
char cmd_string[]="[vxx][sxx][mxx]";
uint8_t i = PC_TXVOLUME&15;
cmd_string[2] = '0'+i/10;
cmd_string[3] = '0'+i%10;
i = PC_TXVSPEED&15;
cmd_string[7] = '0'+i/10;
cmd_string[8] = '0'+i%10;
i = PC_TXVSPEED>>4;
cmd_string[12] = i==0?'0':'5';
cmd_string[13] = i==0?'3':'0'+i;
VoicePrintf(cmd_string);
while (syn6658_status==0);
delay_ms(100);
}
uint8_t WriteEepData(void)
{
uint8_t res = 0,wbuf8[4]={0xFF,0xFF,0xFF,0xFF};
uint16_t page_offset = FindEepData();
uint32_t buf32 = *((uint32_t*)EEPROM_BLOCK+page_offset);
wbuf8[0]=PC_TXVOLUME;wbuf8[1]=PC_TXVSPEED;
wbuf8[2]=PC_TXPWH8;wbuf8[3]=PC_TXPWL8;
if (buf32==*((uint32_t*)wbuf8))return 0;
/* Unlocks the FLASH Program Erase Controller */
FLASH_Unlock();
/* Program FLASH */
if (buf32!=0xFFFFFFFF)
{
page_offset++;page_offset &= PAGE_SIZE_MASK>>2;
buf32 = *((uint32_t*)EEPROM_BLOCK+page_offset);
/* Erase */
if (buf32!=0xFFFFFFFF && FLASH_COMPL != FLASH_EraseOnePage(EEPROM_BLOCK))
{
res=1;goto EXIT;
}
}
/* Program */
if (FLASH_COMPL != FLASH_ProgramWord(EEPROM_BLOCK + page_offset*4, *(uint32_t*)wbuf8))
{
res=2;
}
EXIT:
/* Locks the FLASH Program Erase Controller */
FLASH_Lock();
return res;
}
国民技术-N32G030系列(512字节)擦除时间,全文下典型值为2.27ms,数据手册中有介绍,基于应用场景可以自行评估,同时可以提个建议参考:擦写flash前先检测VDD电压,VDD满足大于3V再进行flash操作可减少风险。