📄 flashmem.c
字号:
for (pFA = FLASH_CAST (offset); (pFA < FLASH_CAST (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 = FLASH28_CMD_RESET; *pFA = FLASH28_CMD_READ_MEM; sysFlashDelay (6); SYS_FLASH_WRITE_DISABLE_RTN (); /* lower Vpp */ break; } case (FLASH_29F010): case (FLASH_29LV160T): case (FLASH_29LV160B): case (FLASH_29LV040B): { SYS_FLASH_WRITE_ENABLE_RTN (); /* enable write */ for (pFA = FLASH_CAST (offset); pFA < FLASH_CAST (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 (offset); pFA < FLASH_CAST (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 (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; } 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); }/******************************************************************************** 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 segment, /* segment base of flash*/ int offset /* byte offset into segment */ ) { char *tempBuffer; if ((offset < 0) || (strLen < 0) || (segment < 0) || ((offset + strLen) > FLASH_SEGMENT_SIZE)) return (ERROR); /* see if contents are actually changing */ if (bcmp ((char *) (segment + offset), string, strLen) == 0) return (OK); /* first read existing data */ if (tempBuffer = malloc(FLASH_SEGMENT_SIZE), tempBuffer == 0) return (ERROR); bcopyBytes ((char *) (segment), tempBuffer, FLASH_SEGMENT_SIZE); bcopyBytes (string, (tempBuffer + offset), strLen); if (flashType == 0) flashType = sysFlashTypeGet (); switch (flashType) { case (FLASH_28F640J3A): case (FLASH_28F320J3A): case (FLASH_28F128J3A): /* unlock the sector*/ if (sysFlashUnlock(FLASH_CAST (segment), flashType) == ERROR) { free (tempBuffer); return (ERROR); } /* erase the sector */ if (sysFlashErase (FLASH_CAST (segment), flashType) == ERROR) { free (tempBuffer); return (ERROR); } break; case FLASH_29C040A: case FLASH_29LV1024: /* do not erase these as not required */ break; case (FLASH_29LV160T): case (FLASH_29LV160B): case (FLASH_29LV040B): /* erase the sector */ if (sysFlashErase (FLASH_CAST (segment), flashType) == ERROR) { free (tempBuffer); return (ERROR); } break; default: free (tempBuffer); return (ERROR); break; } /* endswitch */ if (sysFlashWrite (FLASH_CAST (tempBuffer), FLASH_SEGMENT_SIZE, segment, flashType, 0) == ERROR) { free (tempBuffer); return (ERROR); } return OK;}/******************************************************************************** sysSectorUnlock - unlock the flash memory** This routine unlock the contents of flash memory.*** RETURNS: OK, or ERROR if the contents of flash memory cannot be unlocked.*/STATUS sysFlashUnlock ( 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_LOCKSETUP; /* setup */ *pFA = FLASH28_CMD_UNLOCK; /* 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; default: retVal = ERROR; } return (retVal); }/******************************************************************************** sysFlashLock - lock the flash memory** This routine lock the contents of flash memory.*** RETURNS: OK, or ERROR if the contents of flash memory cannot be locked.*/STATUS sysFlashLock ( 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_LOCKSETUP; /* setup */ *pFA = FLASH28_CMD_LOCK; /* 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; default: retVal = ERROR; } return (retVal); }/******************************************************************************** flashNextBlock - Advance a pointer to the next flash block** This routine advances a pointer to the start of the next flash block* for a multi-block device.* * RETURNS: OK, or ERROR if the device type is unknown*/STATUS sysFlashNextBlock ( UINT32 *flash_offset /* Offset into flash memory */ ) { STATUS retVal = OK; UINT32 blockSize; UINT32 flashSize; if (flashType == 0) flashType = sysFlashTypeGet(); switch (flashType) { case (FLASH_28F128J3A): flashSize = 16 * 1024*1024; break; default: return ERROR; } switch (flashType) { case (FLASH_28F128J3A): blockSize = 128 * 1024; *flash_offset = (*flash_offset + blockSize) & ~(blockSize-1); default: return ERROR; } return (retVal); }/********************************************************************************* programFlash - Program the flash from a buffer** This routine updates the flash with the contents of a buffer, optionally* skipping the block containing the NVRam value. It displays a status* update during the programming process.** RETURNS: ERROR or OK*/STATUS programFlash(UINT8* buf, UINT32 flashStart, UINT32 flashEnd, BOOL skipNVRam, BOOL skipFUtil) { UINT32 addr, next_addr; if (flashType == 0) flashType = sysFlashTypeGet (); printf("Progress:\n"); for (addr = flashStart; addr < flashEnd; addr = next_addr) { printf("\r%3d%% ",(100 * (addr -flashStart) / (flashEnd - flashStart))); next_addr = addr; sysFlashNextBlock(&next_addr); /* unlock the block */ if (OK != sysFlashUnlock(FLASH_CAST(addr), flashType)) { printf("Error unlock flash block %x\n", addr); } /*erase the block*/ if (OK != sysFlashErase(FLASH_CAST(addr), flashType)) { printf("Error erasing flash block %X\n",addr); return ERROR; } /*write the block*/ if (OK != sysFlashWrite(FLASH_CAST(buf + (addr - flashStart)), next_addr - addr, addr, flashType, 0)) { printf("Error writing flash block %X\n",addr); return ERROR; } /*compare the block*/ if (0 != bcmp((char*)(buf + (addr - flashStart)), (char*)(addr), next_addr - addr)) { printf("Error: data miscompares after write, block = %X.\n",addr); return ERROR; } } /* end for addr */ printf("\r100%% ... done\n"); return OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -