?? eeprom.c
字號:
} while ( record.status == SUPERSEDED );
last_address = address - (WORD)sizeof(record);
// get next available address
new_address = Find_Next_Address();
if( new_address == SECTOR_FULL ) return SECTOR_FULL; // abort if sector is full
// set old record to update in progress
address = last_address;
for ( i=0; i<sizeof(record); i++ )
{
ptr[i] = Boot_Flash_Read( address++ );
}
record.status = UPDATE_DATA;
address = last_address;
for ( i=0; i < sizeof(record); i++ )
{
if ( Boot_Flash_Write( address++, ptr[i] ) ) return FLASH_WRITE_ERROR;
}
// write data to new address
address = new_address;
record.status = VALID_DATA;
record.last_record_update = 0xFFFF;
for ( i=0; i < EEPROM_RECORD_SIZE; i++ )
{
record.record_data[i] = data_buf[i]; // set data byte
}
address = new_address;
for ( i=0; i < sizeof(record); i++ )
{
if ( Boot_Flash_Write( address++, ptr[i] ) ) return FLASH_WRITE_ERROR;
}
// update old record to superseded
address = last_address;
for ( i=0; i<sizeof(record); i++ )
{
ptr[i] = Boot_Flash_Read( address++ );
}
record.status = SUPERSEDED;
record.last_record_update = new_address;
address = last_address;
for ( i=0; i < sizeof(record); i++ )
{
if ( Boot_Flash_Write( address++, ptr[i] ) ) return FLASH_WRITE_ERROR;
}
return 0;
}
/***** Boot_Flash_Write *****/
// Writes data byte to secondary flash.
// Accepts address in flash; data (byte).
// Returns 0 for successful write. If error, returns 1.
BYTE Boot_Flash_Write(WORD address, BYTE data_byte)
{
BYTE xdata readback;
BYTE xdata done;
BYTE xdata error;
BYTE xdata err;
BYTE xdata poll;
BYTE xdata erase_flag_0 = 0;
BYTE xdata erase_flag_1 = 0;
static BYTE reentry_flag;
// check for re-entrant call to this function
if ( reentry_flag ) return FLASH_ACCESS_ERROR;
reentry_flag = 1;
// un-comment for re-entrancy test
//EA = 1; /* enable interrupts */
done = FALSE;
err = FALSE;
// suspend any erase in progress
if ( Eeprom_Sector_Erase_Status(SECTOR_0) )
{
if ( Eeprom_Sector_Erase_Suspend(SECTOR_0) ) return SECTOR_ERASE_ERROR;
erase_flag_0 = 1;
}
if ( Eeprom_Sector_Erase_Status(SECTOR_1) )
{
if ( Eeprom_Sector_Erase_Suspend(SECTOR_1) ) return SECTOR_ERASE_ERROR;
erase_flag_1 = 1;
}
// disable interrupts during flash write sequence
EA = 0;
// write data byte
*((char xdata *) (SECTOR_0_BASE_ADDRESS + 0x0555)) = 0xAA;
*((char xdata *) (SECTOR_0_BASE_ADDRESS + 0x0AAA)) = 0x55;
*((char xdata *) (SECTOR_0_BASE_ADDRESS + 0x0555)) = 0xA0;
*((char xdata *) address) = data_byte;
// enable interrupts following write
EA = 1;
// now use dat polling method to verify successful write
do
{
poll = *((char xdata *) address); // Read the location that was just programmed
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if ((data_byte & NVM_DATA_POLL) == poll) // compare DQ7
done = TRUE; // dat byte programmed into flash OK, indicate successful exit criteria
else if (error == NVM_ERROR) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while((done == FALSE) && (err == FALSE));
// make sure timeout error and dat poll didn't occur simultaneously
if (err == TRUE)
{
poll = *((char xdata *) address); // Read location in flash again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if ((data_byte & NVM_DATA_POLL) == poll) // compare DQ7
done = TRUE; // dat byte programmed into flash OK at the same time timout
//error occured, indicate successful exit criteria
*((char xdata *) (SECTOR_0_BASE_ADDRESS + 0x0555)) = 0xF0;
//*((char xdata *) 0x0555) = 0xF0; // reset the flash array (short reset instruction)
} // now delay 3 msec per dat sheet
// verify successful write by reading back data and comparing with original
readback = *((char xdata *) address); // readback data from flash
// resume any suspended erase
if ( erase_flag_0 )
{
if ( Eeprom_Sector_Erase_Resume(SECTOR_0) ) return SECTOR_ERASE_ERROR;
}
if ( erase_flag_1 )
{
if ( Eeprom_Sector_Erase_Resume(SECTOR_1) ) return SECTOR_ERASE_ERROR;
}
reentry_flag = 0;
return !(readback == data_byte); // if valid return success
}
/***** Read_Record_Data_Structure *****/
// Reads an entire record structure from memory.
// Accepts record id number.
// Returns address of last record. If error, returns error message.
WORD Read_Record_Data_Structure(WORD id_number, BYTE* buffer)
{
BYTE xdata valid_sector = 0xFF;
xdata struct sector_header xdata header;
xdata struct record_entry xdata record;
BYTE i;
BYTE *ptr;
BYTE xdata *data_buf;
WORD address;
WORD xdata base_address;
WORD xdata last_address;
// get active sector
valid_sector = Find_Active_Sector(F_READ);
if ( valid_sector == SECTOR_ID_ERROR ) return SECTOR_ID_ERROR;
// get pointer to data
data_buf = buffer;
// calculate base address of data
base_address = SECTOR_0_BASE_ADDRESS + ((WORD)valid_sector * SECTOR_SIZE) +
(WORD)sizeof(header) + ( id_number * (WORD)sizeof(record) );
// get base record
ptr = (BYTE*) (&record);
address = base_address;
for ( i=0; i<sizeof(record); i++ )
{
ptr[i] = Boot_Flash_Read( address++ );
}
// get last record
if ( record.last_record_update != 0xFFFF )
{
address = base_address;
do
{
ptr = (BYTE*) (&record);
last_address = address;
for ( i=0; i<sizeof(record); i++ )
{
ptr[i] = Boot_Flash_Read( address++ );
}
address = record.last_record_update;
} while ( record.last_record_update != 0xFFFF );
}
else
{
last_address = base_address;
}
// Get last record
for (i=0; i<sizeof(record); i++)
{
data_buf[i] = Boot_Flash_Read(last_address++);
}
// return address of last record
return last_address - sizeof(record);
}
/***** Boot_Flash_Read *****/
// Reads data from secondary flash.
// Accepts address.
// Returns data at address.
BYTE Boot_Flash_Read(WORD address)
{
BYTE xdata erase_flag_0 = 0;
BYTE xdata erase_flag_1 = 0;
BYTE data_byte;
static BYTE xdata reentry_flag;
// check for re-entrant call to this function
if ( reentry_flag ) return FLASH_ACCESS_ERROR;
reentry_flag = 1;
// un-comment for re-entrancy test
//EA = 1; /* enable interrupts */
// suspend any erase in progress
if ( Eeprom_Sector_Erase_Status(SECTOR_0) )
{
if ( Eeprom_Sector_Erase_Suspend(SECTOR_0) ) return SECTOR_ERASE_ERROR;
erase_flag_0 = 1;
}
if ( Eeprom_Sector_Erase_Status(SECTOR_1) )
{
if ( Eeprom_Sector_Erase_Suspend(SECTOR_1) ) return SECTOR_ERASE_ERROR;
erase_flag_1 = 1;
}
// read data byte from flash
data_byte = *((char xdata *) address);
// resume any suspended erase
if ( erase_flag_0 )
{
if ( Eeprom_Sector_Erase_Resume(SECTOR_0) ) return SECTOR_ERASE_ERROR;
}
if ( erase_flag_1 )
{
if ( Eeprom_Sector_Erase_Resume(SECTOR_1) ) return SECTOR_ERASE_ERROR;
}
reentry_flag = 0;
return data_byte;
}
/***** Eeprom_Sector_Erase *****/
// Erases one boot flash sector.
// Accepts sector number (0-3).
// Returns 0 for successful erasure. If error, returns 1.
BYTE Eeprom_Sector_Erase(BYTE sector)
{
BYTE xdata done;
BYTE xdata poll;
BYTE xdata error;
BYTE xdata err;
done = FALSE;
err = FALSE;
switch (sector)
{
case SECTOR_0:
*(BOOT_FLASH_SECTOR_0_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
*(BOOT_FLASH_SECTOR_0_XAAA) = 0x55; // unlock main flash, write 0x55 to addess 0xXAAA
*(BOOT_FLASH_SECTOR_0_X555) = 0x80; // write 0x80 command to erase entire chip
*(BOOT_FLASH_SECTOR_0_X555) = 0xAA; // continue unlock sequence
*(BOOT_FLASH_SECTOR_0_XAAA) = 0x55; // continue unlock sequence
*((volatile unsigned char xdata *)SECTOR_0_BASE_ADDRESS) = 0x30;// erase sector
do // now use dat polling method to verify successful erase
{
poll = *((volatile unsigned char xdata *)SECTOR_0_BASE_ADDRESS); // read flash status from any address
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // look at D7
if ( poll == NVM_DATA_POLL ) // compare DQ7
done = TRUE; // bulk erase OK,
else if (error == NVM_ERROR) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while( (done == FALSE) && (err == FALSE) );
if ( err == TRUE ) // make sure timeout error and dat poll didn't occur simultaneously
{
poll = *((volatile unsigned char xdata *)SECTOR_0_BASE_ADDRESS); // Read flash status again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (poll == NVM_DATA_POLL) // compare DQ7
done = TRUE; // the flash erased OK at the same time timout error occured
*(BOOT_FLASH_SECTOR_0_X555) = 0xF0; // reset the flash array (short reset instruction)
}
break;
case SECTOR_1:
*(BOOT_FLASH_SECTOR_1_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
*(BOOT_FLASH_SECTOR_1_XAAA) = 0x55; // unlock main flash, write 0x55 to addess 0xXAAA
*(BOOT_FLASH_SECTOR_1_X555) = 0x80; // write 0x80 command to erase entire chip
*(BOOT_FLASH_SECTOR_1_X555) = 0xAA; // continue unlock sequence
*(BOOT_FLASH_SECTOR_1_XAAA) = 0x55; // continue unlock sequence
*((volatile unsigned char xdata *)SECTOR_1_BASE_ADDRESS) = 0x30;// erase sector
do // now use dat polling method to verify successful erase
{
poll = *((volatile unsigned char xdata *)SECTOR_1_BASE_ADDRESS); // read flash status from any address
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // look at D7
if ( poll == NVM_DATA_POLL ) // compare DQ7
done = TRUE; // bulk erase OK,
else if (error == NVM_ERROR) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while( (done == FALSE) && (err == FALSE) );
if ( err == TRUE ) // make sure timeout error and dat poll didn't occur simultaneously
{
poll = *((volatile unsigned char xdata *)SECTOR_1_BASE_ADDRESS); // Read flash status again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (poll == NVM_DATA_POLL) // compare DQ7
done = TRUE; // the flash erased OK at the same time timout error occured
*(BOOT_FLASH_SECTOR_0_X555) = 0xF0; // reset the flash array (short reset instruction)
}
break;
case SECTOR_2:
*(BOOT_FLASH_SECTOR_2_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
*(BOOT_FLASH_SECTOR_2_XAAA) = 0x55; // unlock main flash, write 0x55 to addess 0xXAAA
*(BOOT_FLASH_SECTOR_2_X555) = 0x80; // write 0x80 command to erase entire chip
*(BOOT_FLASH_SECTOR_2_X555) = 0xAA; // continue unlock sequence
*(BOOT_FLASH_SECTOR_2_XAAA) = 0x55; // continue unlock sequence
*((volatile unsigned char xdata *)SECTOR_2_BASE_ADDRESS) = 0x30;// erase sector
do // now use dat polling method to verify successful erase
{
poll = *((volatile unsigned char xdata *)SECTOR_2_BASE_ADDRESS); // read flash status from any address
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // look at D7
if ( poll == NVM_DATA_POLL ) // compare DQ7
done = TRUE; // bulk erase OK,
else if (error == NVM_ERROR) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while( (done == FALSE) && (err == FALSE) );
if ( err == TRUE ) // make sure timeout error and dat poll didn't occur simultaneously
{
poll = *((volatile unsigned char xdata *)SECTOR_2_BASE_ADDRESS); // Read flash status again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (poll == NVM_DATA_POLL) // compare DQ7
done = TRUE; // the flash erased OK at the same time timout error occured
*(BOOT_FLASH_SECTOR_0_X555) = 0xF0; // reset the flash array (short reset instruction)
}
break;
case SECTOR_3:
*(BOOT_FLASH_SECTOR_3_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
*(BOOT_FLASH_SECTOR_3_XAAA) = 0x55; // unlock main flash, write 0x55 to addess 0xXAAA
*(BOOT_FLASH_SECTOR_3_X555) = 0x80; // write 0x80 command to erase entire chip
*(BOOT_FLASH_SECTOR_3_X555) = 0xAA; // continue unlock sequence
*(BOOT_FLASH_SECTOR_3_XAAA) = 0x55; // continue unlock sequence
*((volatile unsigned char xdata *)SECTOR_3_BASE_ADDRESS) = 0x30;// erase sector
do // now use dat polling method to verify successful erase
{
poll = *((volatile unsigned char xdata *)SECTOR_3_BASE_ADDRESS); // read flash status from any address
error = poll & NVM_ERROR; // save timeout error bit at DQ5
poll = poll & NVM_DATA_POLL; // look at D7
if ( poll == NVM_DATA_POLL ) // compare DQ7
done = TRUE; // bulk erase OK,
else if (error == NVM_ERROR) // check for timeout error
err = TRUE; // indicate timeout error occurred
} while( (done == FALSE) && (err == FALSE) );
if ( err == TRUE ) // make sure timeout error and dat poll didn't occur simultaneously
{
poll = *((volatile unsigned char xdata *)SECTOR_3_BASE_ADDRESS); // Read flash status again
poll = poll & NVM_DATA_POLL; // get DQ7 of poll byte read from flash
if (poll == NVM_DATA_POLL) // compare DQ7
done = TRUE; // the flash erased OK at the same time timout error occured
*(BOOT_FLASH_SECTOR_0_X555) = 0xF0; // reset the flash array (short reset instruction)
}
break;
default:
return 1;
}
return !(done);
}
/***** Eeprom_Sector_Erase_Start*****/
// Start Erases one boot flash sector.
// Accepts sector number (0-3).
// Returns 0 for successful erasure. If error, returns 1.
BYTE Eeprom_Sector_Erase_Start(BYTE sector)
{
switch (sector)
{
case SECTOR_0:
*(BOOT_FLASH_SECTOR_0_X555) = 0xAA; // unlock main flash, write 0xAA to addess 0xX555
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -