📄 amd29lv64mtd.c
字号:
/* amd29LvMtd.c - TrueFFS MTD for AMD AM29LV64DLdevices */ /* Copyright 2006 cetc. *//*modification history--------------------06a,21apr00,add Created.*//*DESCRIPTIONThis module implements an TrueFFS MTD for the AMD AM29LV6400DL . *//* includes */#include <vxWorks.h>#include <taskLib.h>#include <logLib.h>#include <stdio.h>#include <cacheLib.h>#include "tffs/flflash.h"#include "tffs/backgrnd.h"#include "config.h"IMPORT int sysClkRateGet();/* defines *//* FLASH_SIZE , FLASH_TFFS_RESERVED define in config.h*/#define AMD29LV_MTD_SECTOR_SIZE (0x20000) /*128KB*/#define AMD29LV_640_CHIP_SIZE (FLASH_SIZE - FLASH_TFFS_RESERVED) /* 14MB. first 1M and last 1M use to save user paramater */#define AMD29LV_640_LAST_SECTOR_NUM (AMD29LV_640_CHIP_SIZE / AMD29LV_MTD_SECTOR_SIZE - 1)#define AMD29LV_MTD_CHIP_CNT (1)#define AMD29LV_MTD_INTERLEAVE (1)#define DEBUG_READ 0x00000001#define DEBUG_WRITE 0x00000002#define DEBUG_PROGRAM 0x00000004#define DEBUG_ERASE 0x00000008#define DEBUG_ID 0x00000010#define DEBUG_MAP 0x00000020#define DEBUG_PROG32 0x00000040#define DEBUG_ALWAYS 0xffffffff#define DEBUG#ifdef DEBUG LOCAL UINT32 debug; #define DEBUG_PRINT(mask, string) \ if ((debug & mask) || (mask == DEBUG_ALWAYS)) \ printf string#else #define DEBUG_PRINT(mask, string)#endif/* local routines */LOCAL FLStatus amd29lv64SectorRangeErase(FLFlash* pVol, int, int);LOCAL FLStatus amd29lv64Program(FLFlash*, CardAddress, const void FAR1*, int, FLBoolean);LOCAL void FAR0* amd29lv64Map(FLFlash*, CardAddress, int);LOCAL void flashReset(FLFlash*);LOCAL void flashIdGet(FLFlash*, UINT16*, UINT16*);LOCAL void flashUnlock(FLFlash*);LOCAL STATUS flashProgram32Bits(FLFlash*, volatile UINT32*, UINT32);LOCAL void flashRegWrite32Bits(FLFlash*, UINT32, UINT32);LOCAL UINT16 flashRegRead16Bits(FLFlash*, UINT32);LOCAL STATUS amd29lv64FlashSectorErase(FLFlash*, int);/******************************************************************************** amd29lv64MTDIdentify - MTD identify routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/FLStatus amd29lv64MTDIdentify ( FLFlash* pVol ) { UINT16 manCode; UINT16 devCode; flashIdGet(pVol, &manCode, &devCode); if (manCode != 0x0001) { DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lv64MTDIdentify Manufacturer unknown: 0x%02x\n", manCode)); return(flUnknownMedia); } if (devCode == 0x22D7) /* amd29LV640 */ { pVol->type = 0x01D7; pVol->erasableBlockSize = AMD29LV_MTD_SECTOR_SIZE; pVol->chipSize = AMD29LV_640_CHIP_SIZE; pVol->noOfChips = AMD29LV_MTD_CHIP_CNT; pVol->interleaving = AMD29LV_MTD_INTERLEAVE; pVol->write = amd29lv64Program; pVol->erase = amd29lv64SectorRangeErase; pVol->map = amd29lv64Map; } else { DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lv64MTDIdentify Device unknown: 0x%02x\n", devCode)); return(flUnknownMedia); } debug=DEBUG_ID; DEBUG_PRINT(DEBUG_ID, ("amd29lv64MTDIdentify succeeds!\n")); return(flOK); }/******************************************************************************** amd29lvProgram - MTD write routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL FLStatus amd29lv64Program ( FLFlash* pVol, CardAddress address, const void FAR1* buffer, int length, FLBoolean overwrite ) { volatile UINT32* pFlash; UINT32* pBuffer; STATUS rc = OK; int i; BOOL doFree = FALSE; DEBUG_PRINT(DEBUG_PROGRAM, ("Program: 0x%08x, 0x%08x, %d\n", (unsigned int) address, length, overwrite)); if (flWriteProtected(vol.socket)) { return(flWriteProtect); } /* Check 4 bytes alignment */ if (((address & 0x03) != 0) || (((UINT32) buffer) & 0x03)) { DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lv64Program: Alignment error\n")); return(flBadParameter); } if (overwrite && length == 2) { int sector; int offset; pFlash = (volatile UINT32*) pVol->map(pVol, address, length); pBuffer = (UINT32*) malloc(AMD29LV_MTD_SECTOR_SIZE); if (pBuffer == 0) { DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lv64Program: No memory\n")); return(flBadParameter); } /* Determine sector and offset */ sector = address / AMD29LV_MTD_SECTOR_SIZE; offset = address % AMD29LV_MTD_SECTOR_SIZE; DEBUG_PRINT(DEBUG_PROGRAM,("Overwrite sector: 0x%08x, offset: 0x%08x\n", sector,offset)); /* Get a pointer to the flash sector */ pFlash = (volatile UINT32*) pVol->map(pVol, sector * AMD29LV_MTD_SECTOR_SIZE, AMD29LV_MTD_SECTOR_SIZE); /* Copy the sector from flash to memory */ memcpy(pBuffer, (void*) pFlash, AMD29LV_MTD_SECTOR_SIZE); /* Overwrite the sector in memory */ memcpy(((UINT8*) pBuffer) + offset, buffer, length); /* Erase sector */ rc = amd29lv64SectorRangeErase(pVol, sector, 1); if (rc != flOK) { free(pBuffer); return(rc); } length = AMD29LV_MTD_SECTOR_SIZE; doFree = TRUE; } else { if ((length & 0x03) != 0) { DEBUG_PRINT(DEBUG_ALWAYS, ("amd29lv64Program: length: %d\n", length)); return(flBadParameter); } pBuffer = (UINT32*) buffer; pFlash = (volatile UINT32*) pVol->map(pVol, address, length); } /* Program 'length' bytes (4 bytes each iterations) */ /* upper = ((((UINT32) pFlash) & 0x04) != 0);*/ for (i = 0; i < (length / 4); i++, pFlash++) { /* Don't bother programming if buffer data == format value */ if (pBuffer[i] == 0xffffffff) continue; /* Program 32 bits */ rc = flashProgram32Bits(pVol, pFlash, pBuffer[i]); if (rc != OK) break; } if (doFree) { free(pBuffer); } return((rc == OK) ? flOK : flTimedOut); }/******************************************************************************** amd29lvSectorRangeErase - MTD erase routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL FLStatus amd29lv64SectorRangeErase ( FLFlash* pVol, int sectorNum, int sectorCount ) { int i; STATUS rc; if (sectorNum + sectorCount > AMD29LV_640_LAST_SECTOR_NUM + 1) { DEBUG_PRINT(DEBUG_ALWAYS, ("Invalid sector range: %d , %d\n", sectorNum, sectorCount)); }/* DEBUG_PRINT(DEBUG_ALWAYS, (" Erasing sector range: %d , %d\n", sectorNum, sectorCount));*/ for (i = 0; i < sectorCount; i++) { /* Erase sector*/ rc = amd29lv64FlashSectorErase(pVol, sectorNum + i); if (rc != OK) return(flTimedOut); } return(flOK); }/******************************************************************************** amd29lvMap - MTD map routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL void FAR0* amd29lv64Map ( FLFlash* pVol, CardAddress address, int length ) { UINT32 flashBaseAddr = (pVol->socket->window.baseAddress << 12); void FAR0* pFlash = (void FAR0*) (flashBaseAddr + address); DEBUG_PRINT(DEBUG_MAP, ("Mapping 0x%08x bytes at 0x%08x to %p\n", length, (unsigned int) address, pFlash)); return(pFlash); }/******************************************************************************** flashProgram32Bits - Program 32 bits at 4 byte aligned address.** RETURNS: OK or ERROR**/LOCAL STATUS flashProgram32Bits ( FLFlash* pVol, volatile UINT32* pData, UINT32 data ) { BOOL programmed = FALSE; int timeout; flashUnlock(pVol); flashRegWrite32Bits(pVol, 0x555, 0x00a000a0); DEBUG_PRINT(DEBUG_PROG32, ("Programming 0x%08x to %p\n", data, pData)); *pData = data; CACHE_PIPE_FLUSH(); for (timeout = flMsecCounter + 3000; flMsecCounter < timeout;) { if (*pData == data) { programmed = TRUE; break; } taskDelay(0); } if (!programmed) { DEBUG_PRINT(DEBUG_ALWAYS, ("Timeout\n")); return(ERROR); } return(OK); }/******************************************************************************** flashHalfSectorErase - Erase lower or upper half of sector.** RETURNS: OK or ERROR**/LOCAL STATUS amd29lv64FlashSectorErase ( FLFlash* pVol, int sectorNum ) { BOOL erased = FALSE; int timeout = sysClkRateGet() * 5; UINT32 offset; UINT32 size; volatile UINT32* pFlash; UINT32 sectorAddr; offset = sectorNum * AMD29LV_MTD_SECTOR_SIZE; size = AMD29LV_MTD_SECTOR_SIZE; sectorAddr = (sectorNum << 15); DEBUG_PRINT(DEBUG_ERASE, ("Erasing sector %d, 0x%02x\n", sectorNum, sectorAddr)); /* Erase the sector half */ flashUnlock(pVol); flashRegWrite32Bits(pVol, 0x555, 0x00800080); flashUnlock(&vol); flashRegWrite32Bits(pVol, sectorAddr, 0x00300030); pFlash = (volatile UINT32*) pVol->map(pVol, offset, size); for (timeout = flMsecCounter + 5000; flMsecCounter < timeout;) { if (*pFlash == 0xffffffff) { erased = TRUE; break; } } if (!erased) { DEBUG_PRINT(DEBUG_ALWAYS, ("Sector erase timeout, %p\n", pFlash)); return(ERROR); } return(OK); }/******************************************************************************** flashRegWrite32Bits - Write 32 bits to 4 byte aligned address.** RETURNS: N/A**/LOCAL void flashRegWrite32Bits ( FLFlash* pVol, UINT32 addr, UINT32 data ) { UINT32 flashBaseAddr = (pVol->socket->window.baseAddress << 12); addr = flashBaseAddr + 4* addr; /*modified by MCL*/ /*if (upper) addr += 4;modified by MCL*//* debug=DEBUG_WRITE; */ DEBUG_PRINT(DEBUG_WRITE, ("Writing 0x%08x to 0x%08x\n", data, addr)); /* Write */ *((volatile UINT32*) addr) = data; CACHE_PIPE_FLUSH(); }/******************************************************************************** flashRegRead16Bits - Read 16 bits from 2 byte aligned address.** RETURNS: data at specified address**/LOCAL UINT16 flashRegRead16Bits ( FLFlash* pVol, UINT32 addr ) { UINT16 data; UINT32 flashBaseAddr = (pVol->socket->window.baseAddress << 12); addr = flashBaseAddr + 4 * addr; /*modified by MCL*/ data = *((volatile UINT16*) addr); DEBUG_PRINT(DEBUG_READ, ("Read 0x%08x from 0x%08x\n", data, addr)); CACHE_PIPE_FLUSH(); return(data); }/******************************************************************************** flashIdGet - Get flash man. and device codes.** RETURNS: N/A**/LOCAL void flashIdGet ( FLFlash* pVol, UINT16* manCode, UINT16* devCode ) { flashUnlock(pVol); flashRegWrite32Bits(pVol, 0x555, 0x00900090); *manCode = flashRegRead16Bits(pVol, 0x00); *devCode = flashRegRead16Bits(pVol, 0x01); flashReset(pVol); }/******************************************************************************** flashUnlock - Write unlock sequence to upper or lower flash section.** RETURNS: N/A**/LOCAL void flashUnlock ( FLFlash* pVol ) { flashRegWrite32Bits(pVol, 0x555, 0x00aa00aa); flashRegWrite32Bits(pVol, 0x2aa, 0x00550055); }/******************************************************************************** flashReset - Write reset sequence to upper or lower flash section.** RETURNS: N/A**/LOCAL void flashReset ( FLFlash* pVol ) { flashRegWrite32Bits(pVol, 0, 0x00f000f0); }#define FLASH_TEST#undef FLASH_TEST#ifdef FLASH_TEST#include "tffs/flsocket.h"LOCAL FLFlash testVol;LOCAL FLSocket testSocket;/* Make sure this functions are NOT static (LOCAL) in sysTffs.c */IMPORT void rfaSetWindow (FLSocket vol);IMPORT void rfaSetMappingContext (FLSocket vol, unsigned page);IMPORT FLBoolean rfaWriteProtected (FLSocket vol);/* Initialize */LOCAL void FAR0 *flashMap(FLFlash vol, CardAddress address, int length){ return flMap(vol.socket,address);}void fsinit() { FLStatus rc; testSocket.window.baseAddress = tffsFlashBaseAdrs >> 12; testSocket.window.currentPage = UNDEFINED_MAPPING; testSocket.setWindow = rfaSetWindow; testSocket.setMappingContext = rfaSetMappingContext; testSocket.setMappingContext = rfaSetMappingContext; testSocket.writeProtected = rfaWriteProtected; testVol.socket = &testSocket; testVol.map = flashMap; rc = amd29lv64MTDIdentify(&testVol); if (rc != flOK) { printf("identify fails\n"); } }/* Show */void fsshow() { printf("Type 0x%04x\n", testVol.type); printf("Eraseable block size 0x%08lx\n", testVol.erasableBlockSize); }/* Erase */STATUS fse ( UINT8 sectorNum, UINT8 numSectors ) { FLStatus rc; if (sectorNum <= 3) { printf("Sector contains bootrom!\n"); return(ERROR); } rc = testVol.erase(&testVol, sectorNum, numSectors); return(rc); }/* Program */STATUS fprog ( UINT32 offset, UINT32 bufSize, UINT8 pattern ) { FLStatus rc; UINT32* pBuf; UINT32 sectorNum = offset / AMD29LV_MTD_SECTOR_SIZE; if (sectorNum <= 3) { printf("Sector contains bootrom!\n"); return(ERROR); } if (bufSize == 0) bufSize = 4; if ((bufSize & 0x03) != 0) bufSize += 4 - (bufSize & 0x03); pBuf = memalign(4, bufSize); if (pBuf == 0) return(ERROR); memset(pBuf, pattern, bufSize); rc = testVol.write(&testVol, offset, pBuf, bufSize, FALSE); free(pBuf); return(rc == flOK ? OK : ERROR); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -