📄 flashamdmem.c
字号:
/* flashAmdMem.c - AMD AM29LV033 Flash memory device driver */
/* Copyright 1984-2000 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
V1.09:---------------------------------------------------------------------
05/13/2004 pcd
1. modify to support ks8695 board with AMD AM29LV033 flash memory .
---------------------------------------------------------------------
01m,01feb00,jpd added support for 28F320. SPR 31293
01l,09sep98,jpd added support for 28F016SV; minor doc fixes.
01k,20apr98,jpd moved back into main source tree from local copy in BSPs.
01j,24mar98,jpd added support for 29LV1024 and 29C040A.
01i,04jul97,jpd added support for 28F008 device, made overlay buffer dynamic.
01h,25jun96,map added documentation, and some clean up.
01g,02apr96,tam cast FLASH_ADRS and FLASH_SIZE to UINT32 to get rid off
a compiler warning.
01f,12feb96,kkk made 1st param of sysFlashDataPoll() volatile to confirm
to dzb's change.
01e,26jan96,dzb added volatile to register pointers.
+jpb changed delay parameters to be globals if not defined.
01d,24feb94,dzb added sysFlashWrite{En,Dis}able(), sysFlashBoardDelay().
01c,15feb94,dzb added SYS_FLASH_DELAY_SHIFT macro.
01b,07jan94,dzb added support for 29F0X0 flash devices.
cut ties to NVRAM macros. added support for FLASH_WIDTH.
01a,05oct93,dzb derived from version 1b of mem/iFlashMem.c.
*/
/*
DESCRIPTION
This library contains routines to manipulate flash memory. Read and write
routines are included.
The macro values FLASH_ADRS, FLASH_SIZE, and FLASH_WIDTH must be defined to
indicate the address, size (in bytes), and the data-access width (in bytes) of
the flash memory.
If the flash memory needs to be overlaid, and the section of the memory that
needs to be overlaid is less than FLASH_SIZE, then, for efficiency, define
FLASH_SIZE_WRITABLE to the size (in bytes) of the overlay section.
The routine sysFlashDelay() creates a delay for a specified number of
microseconds. The timing loop can be adjusted on a board-dependent basis by
defining the function sysFlashBoardDelay and values for the following macros,
.iP
SYS_FLASH_DELAY_SHIFT
.iP
SYS_FLASH_DELAY_ADJ
.iP
SYS_FLASH_DELAY_INCR
.LP
To use the routine sysFlashBoardDelay(), the macro SYS_FLASH_BOARD_DELAY
should be defined.
The macro FLASH_NO_OVERLAY should be defined when calls to sysFlashSet()
are expected to erase the flash and reprogram it with only the new data.
The macro SYS_FLASH_TYPE should be defined for flash devices that cannot be
auto-selected. This macro should be set to a flash device code defined in the
header files, <drv/mem/flash28.h> and <drv/mem/flash29.h>
To support flash devices that that need to turn on/off write protect features
(special programming voltages or other write-enable features), the macro
SYS_FLASH_WRITE, and the routines, sysFlashWriteEnable() and
sysFlashFlashWriteDisable() should be defined.
INTERNAL:
The FLASH_SIZE_WRITABLE concept doesn't work very well. It just limits the
amount of flash that is writable, so why bother. What it was really
intended to address was flash that is only block writable, i.e. you
can only write a complete block at a time. To properly handle block
memory, you must copy the old block of memory to a buffer, update the
part of the buffer that is to be changed, and then write back the
complete buffer in a single write operation.
The accesses to non-volatile memory, and flash control registers needs
to be abstracted. Macros should be used for all actual i/o operations.
*/
#include "types.h"
#include "vxWorks.h"
#include "string.h"
#include "stdio.h"
#include "config.h"
#include "drv/mem/flashDev.h"
#include "drv/mem/flash29.h"
#include "flash28.h"
#include "flashMem.h"
/* defines */
/* Driver debug control */
#define DRV_DEBUGFLASH
/* Driver debug control */
#ifdef DRV_DEBUGFLASH
#define FLASHAMD_DEBUG_OFF 0x0000
#define FLASHAMD_DEBUG_ERROR 0x0001
#define FLASHAMD_DEBUG_WRITE 0x0002
#define FLASHAMD_DEBUG_READ 0x0004
#define FLASHAMD_DEBUG_ERASE 0x0008
#define FLASHAMD_DEBUG_TYPEGET 0x0010
#define FLASHAMD_DEBUG_TEST 0x0020
#define FLASHAMD_DEBUG_ALL 0xffff
LOCAL int flashDebug = ( FLASHAMD_DEBUG_ERROR /*| FLASHAMD_DEBUG_WRITE */ );
#define FA_DRV_PRINT(FLG, X) \
do { \
if (flashDebug & FLG) \
printf X; \
} while (0)
#else /* DRV_DEBUGFLASH */
#define FA_DRV_PRINT(FLG, X)
#endif /* DRV_DEBUGFLASH */
/* Establish default values for DELAY parameters */
#ifndef SYS_FLASH_DELAY_SHIFT
# define SYS_FLASH_DELAY_SHIFT 0
#endif /*SYS_FLASH_DELAY_SHIFT*/
#ifndef SYS_FLASH_DELAY_ADJ
# define SYS_FLASH_DELAY_ADJ 0
#endif /* SYS_FLASH_DELAY_ADJ */
#ifndef SYS_FLASH_DELAY_INCR
# define SYS_FLASH_DELAY_INCR 1
#endif /* SYS_FLASH_DELAY_INCR */
/* Names of routines, or null values */
#ifdef SYS_FLASH_WRITE
#define CSO_WRITE_PROTECT_BIT 0x10001000
# define SYS_FLASH_WRITE_ENABLE_RTN() sysFlashWriteEnable ()
# define SYS_FLASH_WRITE_DISABLE_RTN() sysFlashWriteDisable ()
#else
# define SYS_FLASH_WRITE_ENABLE_RTN()
# define SYS_FLASH_WRITE_DISABLE_RTN()
#endif /* SYS_FLASH_WRITE */
#ifdef SYS_FLASH_BOARD_DELAY
# define SYS_FLASH_BOARD_DELAY_RTN() sysFlashBoardDelay ()
#else
# define SYS_FLASH_BOARD_DELAY_RTN()
#endif /* SYS_FLASH_BOARD_DELAY */
#ifdef SYS_FLASH_TYPE
# define FLASH_MEM_TYPE SYS_FLASH_TYPE
#else
# define FLASH_MEM_TYPE 0
#endif /* SYS_FLASH_TYPE */
#ifdef FLASH_SIZE_WRITEABLE
# define FLASH_MEM_SIZE FLASH_SIZE_WRITEABLE
#else
# define FLASH_MEM_SIZE FLASH_SIZE
#endif /* FLASH_SIZE_WRITEABLE */
/* Operation status bits for Flash 29Fxxx devices */
#define Q7(ix) ((ix & 0x80) >> 7) /* DQ7 bit */
#define Q5(ix) ((ix & 0x20) >> 5) /* DQ5 bit */
int flashdelaycount=10;
/* These index must align with the data in flashCmdArray, below.
*/
typedef enum {
OP_0x30 = 0,
OP_0x55,
OP_0x80,
OP_0xA0,
OP_0xAA,
OP_0x20,
OP_MAX
} FLASH_COMMAND_WORD_SELECT;
static long flashCmdArray[ 4 ][ OP_MAX ] = {
{0xF0F0F030, 0xF0F0F055, 0xF0F0F080, 0xF0F0F0A0, 0xF0F0F0AA, 0xF0F0F020},
{0xF0F030F0, 0xF0F055F0, 0xF0F080F0, 0xF0F0A0F0, 0xF0F0AAF0, 0xF0F020F0},
{0xF030F0F0, 0xF055F0F0, 0xF080F0F0, 0xF0A0F0F0, 0xF0AAF0F0, 0xF020F0F0},
{0x30F0F0F0, 0x55F0F0F0, 0x80F0F0F0, 0xA0F0F0F0, 0xAAF0F0F0, 0x20F0F0F0},
};
/* globals */
IMPORT void sysFlashDelay (int);
IMPORT void sysFlashBoardDelay (void);
IMPORT STATUS sysFlashDataPoll ( FLASH_DEF *, FLASH_DEF );
IMPORT int flashEraseSector(int);
/* forward declarations */
void AmdflashReadReset();
int AmdflashEraseDevice(FLASH_DEF *, int);
int AmdflashWrite(int, char *, unsigned int, unsigned int);
LOCAL int AmdflashProgramLong(FLASH_DEF *, FLASH_DEF );
LOCAL int AmdflashProgramDevice(FLASH_DEF *, FLASH_DEF, int);
void flashTest (FLASH_DEF value, int offset);
int AmdflashEraseDevice( FLASH_DEF *sectorBasePtr, int device )
{
int i=0;
STATUS retVal = OK;
/* Write Erase Command Sequence */
*FLASH_5555H_PTR = flashCmdArray[ device ][ OP_0xAA ];
*FLASH_2AAAH_PTR = flashCmdArray[ device ][ OP_0x55 ];
*FLASH_5555H_PTR = flashCmdArray[ device ][ OP_0x80 ];
*FLASH_5555H_PTR = flashCmdArray[ device ][ OP_0xAA ];
*FLASH_2AAAH_PTR = flashCmdArray[ device ][ OP_0x55 ];
*sectorBasePtr = flashCmdArray[ device ][ OP_0x30 ];
/* Verify Data from Erasing Sector with FFh */
do
{
retVal = sysFlashDataPoll (sectorBasePtr, (FLASH_DEF) 0xffffffff);
} while ( (*sectorBasePtr != (FLASH_DEF) 0xffffffff) && (retVal == OK) && (i++<FLASH_ERASE_TIMEOUT_COUNT) );
/* put flash back to read mode */
AmdflashReadReset();
FA_DRV_PRINT ( FLASHAMD_DEBUG_ERASE,
("AmdflashEraseDevice(): device %d erased ok, flashAddr 0x%08X\n", (int)device, (int)sectorBasePtr ));
return (retVal);
}
int AmdflashWrite
(
int sectorNum,
char *buff,
unsigned int offset,
unsigned int count
)
{
volatile FLASH_DEF * flashBuffPtr ; /* flash address */
FLASH_DEF * curBuffPtr ; /* string to be programed */
int writeCount , i ;
STATUS retVal = OK;
/* Program (count / sizeof(long)) long words into Flash.
*/
curBuffPtr = (FLASH_DEF *)buff;
writeCount = (count / sizeof( FLASH_DEF ));
flashBuffPtr = (FLASH_DEF *)(FLASH_BASE_ADDRESS + (sectorNum * FLASH_BANK_SECTOR_SIZE) + offset);
FA_DRV_PRINT (FLASHAMD_DEBUG_WRITE,
("AmdflashWrite(): sectorNum %d, offset %d, writeCount %d, flashAddr 0x%08X\n",
sectorNum, offset, writeCount, (int)flashBuffPtr));
for( i = 0; i < writeCount; i++ )
{
if ( retVal = (STATUS)AmdflashProgramLong( flashBuffPtr, *curBuffPtr ) == ERROR )
{
FA_DRV_PRINT (FLASHAMD_DEBUG_ERROR,
("AmdflashWrite(): Failed: Sector %d, flashAddress 0x%08X, dataBuf 0x%08X=0x%02x \n",
sectorNum, (int)flashBuffPtr, (int)curBuffPtr, *curBuffPtr));
break;
}
else
{
/* print out '.' every 64K(one sector) words */
/* if((((unsigned int)flashBuffPtr) % 0x40000) == 0) */
/* printf("."); */
flashBuffPtr++;
curBuffPtr++;
}
}
/* put flash back to read mode
*/
AmdflashReadReset();
return( retVal );
}
LOCAL int AmdflashProgramLong
(
FLASH_DEF *addr,
FLASH_DEF val
)
{
int device;
for( device = 0; device < FLASH_BANK_WIDTH; device++ )
{
if( AmdflashProgramDevice( addr, val, device) == ERROR )
{
FA_DRV_PRINT (FLASHAMD_DEBUG_ERROR,
("AmdflashProgramLong(): device %d failed, flashAddr 0x%08X programed with dataBuf 0x%x\n",
device, (int)addr, val));
return( ERROR );
}
}
return( OK );
}
LOCAL int AmdflashProgramDevice
(
FLASH_DEF *addr,
FLASH_DEF value,
int device
)
{
int i=0;
STATUS retVal = OK;
/* Write Program Command Sequence */
*FLASH_5555H_PTR = flashCmdArray[ device ][ OP_0xAA ];
*FLASH_2AAAH_PTR = flashCmdArray[ device ][ OP_0x55 ];
*FLASH_5555H_PTR = flashCmdArray[ device ][ OP_0xA0 ];
/* Program Data (dataBuf) to flash address (addr) */
*addr = value;
/* Verify - Data read compare with Data wrote */
do
{
retVal = sysFlashDataPoll (addr, (FLASH_DEF) value);
} while ( (*addr != value) && (retVal == OK) && (i++<FLASH_ERASE_TIMEOUT_COUNT) );
return (retVal);
}
void AmdflashReadReset()
{
*FLASH_5555H_PTR = FLASH29_CMD_FIRST;
*FLASH_2AAAH_PTR = FLASH29_CMD_SECOND;
*FLASH_5555H_PTR = FLASH29_CMD_READ_RESET;
}
void flashTest
(
FLASH_DEF value, /* value to program */
int sectorOffset /* sector offset into flash memory */
)
{
static FLASH_DEF str[256];
STATUS status;
FA_DRV_PRINT (FLASHAMD_DEBUG_TEST,
("flashTest(): value 0x%X, sectorOffset %d \n", value, sectorOffset));
memset (str, value, sizeof(str));
if( flashEraseSector( sectorOffset ) == ERROR )
return;
status = AmdflashWrite ( sectorOffset, str, 0, 16 );
if (status == ERROR)
FA_DRV_PRINT (FLASHAMD_DEBUG_ERROR,
("program data 0x%x to flash sector offset %08x fail\n", value, sectorOffset));
else
FA_DRV_PRINT (FLASHAMD_DEBUG_TEST,
("program data 0x%x to flash sector offset %08x OK\n", value, sectorOffset));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -