📄 lld.c
字号:
status_read_2 = FLASH_RD(base_addr, offset);
status_read_3 = FLASH_RD(base_addr, offset);
/* Any DQ6 toggles */
dq6_toggles = ((status_read_1 ^ status_read_2) & /* Toggles between read1 and read2 */
(status_read_2 ^ status_read_3) & /* Toggles between read2 and read3 */
DQ6_MASK ); /* Check for DQ6 only */
if (dq6_toggles)
{
/* Checking WriteBuffer Abort condition:
Check for all devices that have DQ6 toggling also have Write Buffer Abort DQ1 set */
if (WriteBufferProgramming &&
((DQ6_TGL_DQ1_MASK & status_read_1) == DQ6_TGL_DQ1_MASK) )
return DEV_WRITE_BUFFER_ABORT;
/* Checking Timeout condition:
Check for all devices that have DQ6 toggling also have Time Out DQ5 set. */
if ((DQ6_TGL_DQ5_MASK & status_read_1) == DQ6_TGL_DQ5_MASK )
return DEV_EXCEEDED_TIME_LIMITS;
/* No timeout, no WB error */
return DEV_BUSY;
}
else /* no DQ6 toggles on all devices */
{
/* Checking Erase Suspend condition */
status_read_1 = FLASH_RD(base_addr, offset);
status_read_2 = FLASH_RD(base_addr, offset);
/* Checking Erase Suspend condition */
if ( ((status_read_1 ^ status_read_2) & DQ2_MASK) == 0)
return DEV_NOT_BUSY; /* All devices DQ2 not toggling */
if (((status_read_1 ^ status_read_2) & DQ2_MASK) == DQ2_MASK)
return DEV_SUSPEND; /* All devices DQ2 toggling */
else
return DEV_BUSY; /* Wait for all devices DQ2 toggling */
}
}
else
{
/*..................................................................
Use Status Register Read command to read the status register.
This is for GL-R device only
...................................................................*/
#ifdef STATUS_REG
volatile FLASHDATA status_reg;
wlld_StatusRegReadCmd( base_addr, offset ); /* Issue status register read command */
status_reg = FLASH_RD(base_addr, offset); /* read the status register */
if ( (status_reg & DEV_RDY_MASK) != DEV_RDY_MASK ) /* Are all devices done bit 7 is 1 */
return DEV_BUSY ;
if ( status_reg & DEV_ERASE_MASK ) /* Any erase error */
return DEV_ERASE_ERROR;
if ( status_reg & DEV_PROGRAM_MASK ) /* Any program error */
return DEV_PROGRAM_ERROR;
if ( status_reg & DEV_SEC_LOCK_MASK ) /* Any sector lock error */
return DEV_SECTOR_LOCK;
return DEV_NOT_BUSY ;
#endif
return DEV_STATUS_UNKNOWN; /* should never get here */
}
}
#endif
/******************************************************************************
*
* lld_WriteBufferProgramOp - Performs a Write Buffer Programming Operation.
*
* Function programs a write-buffer overlay of addresses to data
* passed via <data_buf>.
* Function issues all required commands and polls for completion.
*
* There are 4 main sections to the function:
* Set-up and write command sequence
* Determine number of locations to program and load buffer
* Start operation with "Program Buffer to Flash" command
* Poll for completion
*
* REQUIREMENTS:
* Data in the buffer MUST be properly aligned with the Flash bus width.
* No parameter checking is performed.
* The <word_count> variable must be properly initialized.
* Valid <byte_cnt> values:
* min = 1 byte (only valid when used with a single x8 Flash)
* max = write buffer size in bytes * number of devices in parallel
(e.g. 32-byte buffer per device, 2 x16 devices = 64 bytes)
*
* RETURNS: DEVSTATUS
*/
#ifndef REMOVE_WRITE_BUFFER_PROGRAMMING
DEVSTATUS lld_WriteBufferProgramOp
(
FLASHDATA * base_addr, /* device base address is system */
ADDRESS offset, /* address offset from base address */
WORDCOUNT word_count, /* number of words to program */
FLASHDATA *data_buf /* buffer containing data to program */
)
{
DEVSTATUS status;
FLASHDATA write_data = 0;
FLASHDATA read_data = 0;
ADDRESS last_loaded_addr;
ADDRESS current_offset;
ADDRESS end_offset;
FLASHDATA wcount;
/* Initialize variables */
current_offset = offset;
end_offset = offset + word_count - 1;
last_loaded_addr = offset;
/* don't try with a count of zero */
if (!word_count)
{
return(DEV_NOT_BUSY);
}
/* Issue Load Write Buffer Command Sequence */
lld_WriteToBufferCmd(base_addr, offset);
/* Write # of locations to program */
wcount = (FLASHDATA)word_count - 1;
wcount *= LLD_DEV_MULTIPLIER;
FLASH_WR(base_addr, offset, wcount);
/* Load Data into Buffer */
while(current_offset <= end_offset)
{
/* Store last loaded address & data value (for polling) */
last_loaded_addr = current_offset;
write_data = *data_buf;
/* Write Data */
FLASH_WR(base_addr, current_offset++, *data_buf++);
}
/* Issue Program Buffer to Flash command */
lld_ProgramBufferToFlashCmd(base_addr, last_loaded_addr);
status = lld_Poll(base_addr, last_loaded_addr, &write_data,
&read_data, LLD_P_POLL_WRT_BUF_PGM);
return(status);
}
#endif
/******************************************************************************
*
* lld_ProgramOp - Performs a standard Programming Operation.
*
* Function programs a single location to the specified data.
* Function issues all required commands and polls for completion.
*
*
* RETURNS: DEVSTATUS
*/
#ifndef REMOVE_LLD_PROGRAM_OP
DEVSTATUS lld_ProgramOp
(
FLASHDATA * base_addr, /* device base address is system */
ADDRESS offset, /* address offset from base address */
FLASHDATA write_data /* variable containing data to program */
)
{
FLASHDATA read_data = 0;
DEVSTATUS status;
lld_ProgramCmd(base_addr, offset, &write_data);
status = lld_Poll(base_addr, offset, &write_data, &read_data, LLD_P_POLL_PGM);
return(status);
}
#endif
/******************************************************************************
*
* lld_SectorEraseOp - Performs a Sector Erase Operation
*
* Function erases the sector containing <base_addr> + <offset>.
* Function issues all required commands and polls for completion.
*
*
* RETURNS: DEVSTATUS
*
* ERRNO:
*/
#ifndef REMOVE_LLD_SECTOR_ERASE_OP
DEVSTATUS lld_SectorEraseOp
(
FLASHDATA * base_addr, /* device base address is system */
ADDRESS offset /* address offset from base address */
)
{
FLASHDATA expect_data = (FLASHDATA)0xFFFFFFFF;
FLASHDATA actual_data = 0;
DEVSTATUS status;
lld_SectorEraseCmd(base_addr, offset);
status = lld_Poll(base_addr, offset, &expect_data, &actual_data, LLD_P_POLL_SEC_ERS);
return(status);
}
#endif
/******************************************************************************
*
* lld_ChipEraseOp - Performs a Chip Erase Operation
*
* Function erases entire device located at <base_addr>.
* Function issues all required commands and polls for completion.
*
*
* RETURNS: DEVSTATUS
*/
#ifndef REMOVE_LLD_CHIP_ERASE_OP
DEVSTATUS lld_ChipEraseOp
(
FLASHDATA * base_addr /* device base address in system */
)
{
DEVSTATUS status;
FLASHDATA expect_data = (FLASHDATA)0xFFFFFFFF;
FLASHDATA actual_data = 0;
lld_ChipEraseCmd(base_addr);
status = lld_Poll(base_addr, 0, &expect_data, &actual_data, LLD_P_POLL_CHIP_ERS);
/* if an error during polling, write RESET command to device */
if(status != DEV_NOT_BUSY) lld_ResetCmd(base_addr);
return(status);
}
#endif
/******************************************************************************
*
* DelayMilliseconds - Performs a delay. If you have a better way,
* edit the macro DELAY_MS in lld_target_specific.h
*
* RETURNS: void
*
*/
#ifndef REMOVE_DELAY_MILLISECONDS
void DelayMilliseconds(int milliseconds)
{
int i;
for (i = 0; i < milliseconds; i++)
DELAY_US(1000);
}
#endif
/******************************************************************************
*
* DelayMicroseconds - Performs a delay. If you have a better way,
* edit the macro DELAY_US in lld_target_specific.h
*
* RETURNS: void
*
*/
#ifndef REMOVE_DELAY_MICROSECONDS
void DelayMicroseconds(int microseconds)
{
int volatile i, j;
for (j = 0; j < microseconds; j++)
for(i = 0; i < DELAY_1us; i++) i = i;
}
#endif
/******************************************************************************
*
* lld_ReadOp - Read memory array operation
*
* RETURNS: data read
*
*/
#ifndef REMOVE_LLD_READ_OP
FLASHDATA lld_ReadOp
(
FLASHDATA * base_addr, /* device base address is system */
ADDRESS offset /* address offset from base address */
)
{
FLASHDATA data;
data = FLASH_RD(base_addr, offset);
return(data);
}
#endif
/******************************************************************************
*
* lld_GetDeviceId - Get device ID operation
*
* RETURNS: three byte ID in a single int
*
*/
#ifndef REMOVE_LLD_GET_DEVICE_ID
unsigned int lld_GetDeviceId
(
FLASHDATA * base_addr /* device base address in system */
)
{
unsigned int id;
FLASH_WR(base_addr, LLD_UNLOCK_ADDR1, NOR_UNLOCK_DATA1);
FLASH_WR(base_addr, LLD_UNLOCK_ADDR2, NOR_UNLOCK_DATA2);
FLASH_WR(base_addr, LLD_UNLOCK_ADDR1, NOR_AUTOSELECT_CMD);
id = (unsigned int)(FLASH_RD(base_addr, 0x0001) & 0x000000FF) << 16;
id |= (unsigned int)(FLASH_RD(base_addr, 0x000E) & 0x000000FF) << 8;
id |= (unsigned int)(FLASH_RD(base_addr, 0x000F) & 0x000000FF) ;
lld_ResetCmd(base_addr);
return(id);
}
#endif
/******************************************************************************
*
* lld_memcpy This function attempts to mimic the standard memcpy
* function for flash. It segments the source data
* into page size chunks for use by Write Buffer Programming.
*
* RETURNS: DEVSTATUS
*
*/
#ifndef REMOVE_WRITE_BUFFER_PROGRAMMING
DEVSTATUS lld_memcpy
(
FLASHDATA * base_addr, /* device base address is system */
ADDRESS offset, /* address offset from base address */
WORDCOUNT word_cnt, /* number of words to program */
FLASHDATA *data_buf /* buffer containing data to program */
)
{
ADDRESS mask = LLD_BUFFER_SIZE - 1;
WORDCOUNT intwc = word_cnt;
DEVSTATUS status = DEV_NOT_BUSY;
if (offset & mask)
{
/* program only as much as necessary, so pick the lower of the two numbers */
if (word_cnt < (LLD_BUFFER_SIZE - (offset & mask)) )
intwc = word_cnt;
else
intwc = LLD_BUFFER_SIZE - (offset & mask);
/* program the first few to get write buffer aligned */
status = lld_WriteBufferProgramOp(base_addr, offset, intwc, data_buf);
if (status != DEV_NOT_BUSY)
{
return(status);
}
offset += intwc; /* adjust pointers and counter */
word_cnt -= intwc;
data_buf += intwc;
if (word_cnt == 0)
{
return(status);
}
}
while(word_cnt >= LLD_BUFFER_SIZE) /* while big chunks to do */
{
status = lld_WriteBufferProgramOp(base_addr, offset, LLD_BUFFER_SIZE, data_buf);
if (status != DEV_NOT_BUSY)
{
return(status);
}
offset += LLD_BUFFER_SIZE; /* adjust pointers and counter */
word_cnt -= LLD_BUFFER_SIZE;
data_buf += LLD_BUFFER_SIZE;
}
if (word_cnt == 0)
{
return(status);
}
status = lld_WriteBufferProgramOp(base_addr, offset, word_cnt, data_buf);
return(status);
}
#endif
/******************************************************************************
*
* lld_ReadCfiWord - Read CFI word operation.
*
* RETURNS: word read
*
*/
#ifndef REMOVE_LLD_READ_CFI_WORD
FLASHDATA lld_ReadCfiWord
(
FLASHDATA * base_addr, /* device base address is system */
ADDRESS offset /* address offset from base address */
)
{
FLASHDATA data;
FLASH_WR(base_addr, LLD_UNLOCK_ADDR1, NOR_CFI_QUERY_CMD);
data = FLASH_RD(base_addr, offset);
lld_ResetCmd(base_addr);
return(data);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -