?? flashmem.c
字號:
/* flashMem.c - Flash memory device driver *//* Copyright 1984-2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01p,10jan02,m_h fix NVRAM01o,23feb00,jpd comments changes.01n,21feb00,jpd added INCLUDE_FLASH_SIB_FOOTER handling.01m,01feb00,jpd added support for 28F320.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.*//*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 "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 */#ifdef INCLUDE_FLASH_SIB_FOOTER#define TYPE_DELETED 0xFFFFFFFF#define TYPE_CUSTOM_MASK 0xFFFF0000#define TYPE_WRS_SIB 0x00010000#define SIB_HEADER_SIGNATURE 0xA00FFF9F /* This is an invalid instruction */#define FLASH_FOOTER_SIGNATURE 0xA0FFFF9F /* This is an invalid instruction */#define FLASH_BLOCK_SIZE SZ_128Ktypedef struct footerType { void * infoBase; /* Address of first word of ImageFooter */ char * blockBase; /* Start of area reserved by this footer */ UINT32 signature; /* 'Magic' number proves it's a footer */ UINT32 type; /* Area type: ARM Image, SIB, customer */ UINT32 checksum; /* Just this structure */ } FOOTER;#endif /* INCLUDE_FLASH_SIB_FOOTER *//* 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;/* forward declarations */#ifdef __STDC__void sysFlashDelay (int delayCount);STATUS sysFlashDataPoll (volatile FLASH_DEF * pFA, FLASH_DEF value);STATUS sysFlashErase (UINT8 flashType);STATUS sysFlashWrite (FLASH_DEF * pFB, int size, int offset, UINT8 flashType, FLASH_DEF value);UINT8 sysFlashTypeGet (void);#else /* __STDC__ */void sysFlashDelay ();STATUS sysFlashDataPoll ();STATUS sysFlashErase ();STATUS sysFlashWrite ();UINT8 sysFlashTypeGet ();#endif /* __STDC__ *//******************************************************************************** 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_SIZE)) return (ERROR); bcopyBytes ((char *) (FLASH_ADRS + 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 flash memory** This routine clears the contents of flash memory.** Flash 28F\f2xxx\f1 devices are erased by writing a flash erase command to* the device and verifying that each flash location is set to a high value* (0xFF).** 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 flash memory cannot be erased.*/STATUS sysFlashErase ( UINT8 flashType /* type of flash memory on-board */ ) { volatile FLASH_DEF * pFA = FLASH_CAST (FLASH_ADRS); STATUS retVal = OK; int ix; switch (flashType) { case (FLASH_28F008): case (FLASH_28F016): case (FLASH_28F160): case (FLASH_28F320): SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */ *pFA = FLASH28_CMD_ERASE_SETUP; /* setup */ *pFA = FLASH28F008_CMD_ERASE; /* erase */ /* Check Write State Machine Status */ do *pFA = FLASH28F008_CMD_READ_STATUS; while ((*pFA & FLASH28F008_STAT_WSMS) != FLASH28F008_STAT_WSMS); sysFlashDelay (6); /* Check Erase Error Status */ if ((*pFA & FLASH28F008_STAT_EWS) != 0) { *pFA = FLASH28F008_CMD_CLEAR_STATUS; retVal = ERROR; } pFA = FLASH_CAST (FLASH_ADRS); *pFA = FLASH28_CMD_RESET; SYS_FLASH_WRITE_DISABLE_RTN (); /* lower Vpp */ break; case (FLASH_28F256): case (FLASH_28F512): case (FLASH_28F010): case (FLASH_28F020): { /* program the device to all zeros */ if (sysFlashWrite (NULL, FLASH_SIZE, 0, flashType, 0) == ERROR) return (ERROR); SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */ *pFA = FLASH28_CMD_ERASE_SETUP; /* setup */ *pFA = FLASH28_CMD_ERASE; /* erase */ sysFlashDelay (10000); for (; (pFA < FLASH_CAST ((UINT32)FLASH_ADRS + (UINT32)FLASH_SIZE)) && (retVal == OK); pFA++) for (ix = 0; TRUE; ix++) { *pFA = FLASH28_CMD_ERASE_VERIFY; /* verify */ sysFlashDelay (6); /* wait for verify */ if (*pFA == (FLASH_DEF) 0xffffffff) /* done? */ break; if (ix == 1000) { retVal = ERROR; break; } *pFA = FLASH28_CMD_ERASE_SETUP; /* setup */ *pFA = FLASH28_CMD_ERASE; /* erase */ sysFlashDelay (10000); } pFA = FLASH_CAST (FLASH_ADRS); *pFA = FLASH28_CMD_RESET; *pFA = FLASH28_CMD_READ_MEM; sysFlashDelay (6); SYS_FLASH_WRITE_DISABLE_RTN (); /* lower Vpp */ break; } case (FLASH_29F010): { 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; *(FLASH_CAST FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_SIXTH; do { retVal = sysFlashDataPoll (pFA, (FLASH_DEF) 0xffffffff); } while ((*pFA != (FLASH_DEF) 0xffffffff) && (retVal == OK)); *(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_READ_RESET; SYS_FLASH_WRITE_DISABLE_RTN (); /* disable enable */ break; } case (FLASH_29C040A): case (FLASH_29LV1024): /* * You can erase these entire chips, but there is really no * need, as a write automatically erases the sector being * written. In particular, we will not generally want all * of the chip erased from sysFlashSet(). */ { *(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; *(FLASH_CAST FLASH29_REG_FIRST_CYCLE) = FLASH29_CMD_SIXTH; /* * Atmel chip spec says it will take 20 ms max and does not * define a mechanism for polling for completion * * It seems that this driver cannot always safely use taskDelay() */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -