📄 flashmem.c
字号:
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 (FLASH_ADRS + offset); (pFA < FLASH_CAST
(FLASH_ADRS + 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);
sysFlashDelay (6);
/* Check Byte Write Error Status */
if ((*pFA & FLASH28F008_STAT_BWS) != 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):
{
SYS_FLASH_WRITE_ENABLE_RTN (); /* raise Vpp */
for (pFA = FLASH_CAST (FLASH_ADRS + offset); (pFA < FLASH_CAST
(FLASH_ADRS + size + offset)) && (retVal == OK); pFA++)
for (ix = 0; TRUE; ix++)
{
if (pFB != NULL)
value = *pFB++;
*pFA = FLASH28_CMD_PROG_SETUP; /* write setup */
*pFA = value; /* data to write */
sysFlashDelay (10); /* wait for write */
*pFA = FLASH28_CMD_PROG_VERIFY; /* verify command */
sysFlashDelay (6); /* wait for verify */
if (*pFA == value) /* done? */
break;
if (ix == 25) /* error? */
{
retVal = ERROR;
break;
}
}
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 */
for (pFA = FLASH_CAST (FLASH_ADRS + offset); pFA < FLASH_CAST
(FLASH_ADRS + size + offset) && (retVal == OK); pFA++)
{
*(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_PROGRAM;
if (pFB != NULL)
value = *pFB++;
*pFA = value; /* data to write */
do {
retVal = sysFlashDataPoll (pFA, (FLASH_DEF) value);
} while ((*pFA != value) && (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 write */
break;
}
case (FLASH_29C040A):
sectorSize = 256;
twc = 1;
/* FALL THROUGH */
case (FLASH_29LV1024):
{
for (pFA = FLASH_CAST (FLASH_ADRS + offset);
pFA < FLASH_CAST (FLASH_ADRS + size + offset); )
{
/* Enable sector 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_PROGRAM;
/*
* write the sector:
* 29LV1024: 128 half-word accesses = 256 bytes
* 29C040A 256 byte accesses
*/
for (ix = 0; ix < sectorSize; ix++)
{
if (pFB != NULL)
value = *pFB++;
/* ensure entire sector written */
if (pFA >= FLASH_CAST (FLASH_ADRS + size + offset))
value = (FLASH_DEF) 0xFFFFFFFF;
*pFA++ = value; /* data to write */
}
/*
* Ensure write cycle completes. Atmel chip spec suggest
* waiting for a specified time rather than polling for
* completion.
*
* It seems that we cannot always safely use taskDelay()
*/
sysFlashDelay (10000 * twc);
}
break;
}
case (FLASH_29LV033):
{
for (pFA = FLASH_CAST (FLASH_ADRS + offset); pFA < FLASH_CAST
(FLASH_ADRS + size + offset) && (retVal == OK); pFA++)
{
*(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_PROGRAM;
if (pFB != NULL)
value = *pFB++;
*pFA = value; /* data to write */
do {
retVal = sysFlashDataPoll (pFA, (FLASH_DEF) value);
} while ((*pFA != value) && (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;
break;
}
default:
retVal = ERROR;
}
return (retVal);
}
/******************************************************************************
*
* sysFlashTypeGet - determine the device type of on-board flash memory
*
* This routine uses the `autoselect' command to determine the device type of
* on-board flash memory for flash 29F\f2xxx\f1 devices.
*
* RETURNS: An integer indicating the device type of on-board flash memory.
*/
UINT8 sysFlashTypeGet (void)
{
volatile FLASH_DEF * pFA = FLASH_CAST (FLASH_ADRS); /* flash address */
UINT8 retVal;
SYS_FLASH_WRITE_ENABLE_RTN (); /* enable writes */
*(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_AUTOSELECT;
/* 29LV1024 (at least) requires 20ms delay */
/* It seems we cannot always safely use taskDelay() */
sysFlashDelay (20000);
retVal = (UINT8) *++pFA;
*(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;
sysFlashDelay (20000);
SYS_FLASH_WRITE_DISABLE_RTN (); /* disable writes */
return (retVal);
}
#ifdef INCLUDE_FLASH_SIB_FOOTER
/******************************************************************************
*
* footerChecksum - calculate the footer checksum.
*
* This function calculates the checksum for a footer.
*
* RETURNS: The checksum
*/
static UINT32 footerChecksum
(
FOOTER * footer
)
{
UINT32 checksum;
UINT32 * ptr;
int size;
UINT32 word;
checksum = 0;
size = sizeof (FOOTER);
ptr = (UINT32 *)footer;
while (size > 0)
{
word = *ptr++;
if (word > ~checksum)
checksum++;
checksum += word;
size -= sizeof (word);
}
return ~checksum;
}
/******************************************************************************
*
* sysFlashWriteFooter - write footer to flash memory
*
* This routine initializes and writes a footer to the block defined by
* FLASH_ADRS so that this block can be seen from other utilities.
*
* RETURNS: OK or ERROR
*/
STATUS sysFlashWriteFooter
(
int flashType
)
{
FOOTER footer;
FOOTER * current;
UINT32 writeOffset;
/* Build a flash footer to describe this area. */
footer.blockBase = (char *)FLASH_ADRS;
footer.infoBase = NULL;
footer.type = TYPE_WRS_SIB;
footer.signature = FLASH_FOOTER_SIGNATURE;
footer.checksum = 0;
footer.checksum = footerChecksum (&footer);
current = (FOOTER *)(FLASH_ADRS + FLASH_BLOCK_SIZE - sizeof (FOOTER));
if (current->type == TYPE_WRS_SIB)
return OK;
writeOffset = FLASH_BLOCK_SIZE - sizeof (FOOTER);
if (flashType == 0)
flashType = sysFlashTypeGet ();
if (sysFlashWrite(FLASH_CAST(&footer), sizeof(FOOTER),
writeOffset,
flashType, 0) != OK)
return ERROR;
return OK;
}
#endif /* INCLUDE_FLASH_SIB_FOOTER */
/******************************************************************************
*
* sysFlashSet - write to flash memory
*
* This routine copies a specified string into flash memory after calling
* sysFlashErase() and clearing flash memory.
*
* If FLASH_NO_OVERLAY is defined, the parameter <offset> must be
* appropriately aligned for the Flash devices in use (device width,
* sector size etc.).
*
* If the specified string must be overlaid on the contents of flash memory,
* undefine FLASH_NO_OVERLAY.
*
* RETURNS: OK, or ERROR if the write fails or the input parameters are
* out of range.
*
* SEE ALSO: sysFlashErase(), sysFlashGet(), sysFlashTypeGet(), sysFlashWrite()
*
* INTERNAL
* If multiple tasks are calling sysFlashSet() and sysFlashGet(),
* they should use a semaphore to ensure mutually exclusive access to flash
* memory.
*/
STATUS sysFlashSet
(
char * string, /* string to be copied into flash memory */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into flash memory */
)
{
static UINT8 flashType = FLASH_MEM_TYPE;
#ifndef FLASH_NO_OVERLAY
char *tempBuffer;
#endif /* FLASH_NO_OVERLAY */
if ((offset < 0) || (strLen < 0) || ((offset + strLen) > FLASH_MEM_SIZE))
return (ERROR);
/* see if contents are actually changing */
if (bcmp ((char *) (FLASH_ADRS + offset), string, strLen) == 0)
return (OK);
#ifndef FLASH_NO_OVERLAY
/* first read existing data */
if (tempBuffer = malloc(FLASH_MEM_SIZE), tempBuffer == 0)
return (ERROR);
bcopyBytes ((char *) FLASH_ADRS, tempBuffer, FLASH_MEM_SIZE);
bcopyBytes (string, (tempBuffer + offset), strLen);
#endif /* FLASH_NO_OVERLAY */
if (flashType == 0)
flashType = sysFlashTypeGet ();
switch (flashType)
{
case FLASH_29C040A:
case FLASH_29LV1024:
/* do not erase these as not required */
break;
default:
if (sysFlashErase (flashType) == ERROR) /* erase device */
{
#ifndef FLASH_NO_OVERLAY
free (tempBuffer);
#endif
return (ERROR);
}
break;
} /* endswitch */
#ifndef FLASH_NO_OVERLAY /* program device */
if (sysFlashWrite (FLASH_CAST (tempBuffer), FLASH_MEM_SIZE, 0, flashType, 0)
== ERROR)
{
free (tempBuffer);
#else /* FLASH_NO_OVERLAY */
if (sysFlashWrite (FLASH_CAST (string), strLen, offset, flashType, 0) ==
ERROR)
{
#endif /* FLASH_NO_OVERLAY */
return (ERROR);
}
#ifdef INCLUDE_FLASH_SIB_FOOTER
/*
* As block has been erased above, we can write the footer at the end of
* the block.
*/
sysFlashWriteFooter (flashType);
#endif
#ifndef FLASH_NO_OVERLAY
free (tempBuffer);
#endif
return (OK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -