📄 flashmem.c
字号:
/* flashMem.c - Flash memory device driver *//* Copyright 1984-2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01o,15feb01,frf merged latest contribution, added support for 28F128J3A, 28F320J3A, 28F640J3A and 29LV040B.01n,23mar00,zl added support for 29LV160B/T. added sysSectorErase().01m,01feb00,jpd added support for 28F320. SPR 3129301l,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.*//*DESCRIPTIONThis library contains routines to manipulate flash memory. Read and writeroutines are included.The macro values FLASH_ADRS, FLASH_SIZE, and FLASH_WIDTH must be defined toindicate the address, size (in bytes), and the data-access width (in bytes) ofthe flash memory.If the flash memory needs to be overlaid, and the section of the memory thatneeds to be overlaid is less than FLASH_SIZE, then, for efficiency, defineFLASH_SIZE_WRITABLE to the size (in bytes) of the overlay section.The routine sysFlashDelay() creates a delay for a specified number ofmicroseconds. The timing loop can be adjusted on a board-dependent basis bydefining the function sysFlashBoardDelay and values for the following macros,.iPSYS_FLASH_DELAY_SHIFT.iPSYS_FLASH_DELAY_ADJ.iPSYS_FLASH_DELAY_INCR.LPTo use the routine sysFlashBoardDelay(), the macro SYS_FLASH_BOARD_DELAYshould 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 beauto-selected. This macro should be set to a flash device code defined in theheader 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 macroSYS_FLASH_WRITE, and the routines, sysFlashWriteEnable() andsysFlashFlashWriteDisable() should be defined.INTERNAL:The FLASH_SIZE_WRITABLE concept doesn't work very well. It just limits theamount of flash that is writable, so why bother. What it was reallyintended to address was flash that is only block writable, i.e. youcan only write a complete block at a time. To properly handle blockmemory, you must copy the old block of memory to a buffer, update thepart of the buffer that is to be changed, and then write back thecomplete buffer in a single write operation.The accesses to non-volatile memory, and flash control registers needsto be abstracted. Macros should be used for all actual i/o operations.*/#include "drv/mem/flashDev.h"#include "drv/mem/flash28.h"#include "drv/mem/flash29.h"/* defines *//* 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 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 *//* globals */IMPORT void sysFlashWriteEnable (void);IMPORT void sysFlashWriteDisable (void);IMPORT void sysFlashBoardDelay (void);int flashDelayShift = SYS_FLASH_DELAY_SHIFT;int flashDelayAdj = SYS_FLASH_DELAY_ADJ;int flashDelayIncr = SYS_FLASH_DELAY_INCR;static UINT8 flashType = FLASH_MEM_TYPE;/* forward declarations */void sysFlashDelay (int delayCount);STATUS sysFlashDataPoll (volatile FLASH_DEF * pFA, FLASH_DEF value);STATUS sysFlashWrite (FLASH_DEF * pFB, int size, int offset, UINT8 flashType, FLASH_DEF value);STATUS sysFlashUnlock ( FLASH_DEF * pFA, UINT8 flashType);STATUS sysFlashLock(FLASH_DEF * pFA, UINT8 flashType);UINT8 sysFlashTypeGet (void);STATUS sysFlashNextBlock(UINT32 * flash_offset);/******************************************************************************** sysFlashGet - get the contents of flash memory** This routine copies the contents of flash memory into a specified* string. The string is terminated with an EOS.** RETURNS: OK, or ERROR if access is outside the flash memory range.** SEE ALSO: sysFlashSet()** INTERNAL* If multiple tasks are calling sysFlashSet() and sysFlashGet(),* they should use a semaphore to ensure mutually exclusive access.*/STATUS sysFlashGet ( char * string, /* where to copy flash memory */ int strLen, /* maximum number of bytes to copy */ int offset /* byte offset into flash memory */ ) { if ((offset < 0) || (strLen < 0) || ((offset + strLen) > (FLASH_ADRS + FLASH_SIZE))) return (ERROR); bcopyBytes ((char *) (offset), string, strLen); string [strLen] = EOS; return (OK); }/******************************************************************************** sysFlashDelay - create a delay for a specified number of microseconds** This routine implements a busy wait for a specified number of microseconds.* The timing loop can be adjusted on a board-dependent basis by* defining values for the following macros:* .iP* SYS_FLASH_DELAY_SHIFT* .iP* SYS_FLASH_DELAY_ADJ* .iP* SYS_FLASH_DELAY_INCR* .LP* The values SYS_FLASH_DELAY_SHIFT and SYS_FLASH_DELAY_ADJ* convert microseconds into a board-dependent tick-count.* This routine can call a user-defined hook, sysFlashBoardDelay(),* which creates a delay for a number of board-dependent ticks as* specified by SYS_FLASH_DELAY_INCR. To use sysFlashBoardDelay(), define* SYS_FLASH_BOARD_DELAY in config.h.** RETURNS: N/A** SEE ALSO: sysFlashErase(), sysFlashWrite()*/void sysFlashDelay ( int delayCount /* number of uSec to delay */ ) { int ix; delayCount <<= flashDelayShift; /* board-dependent shift */ delayCount += flashDelayAdj; /* board-dependent addition */ for (ix = 0; ix < delayCount; ix += flashDelayIncr) SYS_FLASH_BOARD_DELAY_RTN (); }/******************************************************************************** sysFlashDataPoll - wait for a flash device operation to complete** This routine polls a specified address on a 29F\f2xxx\f1 flash device* until the device operation at that location completes or times out.** While a flash operation is in progress, a read on the device* returns on Q7 (data bit 7) the complement of the previous value of Q7. Once* the flash operation has completed, the Q7 bit returns the true data* of the last write. Subsequent reads return the correct data in Q0-7.** The Q5 bit implements a timeout functionality. When a currently* executing flash operation exceeds specified limits, the Q5 bit is set (to 1).** RETURNS: OK, or ERROR if the timeout (!Q5) occurs before the device operation* completes.** SEE ALSO: sysFlashErase(), sysFlashWrite()*/STATUS sysFlashDataPoll ( volatile FLASH_DEF * pFA, /* programmed address to poll */ FLASH_DEF value /* data programmed to poll address */ ) { STATUS retVal = OK; volatile FLASH_POLL_DEF * pTest = (FLASH_POLL_DEF *) pFA; volatile FLASH_POLL_DEF * pVal = (FLASH_POLL_DEF *) &value; int ix; /* byte counter */ int vBit; /* programmed value of DQ7 */ for (ix = (FLASH_WIDTH/FLASH_CHIP_WIDTH - 1); (ix >= 0 ) && (retVal == OK); ix--, pTest++, pVal++) { vBit = Q7(*pVal); while (Q7(*pTest) != vBit) if (Q5(*pTest) == 1) /* timeout ? */ break; if (Q7(*pTest) != vBit) /* check Q7 & Q5 race */ retVal = ERROR; } return (retVal); }/******************************************************************************** sysFlashErase - erase the contents of a sector** This routine clears the contents of one sector in the flash memory.** Flash 29F\f2xxx\f1 devices are erased by writing the six-byte erase code* into specific address locations, which sets all byte locations to a high* value (0xFF).** RETURNS: OK, or ERROR if the contents of sector cannot be erased.*/STATUS sysFlashErase ( FLASH_DEF * pFA, /* Sector start address */ UINT8 flashType /* type of flash memory on-board */ ) { STATUS retVal = OK; switch (flashType) { case (FLASH_28F640J3A): case (FLASH_28F320J3A): case (FLASH_28F128J3A): SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */ *pFA = FLASH28_CMD_ERASE_SETUP; /* setup */ *pFA = FLASH28F008_CMD_ERASE; /* erase */ /* Check Write State Machine Status */ do { } while ((*pFA & FLASH28F008_STAT_WSMS) != FLASH28F008_STAT_WSMS); /* Check Erase Error Status */ if (*pFA & (BIT(5) | BIT(4) | BIT(3) | BIT(1))) { *pFA = FLASH28F008_CMD_CLEAR_STATUS; retVal = ERROR; } *pFA = FLASH28_CMD_RESET; SYS_FLASH_WRITE_DISABLE_RTN (); /* lower Vpp */ break; case (FLASH_29LV160T): case (FLASH_29LV160B): case (FLASH_29LV040B): SYS_FLASH_WRITE_ENABLE_RTN (); /* enable write */ *(FLASH_CAST FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_FIRST; *(FLASH_CAST FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND; *(FLASH_CAST FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_CHIP_ERASE; *(FLASH_CAST FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_FOURTH; *(FLASH_CAST FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_FIFTH; *pFA = FLASH29_CMD_SECTOR; do { retVal = sysFlashDataPoll (pFA, (FLASH_DEF) 0xffffffff); } while ((*pFA != (FLASH_DEF) 0xffffffff) && (retVal == OK)); SYS_FLASH_WRITE_DISABLE_RTN (); /* disable write */ break; default: retVal = ERROR; } return (retVal); }/******************************************************************************** sysFlashWrite - write data to flash memory** This routine copies specified data of a specified length, <size>, into a* specified offset, <offset>, in the flash memory. Data is passed as a string,* <pFB>, if not NULL. If NULL, data is taken as a repeated sequence of* <value>.* The parameter <flashType> should be set to the flash device code.* The parameter <offset> must be appropriately aligned for the width of* the Flash devices in use.** Flash 28F\f2xxx\f1 devices are programmed by a sequence of operations:* .iP* set up device to write* .iP* perform write* .iP* verify the write* .LP** Flash 29F\f2xxx\f1 devices are programmed by a sequence of operations:* .iP* set up device to write* .iP* perform write* .iP* wait for the write to complete* .LP** RETURNS: OK, or ERROR if the write operation fails.** SEE ALSO: sysFlashSet()*/STATUS sysFlashWrite ( FLASH_DEF * pFB, /* string to be copied; use <value> if NULL */ int size, /* size to program in bytes */ int offset, /* byte offset into flash memory */ UINT8 flashType, /* type of flash memory on-board */ FLASH_DEF value /* value to program */ ) { volatile FLASH_DEF * pFA; /* flash address */ STATUS retVal = OK; int ix; int sectorSize = 128; int twc = 2; /* time for write completion */ switch (flashType) { case (FLASH_28F008): case (FLASH_28F016): case (FLASH_28F160): case (FLASH_28F320): SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */ for (pFA = FLASH_CAST (offset); (pFA < FLASH_CAST (size + offset)) && (retVal == OK); pFA++) { if (pFB != NULL) value = *pFB++; *pFA = FLASH28_CMD_PROG_SETUP; /* write setup */ *pFA = value; /* data to write */ /* Check Write State Machine Status */ do { *pFA = FLASH28F008_CMD_READ_STATUS; } while ((*pFA & FLASH28F008_STAT_WSMS) != FLASH28F008_STAT_WSMS); /* Check Byte Write Error Status */ if (*pFA & (BIT(5) | BIT(4) | BIT(3) | BIT(1))) { *pFA = FLASH28F008_CMD_CLEAR_STATUS; retVal = ERROR; } } *pFA = FLASH28_CMD_RESET; SYS_FLASH_WRITE_DISABLE_RTN (); /* lower Vpp */ break; case (FLASH_28F320J3A): case (FLASH_28F640J3A): case (FLASH_28F128J3A): SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */ for ( pFA = FLASH_CAST (offset); (pFA <FLASH_CAST (size + offset)) && (retVal == OK); pFA++) { if (pFB != NULL) value = *pFB++; *pFA = FLASH28_CMD_PROG_SETUP; /* write setup */ *pFA = value; /* data to write */ /* Check Write State Machine Status */ do { } while ((*pFA & FLASH28F008_STAT_WSMS) != FLASH28F008_STAT_WSMS); /* Check Byte Write Error Status */ if (*pFA & (BIT(5) | BIT(4) | BIT(3) | BIT(1))) { *pFA = FLASH28F008_CMD_CLEAR_STATUS; retVal = ERROR; } *pFA = FLASH28_CMD_RESET; } SYS_FLASH_WRITE_DISABLE_RTN (); /* lower Vpp */ break; case (FLASH_28F256): case (FLASH_28F512): case (FLASH_28F010): case (FLASH_28F020): { SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -