N76E003模拟EEPROM读取和保存应用配置
N76E003模拟EEPROM读取和保存应用配置的代码参考了文章:
https://blog.csdn.net/u014798590/article/details/89268198
我在这个文章代码的基础上优化了下空间,同时更方便配置保存。
用法:在结构体store_config_t内添加想要保存的配置即可,由于是整页擦除,为了不丢失其他配置,保存前需要同步整个store_config_t内容,然后再整体保存。
注意STORE_DATA_SIZE的值要大于store_config_t的大小。
读写配置参考test_flash调用方式。
#define DEF_CFG_VAL_U8 0xFF
#define DEF_CFG_VAL_U16 0xFFFF
typedef struct store_config_struct
{
uint8_t enable;
uint8_t val_u8;
int val_s16;
uint16_t val_u16;
} store_config_t;
int load_config(store_config_t *p_store_cfg);
int save_config(store_config_t *p_store_cfg);
void test_flash(void);
#define FLASH_STORE_ADDR_BASE 0x4700//位于地址末端.4700~47FF共256字节
#define PER_PAGE_SIZE 128
#define EN_OPTIMIZE_XDATA_BUFFER_SIZE
#ifndef EN_OPTIMIZE_XDATA_BUFFER_SIZE
#define STORE_DATA_SIZE 128
#else
#define STORE_DATA_SIZE 16 /*set to sizeof(store_config_t) */
#endif
volatile uint8_t xdata page_buffer[STORE_DATA_SIZE];
uint16_t Read_APROM_WORD(uint16_t *read_addr)
{
uint16_t rdata;
uint16_t code *u16_addr = (uint16_t code *)read_addr;
rdata = *u16_addr;
return rdata;
}
#ifndef EN_OPTIMIZE_XDATA_BUFFER_SIZE
void Write_DATAFLASH_DATA(uint16_t u16EPAddr,
uint8_t *src_data_ptr,
int src_data_len)
{
uint8_t looptmp=0;
uint16_t u16_addrl_r;
uint16_t RAMtmp;
if (src_data_ptr == NULL || src_data_len <= 0)
{
#ifdef ERR_MSG
printf("Write_DATAFLASH_DATA: input error!"CRLF);
#endif
return;
}
if (src_data_len > STORE_DATA_SIZE)
{
#ifdef ERR_MSG
printf("Write_DATAFLASH_DATA: input error! data len=%u is too big to save!"CRLF, src_data_len);
#endif
return;
}
//Check page start address
u16_addrl_r=(u16EPAddr/128)*128;
//Save APROM data to XRAM0
#if 0
for(looptmp=0;looptmp<0x80;looptmp++)
{
RAMtmp = Read_APROM_BYTE((uint16_t *)(u16_addrl_r+looptmp));
page_buffer[looptmp] = RAMtmp & 0xFF;
}
#else
for(looptmp=0; looptmp<PER_PAGE_SIZE; looptmp+=2)
{
RAMtmp = Read_APROM_WORD((uint16_t *)(u16_addrl_r+looptmp));
page_buffer[looptmp] = (RAMtmp >> 8) & 0xFF;
page_buffer[looptmp+1] = RAMtmp & 0xFF;
}
#endif
// Modify customer data in XRAM
//page_buffer[u16EPAddr&0x7f] = u8EPData;
memcpy((page_buffer + (u16EPAddr&0x7f)), (uint8_t *)src_data_ptr, src_data_len);
//Erase APROM DATAFLASH page
IAPAL = u16_addrl_r&0xff;
IAPAH = (u16_addrl_r>>8)&0xff;
IAPFD = 0xFF;
set_IAPEN;
set_APUEN;
IAPCN = 0x22;
set_IAPGO;
//Save changed RAM data to APROM DATAFLASH
set_IAPEN;
set_APUEN;
IAPCN = 0x21;
for(looptmp=0;looptmp<PER_PAGE_SIZE;looptmp++)
{
IAPAL = (u16_addrl_r&0xff)+looptmp;
IAPAH = (u16_addrl_r>>8)&0xff;
IAPFD = page_buffer[looptmp];
set_IAPGO;
}
clr_APUEN;
clr_IAPEN;
}
#else
void Write_DATAFLASH_DATA(uint16_t u16EPAddr,
uint8_t *src_data_ptr,
int src_data_len)
{
uint8_t looptmp=0;
uint16_t u16_addrl_r;
uint16_t RAMtmp;
if (src_data_ptr == NULL || src_data_len <= 0)
{
#ifdef ERR_MSG
printf("flashw: input error!"CRLF);
#endif
return;
}
if ((u16EPAddr&0x7f != 0) || (src_data_len > STORE_DATA_SIZE))
{
#ifdef ERR_MSG
/*u16EPAddr must start of this page */
printf("flashw: input error! data len=%u, target addr=0x%X!"CRLF,
src_data_len, u16EPAddr);
#endif
return;
}
//Check page start address
u16_addrl_r=(u16EPAddr/128)*128;
//Save APROM data to XRAM0
for(looptmp=0; looptmp<STORE_DATA_SIZE; looptmp+=2)
{
RAMtmp = Read_APROM_WORD((uint16_t *)(u16_addrl_r+looptmp));
page_buffer[looptmp] = (RAMtmp >> 8) & 0xFF;
if ((STORE_DATA_SIZE - 1) != looptmp)
{
page_buffer[looptmp+1] = RAMtmp & 0xFF;
}
}
// Modify customer data in XRAM
memcpy((page_buffer), (uint8_t *)src_data_ptr, src_data_len);
//Erase APROM DATAFLASH page
IAPAL = u16_addrl_r&0xff;
IAPAH = (u16_addrl_r>>8)&0xff;
IAPFD = 0xFF;
set_IAPEN;
set_APUEN;
IAPCN = 0x22;
set_IAPGO;
//Save changed RAM data to APROM DATAFLASH
set_IAPEN;
set_APUEN;
IAPCN = 0x21;
for(looptmp=0;looptmp<PER_PAGE_SIZE;looptmp++)
{
IAPAL = (u16_addrl_r&0xff)+looptmp;
IAPAH = (u16_addrl_r>>8)&0xff;
IAPFD = (looptmp < STORE_DATA_SIZE) ? page_buffer[looptmp] : 0xFF;
set_IAPGO;
}
clr_APUEN;
clr_IAPEN;
}
#endif
void Read_DATAFLASH_DATA(uint16_t u16EPAddr,
uint8_t *ptr,
int len)
{
uint16_t i;
uint16_t value;
for (i = 0; i < len; i += 2)
{
value = Read_APROM_WORD((uint16_t *)(u16EPAddr + i));
*(ptr + i) = (value >> 8) & 0xFF;
if ((len - 1) != i)
{
*(ptr + i + 1) = (value) & 0xFF;
}
}
}
int load_config(store_config_t *p_store_cfg)
{
if (!p_store_cfg)
{
return -1;
}
Read_DATAFLASH_DATA((uint16_t)(FLASH_STORE_ADDR_BASE), (uint8_t *)p_store_cfg, sizeof(store_config_t));
return 0;
}
int save_config(store_config_t *p_store_cfg)
{
if (!p_store_cfg)
{
return -1;
}
Write_DATAFLASH_DATA((uint16_t)(FLASH_STORE_ADDR_BASE), (uint8_t *)p_store_cfg, sizeof(store_config_t));
return 0;
}
void test_flash(void)
{
store_config_t tmp_store_cfg;
tmp_store_cfg.enable = 89;
tmp_store_cfg.val_u8 = 0xf1;
tmp_store_cfg.val_s16 = -1612;
tmp_store_cfg.val_u16 = 0x2F92;
save_config(&tmp_store_cfg);
memset(&tmp_store_cfg, 0, sizeof(store_config_t));
load_config(&tmp_store_cfg);
printf("test_flash: 1 the store config EN=%bu, val_u8=0x%bX, temp=(%d, %X)"CRLF,
tmp_store_cfg.enable, tmp_store_cfg.val_u8,
tmp_store_cfg.val_s16, tmp_store_cfg.val_u16);
tmp_store_cfg.enable = 0;
tmp_store_cfg.val_u8 = 0x12;
tmp_store_cfg.val_s16 = 0x3789;
tmp_store_cfg.val_u16 = 0xE2;
save_config(&tmp_store_cfg);
memset(&tmp_store_cfg, 0, sizeof(store_config_t));
load_config(&tmp_store_cfg);
printf("test_flash: 2 the store config EN=%bu, val_u8=0x%bX, temp=(%X, %X)"CRLF,
tmp_store_cfg.enable, tmp_store_cfg.val_u8,
tmp_store_cfg.val_s16, tmp_store_cfg.val_u16);
tmp_store_cfg.enable = 6;
tmp_store_cfg.val_u8 = 0xC3;
tmp_store_cfg.val_s16 = 0xFFFF;
tmp_store_cfg.val_u16 = 0x3F92;
save_config(&tmp_store_cfg);
memset(&tmp_store_cfg, 0, sizeof(store_config_t));
load_config(&tmp_store_cfg);
printf("test_flash: 3 the store config EN=%bu, val_u8=0x%bX, temp=(%X, %X)"CRLF,
tmp_store_cfg.enable, tmp_store_cfg.val_u8,
tmp_store_cfg.val_s16, tmp_store_cfg.val_u16);
// reset to default
tmp_store_cfg.enable = 0;
tmp_store_cfg.val_u8 = DEF_CFG_VAL_U8;
tmp_store_cfg.val_s16 = DEF_CFG_VAL_U16;
tmp_store_cfg.val_u16 = DEF_CFG_VAL_U16;
save_config(&tmp_store_cfg);
}