📄 flashc.txt
字号:
if (retry-- > 0) {
++retried;
--dst, --src; /* back up */
goto again; /* and retry the last word */
}
if (ub == FALSE)
flash_command(FLASH_RESET,sector,0,0);
}
return (char *)src - buf;
}
/*********************************************************************/
/* Flash_status utilizes the DQ6, DQ5, and DQ3 polling algorithms */
/* described in the flash data book. It can quickly ascertain the */
/* operational status of the flash device, and return an */
/* appropriate status code (defined in flash.h) */
/*********************************************************************/
int flash_status(word far *fp)
{
unsigned char d, t;
int retry = 1;
again:
d = *fp; /* read data */
t = d ^ *fp; /* read it again and see what toggled */
if (t == 0) { /* no toggles, nothing's happening */
return STATUS_READY;
}
else if (t == 0x04) { /* erase-suspend */
if (retry--) goto again; /* may have been write completion */
return STATUS_ERSUSP;
}
else if (t & 0x40) {
if (d & 0x20) { /* timeout */
return STATUS_TIMEOUT;
}
else {
return STATUS_BUSY;
}
}
if (retry--) goto again; /* may have been write completion */
return STATUS_ERROR;
}
/*********************************************************************/
/* BEGIN API WRAPPER FUNCTIONS */
/*********************************************************************/
/* Flash_sector_erase() will erase a single sector dictated by the */
/* sector parameter. */
/* Note: this function will merely BEGIN the erase program. Code */
/* execution will immediately return to the calling function */
/*********************************************************************/
byte flash_sector_erase(byte sector)
{
flash_command(FLASH_SERASE,sector,0,0);
return(1);
}
/*********************************************************************/
/* Flash_sector_erase_int() is identical to flash_sector_erase(), */
/* except it will wait until the erase is completed before returning */
/* control to the calling function. This can be used in cases which */
/* require the program to hold until a sector is erased, without */
/* adding the wait check external to this function. */
/*********************************************************************/
byte flash_sector_erase_int(byte sector)
{
flash_command(FLASH_SERASE,sector,0,0);
while (flash_status(get_flash_memptr(sector))
== STATUS_BUSY) { }
return(1);
}
/*********************************************************************/
/* flash_reset() will reset the flash device to reading array data. */
/* It is good practice to call this function after autoselect */
/* sequences had been performed. */
/*********************************************************************/
byte flash_reset(void)
{
flash_command(FLASH_RESET,1,0,0);
return(1);
}
/*********************************************************************/
/* flash_get_device_id() will perform an autoselect sequence on the */
/* flash device, and return the device id of the component. */
/* This function automatically resets to read mode. */
/*********************************************************************/
word flash_get_device_id(byte sector)
{
word far *fwp; /* flash window */
word answer;
fwp = (word *)get_flash_memptr(sector);
flash_command(FLASH_AUTOSEL,sector,0,0);
answer = *(fwp++);
flash_command(FLASH_RESET,sector,0,0); /* just to be safe */
return( (word) answer );
}
/*********************************************************************/
/* flash_get_manuf_code() will perform an autoselect sequence on the */
/* flash device, and return the manufacturer code of the component. */
/* This function automatically resets to read mode. */
/*********************************************************************/
byte flash_get_manuf_code(byte sector)
{
word far *fwp; /* flash window */
word answer;
fwp = (word *)get_flash_memptr(sector);
flash_command(FLASH_AUTOSEL,sector,0,0);
answer = *fwp;
flash_command(FLASH_RESET,sector,0,0); /* just to be safe */
return( (byte) (answer & 0x00FF) );
}
/*********************************************************************/
/* flash_sector_protect_verify() performs an autoselect command */
/* sequence which checks the status of the sector protect CAM */
/* to check if the particular sector is protected. Function will */
/* return a '0' is the sector is unprotected, and a '1' if it is */
/* protected. */
/*********************************************************************/
byte flash_sector_protect_verify(byte sector)
{
word far *fwp; /* flash window */
byte answer;
fwp = (word *)get_flash_memptr(sector);
flash_command(FLASH_AUTOSEL,sector,0,0);
fwp += ((meminfo->sec[sector].base)/2);
fwp += 2;
answer = (byte) (*fwp & 0x0001); /* Only need DQ0 to check */
flash_command(FLASH_RESET,sector,0,0);
return( (byte) answer );
}
/*********************************************************************/
/* flash_get_status() will return the current operational status of */
/* the flash device. A list of return codes is outlined in flash.h */
/* Note: for DL parts, status will be bank dependent. */
/*********************************************************************/
byte flash_get_status(byte sector)
{
word far *fwp;
fwp = (word *)get_flash_memptr(sector);
return flash_status(fwp);
}
/*********************************************************************/
/* flash_chip_erase() will perform a complete erasure of the flash */
/* device. */
/*********************************************************************/
byte flash_chip_erase(byte sector)
{
flash_command(FLASH_CERASE,sector,0,0);
return(1);
}
/*********************************************************************/
/* flash_write_word() will program a single word of data at the */
/* specified offset from the beginning of the sector parameter. */
/* Note: this offset must be word aligned, or else errors are */
/* possible (this can happen when dealing with odd offsets due to */
/* only partial programming. */
/* Note: It is good practice to check the desired offset by first */
/* reading the data, and checking to see if it contains 0xFFFF */
/*********************************************************************/
byte flash_write_word(byte sector, word offset, word data)
{
flash_command(FLASH_PROG, sector, offset, data);
return (1);
}
/*********************************************************************/
/* flash_read_word() reads a single word of data from the specified */
/* offset from the sector parameter. This function will auto align */
/* the offset to return word data. */
/*********************************************************************/
word flash_read_word(byte sector, word offset)
{
word far *fwp;
flash_command(FLASH_SELECT,sector,0,0);
fwp = (word *)get_flash_memptr(sector);
if (offset & 0x0001){ /* Is odd? */
offset--;
}
fwp += offset;
return( (word) *fwp );
}
/*********************************************************************/
/* flash_write_string() functions like flash_write_word(), except */
/* that it accepts a pointer to a buffer to be programmed. This */
/* function will align the data to a word offset, then bulk program */
/* the flash device with the provided data. */
/* The maximum buffer size is currently only limited to the data */
/* size of the numbytes parameter (which in the test system is */
/* 16 bits = 65535 words */
/* Since the current maximum flash sector size is 64kbits, this */
/* should not present a problem. */
/*********************************************************************/
byte flash_write_string(byte sector, word offset,
byte *buffer, word numbytes)
{
word value=0;
if(numbytes == 0)
value = (word) strlen(buffer);
else
value = numbytes;
if (value & 0x0001)
value--; /* Need to make sure we don't overrun buffer */
flash_write(sector, offset, buffer, value,FALSE);
return (1);
}
/*********************************************************************/
/* flash_erase_suspend() will suspend an erase process in the */
/* specified sector. Array data can then be read from other sectors */
/* (or any other sectors in other banks), and the erase can be */
/* resumed using the flash_erase_resume function. */
/* Note: multiple sectors can be queued for erasure, so long as the */
/* 80 uS erase suspend window has not terminated (see AMD data sheet */
/* concerning erase_suspend restrictions). */
/*********************************************************************/
byte flash_erase_suspend(byte sector)
{
flash_command(FLASH_ESUSPEND, sector, 0, 0);
return (1);
}
/*********************************************************************/
/* flash_erase_resume() will resume all pending erases in the bank */
/* in which the sector parameter is located. */
/*********************************************************************/
byte flash_erase_resume(byte sector)
{
flash_command(FLASH_ERESUME, sector, 0, 0);
return (1);
}
/*********************************************************************/
/* flash_get_sector_size() is provided for cases in which the size */
/* of a sector is required by a host application. The sector size */
/* (in bytes) is returned in the data location pointed to by the */
/* 'size' parameter. */
/*********************************************************************/
byte flash_get_sector_size(byte sector, dword *size)
{
*size = meminfo->sec[sector].size;
return(1);
}
/*********************************************************************/
/* UNLOCK BYPASS FUNCTIONS */
/*********************************************************************/
/* Unlock bypass mode is useful whenever the calling application */
/* wished to program large amounts of data in minimal time. Unlock */
/* bypass mode remove half of the bus overhead required to program */
/* a single word, from 4 cycles down to 2 cycles. Programming of */
/* individual bytes does not gain measurable benefit from unlock */
/* bypass mode, but programming large strings can see a significant */
/* decrease in required programming time. */
/*********************************************************************/
/*********************************************************************/
/* flash_ub() places the flash into unlock bypass mode. This */
/* is REQUIRED to be called before any of the other unlock bypass */
/* commands will become valid (most will be ignored without first */
/* calling this function. */
/*********************************************************************/
byte flash_ub(byte sector)
{
flash_command(FLASH_UB, sector, 0, 0);
return(1);
}
/*********************************************************************/
/* flash_write_word_ub() programs a single word using unlock bypass */
/* mode. Note that the calling application will see little benefit */
/* from programming single words using this mode (outlined above) */
/*********************************************************************/
byte flash_write_word_ub(byte sector, word offset, word data)
{
flash_command(FLASH_UBPROG, sector, offset, data);
return (1);
}
/*********************************************************************/
/* flash_write_string_ub() behaves in the exact same manner as */
/* flash_write_string() (outlined above), expect that it utilizes */
/* the unlock bypass mode of the flash device. This can remove */
/* significant overhead from the bulk programming operation, and */
/* when programming bulk data a sizeable performance increase can be */
/* observed. */
/*********************************************************************/
byte flash_write_string_ub(byte sector, word offset,
byte *buffer, word numbytes)
{
word value=0;
if(numbytes == 0)
value = (word) strlen(buffer);
else
value = numbytes;
if (value & 0x0001)
value--; /* Need to make sure we don't overrun buffer */
flash_write(sector, offset, buffer, value,TRUE);
return (1);
}
/*********************************************************************/
/* flash_reset_ub() is required to remove the flash from unlock */
/* bypass mode. This is important, as other flash commands will be */
/* ignored while the flash is in unlock bypass mode. */
/*********************************************************************/
byte flash_reset_ub(void)
{
flash_command(FLASH_UBRESET,1,0,0);
return(1);
}
/*********************************************************************/
/* Usefull funtion to return the number of sectors in the device. */
/* Can be used for functions which need to loop among all the */
/* sectors, or wish to know the number of the last sector. */
/*********************************************************************/
void flash_get_numsectors(int *num)
{
*num = meminfo->nsect;
}
/*********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -