标题:
ABOV A94B114芯片EEPROM相关求助
[打印本页]
作者:
节水牛仔有点渴
时间:
2023-10-19 18:09
标题:
ABOV A94B114芯片EEPROM相关求助
如题,本人在使用ABOV A94B114芯片进行开发时,在掉电记忆的处理部分遇到了难题,希望有大佬能帮忙看看.大家讨论讨论交流一下思路也好eeprom.c文件内容如下
uint8 xdata SaveData[MAX_TAB_ADDRES];
uint8 xdata NAME_SAVE_FG;
uint8 xdata TestrAM1;
uint8 xdata TestrAM2;
unsigned int User_ID;
unsigned char *PageBufData;
unsigned int PageBufDataSize;
volatile unsigned char data code_buf[20] _at_ 0x30;
volatile unsigned char data g_FEMR, g_FECR, g_WDTMR;
volatile unsigned char g_IE, g_IE1, g_IE2;
extern void Flash_Enter(void);
void Init_Flash()
{
User_ID = 0;
// Set Flash Sector Address as Dummy address
FEARH = (FLASH_ADDR_DUMMY >> 16) & 0x0f; //Flash Sector Address High Register
FEARM = (FLASH_ADDR_DUMMY >> 8) & 0xff; //Flash Sector Address Middle Register
FEARL = (FLASH_ADDR_DUMMY >> 0) & 0xff; //Flash Sector Address Low Register
}
void Flash_Enter(void)
{
g_IE = IE;
g_IE1 = IE1;
g_IE2 = IE2;
IE = 0;
IE1 = 0;
IE2 = 0;
g_WDTMR = WDTMR; // Backup WDTMR
WDTMR = 0; // Watch Dog Timer Stop.
g_WDTMR |= 0x04; // Clear WDT Counter
// To access Flash Control register, ENTRY_0~2 should be set 0xAA, 0x55, 0xA5.
*(unsigned char xdata *)0x10D8 = 0xAA;
*(unsigned char xdata *)0x10DA = 0x55;
*(unsigned char xdata *)0x10DD = 0xA5;
// Set Flash Sector Address as Dummy address
FEARH = (FLASH_ADDR_DUMMY >> 16) & 0x0f; //Flash Sector Address High Register
FEARM = (FLASH_ADDR_DUMMY >> 8) & 0xff; //Flash Sector Address Middle Register
FEARL = (FLASH_ADDR_DUMMY >> 0) & 0xff; //Flash Sector Address Low Register
}
void Flash_Exit(void)
{
FECR = 0x33; //FLASH_MODE_EXIT
// After to change Flash Control register, ENTRY_0~2 should be set 0x00.
*(unsigned char xdata *)0x10D8 = 0x00;
*(unsigned char xdata *)0x10DA = 0x00;
*(unsigned char xdata *)0x10DD = 0x00;
// Flash code buffer ram clear.
#pragma asm
mov r0, #code_buf
mov r2, #20
clr a
loop0:
mov @r0, a
inc r0
djnz r2, loop0
#pragma endasm
WDTMR = g_WDTMR; // Restore WDTMR
/* restore IE setting */
IE = g_IE;
IE1 = g_IE1;
IE2 = g_IE2;
}
volatile void write_page_buffer_src()
{
FEMR = 0x89;//
//FLASH_SEL // FSEL (Select Flash memory)
//| FLASH_PBUFF_SEL // PBUFF (Select page buffer)
//| FLASH_CON_ENABLE; // FEEN (Enable program & erase)
#pragma asm
mov r0,#32
mov dptr,#0x10E0 ; page buffer address
write_page_buffer_src_loop:
mov a, @r1 ;r1=addr of rxdata
movx @dptr,a
inc r1
inc dptr
djnz r0,write_page_buffer_src_loop
#pragma endasm
FEMR = 0;
}
void write_page_buffer(unsigned char *dt) // dt -> r3, r2, r1
{
uint8 *temp = dt;
#pragma asm
mov dptr,#write_page_buffer_src
mov r0,#0x30
mov r2,#0x12
write_page_buffer_loop:
clr a
movc a,@a+dptr
mov @r0,a
inc dptr
inc r0
djnz r2,write_page_buffer_loop
ljmp 0x8030 ; jump sram region
#pragma endasm
}
volatile void do_flash_at_sram_src()
{
#pragma asm
mov FEMR,g_FEMR // 3 byte
mov FECR,g_FECR // 3 byte
_flash_busy_wait:
mov A,FESR // 2 byte
JNB ACC.7,_flash_busy_wait // 3 byte
clr A // 1 byte
mov FEMR,A // 2 byte
#pragma endasm
} // RET // 1byte
void do_flash_at_sram()
{
#pragma asm
mov dptr,#do_flash_at_sram_src
mov r0,#0x30
mov r1,#0x0F
do_flash_at_sram_loop:
clr a
movc a,@a+dptr
mov @r0,a
inc dptr
inc r0
djnz r1,do_flash_at_sram_loop
ljmp 0x8030
#pragma endasm
}
void Update_Flash_Buf(unsigned char *buf, unsigned int buf_size)
{
//Flash Buffer Update
User_ID = FLASH_USER_ID;
PageBufData = buf;
PageBufDataSize = buf_size;
}
void Update_Flash(unsigned int key)
{
unsigned char i = 0;
unsigned int s = 0;
unsigned long addr;
unsigned char ret = 0;
if(key == FLASH_KEY)
{
if(User_ID == FLASH_USER_ID)
{
addr = FLASH_ADDR_USER;
s = PageBufDataSize;
while(PageBufDataSize > 0)
{
if(PageBufDataSize < PAGE_BUFFER_SIZE)
{
s = PageBufDataSize;
PageBufDataSize = 0;
}
else
{
s = PAGE_BUFFER_SIZE;
PageBufDataSize -= PAGE_BUFFER_SIZE;
}
ret = Erase_Flash(FLASH_KEY, FLASH_ADDR_USER + (PAGE_BUFFER_SIZE*i));
if(ret == 1 || ret == 2)
{
//error;
while(1);
}
ret = Write_Flash(FLASH_KEY, FLASH_ADDR_USER + (PAGE_BUFFER_SIZE*i),
s, PageBufData + (PAGE_BUFFER_SIZE*i));
if(ret == 1 || ret == 4)
{
//error;
while(1);
}
i++;
}
}
User_ID = 0;
}
}
unsigned char Erase_Flash(unsigned int key, unsigned long sector_address)
{
unsigned char code *rom_addr = 0x0000;
unsigned char i = 0;
unsigned char tmp = 0;
unsigned char tmp2 = 0;
unsigned char ret = 0;
//Disable EA
tmp = IE;
IE &= (~0x80);
//LVR enable, safety code
tmp2 = LVIR;
LVIR &= ~(1<<7); //LVR enable
if(key == FLASH_KEY)
{
key ^= FLASH_XOR;
if(sector_address < (unsigned long)FLASH_SIZE)
{
// Flash Flash Control Register CLR change before initialization.
FECR = 0;
FETCR = 0;
FEMR = 0;
// Enable program mode
Flash_Enter();
FETCR = WAITTIME; // 0x9D = 157 : (157+1) * 2 (31.25ns * 256) = 2.528ms
FECR = 0x02; // Reset page buffer.
_nop_( ); //Dummy instruction, This instruction must be needed.
_nop_( ); //Dummy instruction, This instruction must be needed.
_nop_( ); //Dummy instruction, This instruction must be needed.
g_FEMR = 0x91; // Set Erase mode.
g_FECR = 0x0B; // Start Erase.
// Set Flash Sector Address as used area
FEARH = (sector_address >> 16) & 0xFF;
FEARM = (sector_address >> 8) & 0xFF;
FEARL = (sector_address) & 0xFF;
//Check Power stable by LVR Enable
//if LVR disable, return error 2
if((LVIR & 0x80) == 0x00)
{
// Check User_ID
if(User_ID == FLASH_USER_ID)
{
// Check valid of Flash Sector Address range
if( (unsigned long)FLASH_ADDR_MIN <= sector_address && sector_address <= (unsigned long)FLASH_ADDR_MAX)
{
if((key ^ FLASH_XOR) == FLASH_KEY)
{
// Flase Erase at ram
do_flash_at_sram();
}
Flash_Exit(); // Set flash to normal mode.
//verify data
for(i = 0; i < PAGE_BUFFER_SIZE; i++)
{
if(rom_addr[sector_address + i] != 0x00)
{
ret = 2;
}
}
}
}
}
else
{
ret = 1;//LVI error
Flash_Exit();
}
// Set Flash Sector Address as Dummy address
FEARH = (FLASH_ADDR_DUMMY >> 16) & 0x0f; //Flash Sector Address High Register
FEARM = (FLASH_ADDR_DUMMY >> 8) & 0xff; //Flash Sector Address Middle Register
FEARL = (FLASH_ADDR_DUMMY >> 0) & 0xff; //Flash Sector Address Low Register
}
}
LVIR = tmp2;
IE = tmp;
return ret;
}
unsigned char Write_Flash(unsigned int key, unsigned long sector_address, unsigned int buf_size, unsigned char *buf)
{
unsigned char *pdt;
unsigned char code *rom_addr=0x0000;
unsigned char i = 0;
unsigned char tmp = 0;
unsigned char tmp2 = 0;
unsigned char ret = 0;
//Disable EA
tmp = IE;
IE &= (~0x80);
//LVR enable, safety code
tmp2 = LVIR;
LVIR &= ~(1<<7); //LVR enable
if(key == FLASH_KEY)
{
key ^= FLASH_XOR;
if(sector_address < (unsigned long)FLASH_SIZE)
{
// Enable program mode
Flash_Enter();
FETCR = WAITTIME; // 0x9D = 157 : (157+1) * 2 (31.25ns * 256) = 2.528ms
FEMR = 0x81; // Select flash and enable control.
FECR = 0x02 ; // (Reset page buffer)
_nop_( ); //Dummy instruction, This instruction must be needed.
_nop_( ); //Dummy instruction, This instruction must be needed.
_nop_( ); //Dummy instruction, This instruction must be needed.
// Set Flash Sector Address as used area
FEARH = (sector_address >> 16) & 0xFF;
FEARM = (sector_address >> 8) & 0xFF;
FEARL = (sector_address) & 0xFF;
write_page_buffer(buf);
buf_size = buf_size;//not used A94B114
g_FEMR = 0xA1; // Set write mode.
g_FECR = 0x0B; // Start program.
//Check Power stable by LVR Enable
//if LVR disable, return error 2
if((LVIR & 0x80) == 0x00)
{
// Check User_ID1/2
if(User_ID == FLASH_USER_ID)
{
// Check valid of Flash Sector Address range
if( (unsigned long)FLASH_ADDR_MIN <= sector_address && sector_address <= (unsigned long)FLASH_ADDR_MAX)
{
if((key ^ FLASH_XOR) == FLASH_KEY)
{
// Flase Write at ram
do_flash_at_sram();
}
Flash_Exit(); // Set flash to normal mode.
//verify data
pdt = buf;
for(i = 0; i < PAGE_BUFFER_SIZE; i++)
{
sector_address_tmp = sector_address;
if(rom_addr[sector_address + i] != *pdt)
{
ret = 4;
}
pdt++;
}
}
}
}
else
{
ret = 1;//LVI error
Flash_Exit();
}
// Set Flash Sector Address as Dummy address
FEARH = (FLASH_ADDR_DUMMY >> 16) & 0x0f; //Flash Sector Address High Register
FEARM = (FLASH_ADDR_DUMMY >> 8) & 0xff; //Flash Sector Address Middle Register
FEARL = (FLASH_ADDR_DUMMY >> 0) & 0xff; //Flash Sector Address Low Register
}
}
LVIR = tmp2;
IE = tmp;
return ret;
}
void Read_Flash(unsigned long sector_address, unsigned int buf_size, unsigned char *buf)
{
unsigned char code *rom_addr=0x0000;
unsigned int i = 0;
for(i = 0; i < buf_size; i++)
{
buf[i] = rom_addr[sector_address + i];
}
}
void WriteEEprom(void)
{
if (NAME_SAVE_FG == WRIT_COMMAND_CODE)
{
Init_Flash();
SaveData[1] = TestrAM1;
SaveData[2] = TestrAM2;
SaveData[3] = TempMOde;
SaveData[TEST_C1_ADDRES] = TEST_NAME_C1;
SaveData[TEST_C2_ADDRES] = TEST_NAME_C2;
Update_Flash_Buf(SaveData, PAGE_BUFFER_SIZE);
Update_Flash(FLASH_KEY);
NAME_SAVE_FG = 0;
}
}
void RestPara(void)
{
SaveData[1] = 0X90;
SaveData[2] = 0XA7;
SaveData[3] = TempMOde = 0;
SaveData[TEST_C1_ADDRES] = TEST_NAME_C1;
SaveData[TEST_C2_ADDRES] = TEST_NAME_C2;
Init_Flash();
Update_Flash_Buf(SaveData, PAGE_BUFFER_SIZE);
Update_Flash(FLASH_KEY);
}
void ReadEE(void)
{
Read_Flash(FLASH_ADDR_USER, PAGE_BUFFER_SIZE, SaveData);
if ((SaveData[TEST_C1_ADDRES] == TEST_NAME_C1) && (SaveData[TEST_C2_ADDRES] == TEST_NAME_C2))
{
TestrAM1 = SaveData[1];
TestrAM2 = SaveData[2];
TempMOde = SaveData[3];
}
else
{
RestPara();
}
}
复制代码
在eeprom.c文件当中,除了最后的WriteEEprom,RestPara,ReadEE,其余的部分都是从A94B114官方提供的flash.c例程中copy过来的, 以下是eeprom.h文件内容
#ifndef _EEPROM_H
#define _EEPROM_H
extern uint8 xdata NAME_SAVE_FG;
#define WRIT_COMMAND_CODE 0X12
#define TEST_NAME_C2 0XA4
#define TEST_NAME_C1 0xB4
#define TEST_C1_ADDRES 0
#define TEST_C2_ADDRES 12
#define MAX_TAB_ADDRES 32
//Device Dependent=======================================
#define FLASH_SIZE (0x001FFF)
#define PAGE_BUFFER_SIZE (0x20)
//Modify to use==========================================
//Flash Address for used
#define FLASH_ADDR_USER 0x001f80
//Flash Address Min/Max value for permitted area
#define FLASH_ADDR_MIN 0x001f80
#define FLASH_ADDR_MAX 0x001fff
//more than 2.0V @ IRC 16MHz
#define FLASH_LVI 0x01 //LVI 2.4V(2.05V~2.35V)
//Flash Dummy Address value, not used area
#define FLASH_ADDR_DUMMY 0x03FF00
//=====================================================
//safety code for operation of flash memory
#define FLASH_KEY 0xAA55
#define FLASH_XOR 0x9C75
#define WAITTIME 0x9D // 2.5ms
//Flash Mode Control value
#define FLASH_PAGEBUFFER_RESET 0x01
//Flash User ID value, used password
#define FLASH_USER_ID 0xCC33
extern void Init_Flash();
extern void Update_Flash_Buf(unsigned char *buf, unsigned int size);
extern void Update_Flash(unsigned int key);
extern unsigned char Erase_Flash(unsigned int key, unsigned long sector_address);
extern unsigned char Write_Flash(unsigned int key, unsigned long sector_address, unsigned int size, unsigned char *buf);
extern void Read_Flash(unsigned long sector_address, unsigned int size, unsigned char *buf);
extern void ReadEE(void);
extern void WriteEEprom(void);
#endif
复制代码
在调试过程中发现,每次都是在Write_Flash()函数中,似乎是数据验证出错,导致ret = 4,然后在Update_Flash()中while(1)死循环触发复位, 希望大家能帮忙看看,谢谢!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1