📄 lld.c
字号:
/*****************************************************************************/
/************************* COMMIT INCORPORATED********************************/
/************************ COPYRIGHT INFORMATION *****************************
This program contains proprietary information which is a trade secret of
COMMIT INCORPORATED and also is protected as an unpublished work under
applicable Copyright laws. Recipient is to retain this program in confidence
and is not permitted to use or make copies thereof other than as permitted
in a written agreement with COMMIT INCORPORATED.
******************************************************************************/
/*****************************************************************************
Description:bit utility
Create Date: Apr 20,2005
Department: HW. DRIVER
PROJECT: VENUS
Author: hw drivers/xuting
*****************************************************************************
History:
Date Revision By Comment
Dec 1,2004 draft
Apr 20,2005
*****************************************************************************/
/* NOTICE
MirrorBit flash devices requires 4us from the time
a programming command is issued before the data polling
bits can be read. Without the delay, it is likely
that you will read invalid status from the flash.
The invalid status may lead the software to believe
that programming finished early without problems or
that programming failed. If your system has more
than 4us of delay inherently, you don't need any
additional delay. Otherwise, change the #undef to
a #define
WAIT_4us_FOR_DATA_POLLING_BITS_TO_BECOME_ACTIVE
in lld.h. Make sure your optimization does not
remove the delay loop. You must replace DELAY_4us
with a value which makes sense for your system.
It is possible to suspend the erase operation
with such frequency that it is unable to complete
the erase operation and eventually times-out.
Change the #undef to #define PAUSE_BETWEEN_ERASE_SUSPENDS
in lld.h if you are using erase suspend and the
following is true.
Time between suspends is less that 10 milliseconds
AND total number of suspends per erase can exceed 5000.
Make sure that your optimization does not remove the
delay loop. You must replace DELAY_10ms with a value
which make sense in your system.
If you are using MirrorBit devices, change the macro
#undef MIRRORBIT_DEVICE to #define MIRRORBIT_DEVICE.
If you will be doing suspends while erasing sectors, change
the macro #undef USING_ERASE_SUSPEND to
#define USING_ERASE_SUSPEND. Upon completions of the
sector erase, check the first and last location of the sector
to verify erasure. In the event that either are not erased,
re-issue the sector erase command.
For more information, visit our web site at www.spansion.com,
email us at software@spansion.com or go to www.ask.amd.com.
*/
//#include "nucleus.h"
#include <stdio.h>
#include "lld.h"
#include "lld_hal.h"
#ifdef AMD_DRIVER_FLASH_FOR_SW
#include "ffs.h"
#include "ffstrace.h"
#include "drv.h"
#endif
/* data masks */
#define DQ0_MASK (0x01) /* select DQ0 */
#define DQ1_MASK (0x02) /* select DQ1 */
#define DQ2_MASK (0x04) /* select DQ2 */
#define DQ5_MASK (0x20) /* select DQ5 */
#define DQ6_MASK (0x40) /* select DQ6 */
#define DQ7_MASK (0x80) /* select DQ7 */
/* Address/Command Info */
#define NOR_UNLOCK_ADDR1_X8 (0x555)
#define NOR_UNLOCK_ADDR2_X8 (0x2AA)
#define NOR_UNLOCK_ADDR1_X8_X16 (0xAAA)
#define NOR_UNLOCK_ADDR2_X8_X16 (0x555)
#define NOR_UNLOCK_ADDR1_X16_X32 (0x1555)
#define NOR_UNLOCK_ADDR2_X16_X32 (0xAAA)
#if 1
#define NOR_UNLOCK_DATA1 (0xAAAAAAAA)
#define NOR_UNLOCK_DATA2 (0x55555555)
#define NOR_RESET_CMD (0xF0F0F0F0)
#define NOR_AUTOSELECT_CMD (0x90909090)
#define NOR_PROGRAM_CMD (0xA0A0A0A0)
#define NOR_ERASE_SETUP_CMD (0x80808080)
#define NOR_CHIP_ERASE_CMD (0x10101010)
#define NOR_SECTOR_ERASE_CMD (0x30303030)
#define NOR_SUSPEND_CMD (0xB0B0B0B0)
#define NOR_RESUME_CMD (0x30303030)
#define NOR_CFI_QUERY_CMD (0x98989898)
#define NOR_UNLOCK_BYPASS_ENTRY_CMD (0x20202020)
#define NOR_UNLOCK_BYPASS_PROGRAM_CMD (0xA0A0A0A0)
#define NOR_UNLOCK_BYPASS_RESET_CMD1 (0x90909090)
#define NOR_UNLOCK_BYPASS_RESET_CMD2 (0x00000000)
#define NOR_SECSI_SECTOR_ENTRY_CMD (0x88888888)
#define NOR_SECSI_SECTOR_EXIT_SETUP_CMD (0x90909090)
#define NOR_SECSI_SECTOR_EXIT_CMD (0x00000000)
#define NOR_WRITE_BUFFER_LOAD_CMD (0x25252525)
#define NOR_WRITE_BUFFER_PGM_CONFIRM_CMD (0x29292929)
#define NOR_WRITE_BUFFER_ABORT_RESET_CMD (0xF0F0F0F0)
#else
#define NOR_UNLOCK_DATA1 (0xAA)
#define NOR_UNLOCK_DATA2 (0x55)
#define NOR_RESET_CMD (0xF0)
#define NOR_AUTOSELECT_CMD (0x90)
#define NOR_PROGRAM_CMD (0xA0)
#define NOR_ERASE_SETUP_CMD (0x80)
#define NOR_CHIP_ERASE_CMD (0x10)
#define NOR_SECTOR_ERASE_CMD (0x30)
#define NOR_SUSPEND_CMD (0xB0)
#define NOR_RESUME_CMD (0x30)
#define NOR_CFI_QUERY_CMD (0x98)
#define NOR_UNLOCK_BYPASS_ENTRY_CMD (0x20)
#define NOR_UNLOCK_BYPASS_PROGRAM_CMD (0xA0)
#define NOR_UNLOCK_BYPASS_RESET_CMD1 (0x90)
#define NOR_UNLOCK_BYPASS_RESET_CMD2 (0x00)
#define NOR_SECSI_SECTOR_ENTRY_CMD (0x88)
#define NOR_SECSI_SECTOR_EXIT_SETUP_CMD (0x90)
#define NOR_SECSI_SECTOR_EXIT_CMD (0x00)
#define NOR_WRITE_BUFFER_LOAD_CMD (0x25)
#define NOR_WRITE_BUFFER_PGM_CONFIRM_CMD (0x29)
#define NOR_WRITE_BUFFER_ABORT_RESET_CMD (0xF0)
#endif
unsigned char ff[128] =
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
/* private function prototypes */
DWORD GetUnitReadMask(PARAM data_cfg);
static int UnlockAddrsInit
(
DWORD *ulock_addr1, /* first unlock address */
DWORD *ulock_addr2, /* second unlock address */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
);
static int ReadMaskInit
(
FLASHDATA *read_mask, /* variable in which to store mask */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
);
static int ToggleBit1MaskInit
(
FLASHDATA *toglbit1_mask, /* variable in which to store mask */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
);
static int ToggleBit2MaskInit
(
FLASHDATA *toglbit2_mask, /* variable in which to store mask */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
);
static int ExceedTimeLimitMaskInit
(
FLASHDATA *xcdtimelim_mask, /* variable in which to store mask */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
);
static int WrtBufAbortMaskInit
(
FLASHDATA *wrtbufabort_mask_ptr, /* variable in which to store mask */
PARAM data_cfg, /* data width, # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
);
/* Public Functions */
/******************************************************************************
*
* lld_ResetCmd - Writes a Software Reset command to the flash device
*
*
* RETURNS: LLD_OK, or LLD_ERROR
*
* ERRNO:
* errors generated by HAL functions
*/
int lld_ResetCmd
(
ADDRESS base_addr, /* device base address in system */
DWORD offset, /* address offset from base address */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
)
{
int status = LLD_OK;
/*
* Reserved for Future Use.
* Trivial assignment to prevent compiler warnings
*/
data_cfg = data_cfg;
offset = offset;
/* Write Software RESET command */
status = HalWrite(base_addr + offset, NOR_RESET_CMD, err_code_ptr, err_buf);
return(status);
}
/******************************************************************************
*
* lld_pauseWhileEraseBegins - Pauses after a sector erase command is issued.
*
* This function is used to make sure the erase gets past a critical
* point in the state machine before any erase suspends can begin (E2).
*
*
* RETURNS: LLD_OK, or LLD_ERROR
*
* ERRNO:
* errors generated by HAL functions
*/
int lld_pauseWhileEraseBegins
(
ADDRESS base_addr, /* device base address in system */
DWORD offset, /* address offset from base address */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
)
{
int status = LLD_OK;
FLASHDATA data_read = 0;
FLASHDATA read_mask = 0;
FLASHDATA dq3_mask = 0;
FLASHDATA dq4_mask = 0;
/* Initialize Masks */
status = ReadMaskInit(&read_mask, data_cfg, err_code_ptr, err_buf);
if (status != LLD_OK)
return status;
/* Use toggle bit 2 mask to create dq3 & dq4 mask */
status = ToggleBit2MaskInit(&dq3_mask, data_cfg,
err_code_ptr, err_buf);
if (status != LLD_OK)
return status;
dq3_mask <<= 1;
dq4_mask = dq3_mask << 1;
do
{
/* do a status read of the device */
status = HalRead(base_addr + offset, &data_read, err_code_ptr, err_buf);
if (status != LLD_OK)
return (status);
/* clean up data */
data_read &= read_mask;
}
while((data_read & dq3_mask) != dq3_mask); /* wait for all dq3s to go high */
do
{
/* do a status read of the device */
status = HalRead(base_addr + offset, &data_read, err_code_ptr, err_buf);
if (status != LLD_OK)
return (status);
/* clean up data */
data_read &= read_mask;
}
while((data_read & dq4_mask) != dq4_mask); /* wait for all dq4s to go high */
return (LLD_OK);
}
/******************************************************************************
*
* lld_SecErsCmd - Writes a Sector Erase Command to Flash Device
*
* This function only issues the Sector Erase Command sequence.
* Data bar polling is not implemented in this function.
*
*
* RETURNS: LLD_OK, or LLD_ERROR
*
* ERRNO:
* errors from UnlockAddrsInit
* errors generated by HAL functions
*/
int lld_SecErsCmd
(
ADDRESS base_addr, /* device base address in system */
DWORD offset, /* address offset from base address */
PARAM data_cfg, /* flash data width and # of devices */
PARAM *err_code_ptr, /* variable to store error code */
char *err_buf /* buffer to store error text */
)
{
int status = LLD_OK;
DWORD ulock_addr1;
DWORD ulock_addr2;
uint32 cpsr;
status = UnlockAddrsInit(&ulock_addr1, &ulock_addr2, data_cfg, err_code_ptr, err_buf);
if(status != LLD_OK)
return(status);
#ifdef AMD_DRIVER_FLASH_FOR_SW
cpsr = int_disable();
dev.state = DEV_ERASE;
#endif
/* Issue Sector Erase Command Sequence */
for(; ; )
/* dummy loop for "break" */
{
status = HalWrite(base_addr + ulock_addr1, NOR_UNLOCK_DATA1,
err_code_ptr, err_buf);
if(status != LLD_OK)
break;
status = HalWrite(base_addr + ulock_addr2, NOR_UNLOCK_DATA2,
err_code_ptr, err_buf);
if(status != LLD_OK)
break;
status = HalWrite(base_addr + ulock_addr1, NOR_ERASE_SETUP_CMD,
err_code_ptr, err_buf);
if(status != LLD_OK)
break;
status = HalWrite(base_addr + ulock_addr1, NOR_UNLOCK_DATA1,
err_code_ptr, err_buf);
if(status != LLD_OK)
break;
status = HalWrite(base_addr + ulock_addr2, NOR_UNLOCK_DATA2,
err_code_ptr, err_buf);
if(status != LLD_OK)
break;
/* Write Sector Erase Command to Offset */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -