📄 s29glmtd.c
字号:
/* s29glMtd.c - TrueFFS MTD for Spansion s29gl×××N devices */ /* Copyright 2007 HUST juntong *//* includes */#include <vxWorks.h>#include <taskLib.h>#include <logLib.h>#include <stdio.h>#include <cacheLib.h>#include "tffs/flflash.h"#include "tffs/backgrnd.h"/* defines */#define S29GL_MTD_SECTOR_SIZE (0x80000)/* 128KB */#define S29GL_128_CHIP_SIZE (0x1000000) /* 16MB */#define S29GL_128_LAST_SECTOR_NUM (S29GL_128_CHIP_SIZE / S29GL_MTD_SECTOR_SIZE - 1) /* 127 */#define S29GL_256_CHIP_SIZE (0x2000000) /* 32MB */#define S29GL_256_LAST_SECTOR_NUM (S29GL_256_CHIP_SIZE / S29GL_MTD_SECTOR_SIZE - 1) /* 255 */#define S29GL_512_CHIP_SIZE (0x2000000) /* 32MB */#define S29GL_512_LAST_SECTOR_NUM (S29GL_512_CHIP_SIZE / S29GL_MTD_SECTOR_SIZE - 1) /* 511 */#define S29GL_RSV_FOR_BOOTROM (0x100000)/* 1MB */#define S29GL_FIRST_SECTOR_NUM (S29GL_RSV_FOR_BOOTROM / S29GL_MTD_SECTOR_SIZE ) /* 8 */#define S29GL_MTD_CHIP_CNT (1)#define S29GL_MTD_INTERLEAVE (1)#define FLASH_REGISTER_WR(addr,data) *((volatile UINT16 *)(addr<<1))=(UINT16)data#define FLASH_REGISTER_RD(addr) (*((UINT16 *)(addr<<1)))UINT16 awBuffForOneSector[S29GL_MTD_SECTOR_SIZE];/* local routines */LOCAL FLStatus s29glSectorRangeErase(FLFlash* pVol, int, int);LOCAL FLStatus s29glProgram(FLFlash*, CardAddress, const void FAR1*, int, FLBoolean);LOCAL void FAR0* s29glMap(FLFlash*, CardAddress, int);LOCAL void flashIdGet(FLFlash*, UINT16*, UINT16*);/******************************************************************************** amd29lvMTDIdentify - MTD identify routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/FLStatus s29glMTDIdentify ( FLFlash* pVol ){ UINT16 manCode; UINT16 devCode; flashIdGet ( pVol, &manCode, &devCode ); if (( manCode & 0xff ) != 0x0001 ) { return ( flUnknownMedia ); } if ( devCode == 0x227E ) /* s29GL128N Just Process this kind of chip */ { pVol->type = 0x017E; pVol->erasableBlockSize = S29GL_MTD_SECTOR_SIZE; pVol->chipSize = S29GL_128_CHIP_SIZE - S29GL_RSV_FOR_BOOTROM;/* Not sure ?????????*/ pVol->noOfChips = S29GL_MTD_CHIP_CNT; pVol->interleaving = S29GL_MTD_INTERLEAVE; pVol->write = s29glProgram; pVol->erase = s29glSectorRangeErase; pVol->map = s29glMap; } else { return ( flUnknownMedia ); } return(flOK);}/******************************************************************************** s29glProgram - MTD write routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL FLStatus s29glProgram ( FLFlash* pVol, CardAddress address, const void FAR1* buffer, int length, FLBoolean overwrite ){ volatile UINT16* pFlash; UINT16* pBuffer, *pTemp, *pTemp2; UINT16 wTemp1, wTemp2; int ii, sector, offset, timeout, dwLength ; STATUS rc; /* Check alignment */ if ( ( ( address & 0x01 ) != 0 ) ) /* Maybe do something here */ { ; } if ( ( length > pVol->chipSize ) || ( length <= 0 ) ) { logMsg("s29glProgram() length Error =0x %x.\n",length,0,0,0,0,0); return flWriteFault; } pTemp2 = (UINT16 *)buffer; while ( length > 0 ) { pFlash = (volatile UINT16*) pVol->map(pVol, address, length); /* Determine sector and offset */ sector = ( (UINT32)pFlash ) / pVol->erasableBlockSize ;/* Not sure ????? */ if ( ( sector < S29GL_FIRST_SECTOR_NUM ) || ( sector > S29GL_128_LAST_SECTOR_NUM ) ) { logMsg("s29glProgram() sector Error = %x.\n",sector,0,0,0,0,0); return flWriteFault; } offset = address % pVol->erasableBlockSize;/* the offset address in this sector */ /* Get a pointer to the flash sector */ pFlash = (volatile UINT16*) ( sector * ( pVol->erasableBlockSize ) ); pBuffer = (UINT16*) &awBuffForOneSector;/* Donnot use malloc() */ /* Copy all the sector from flash to memory */ memcpy(pBuffer, (void*) pFlash, pVol->erasableBlockSize); /* Overwrite the sector in memory */ if ( length <= pVol->erasableBlockSize - offset )/* the length is in this sector, once is enough */ { dwLength = length; length = 0; } else { dwLength = pVol->erasableBlockSize - offset; length -= dwLength; pTemp2 += dwLength; address += dwLength; } memcpy(((UINT8*) pBuffer) + offset, pTemp2, dwLength ); /* Erase sector */ rc = pVol->erase(pVol, sector, 1); if ( rc != flOK ) { return ( rc ); } pTemp = ( UINT16 *)pFlash; /* point to the sector start address */ /* Program 'length' bytes (2 bytes each iterations) */ for ( ii = 0; ii < pVol->erasableBlockSize/2; ii++ ) { FLASH_REGISTER_WR(0x555,0xaaaa); FLASH_REGISTER_WR(0x2aa,0x5555); FLASH_REGISTER_WR(0x555,0xa0a0); *pFlash = *pBuffer; wTemp1 = *pFlash & 0x40; timeout = 0x1000000; while ( 1 ) { wTemp2 = *pFlash & 0x40; if ( wTemp1 == wTemp2 ) break; else wTemp1 = wTemp2; if ( timeout-- <= 0 ) { logMsg("s29glProgram() return flTimedOut.\n",0,0,0,0,0,0); return flWriteFault; } } if ( *pFlash != *pBuffer ) { logMsg("s29glProgram() return *pFlash != *pBuffer.\n",0,0,0,0,0,0); return flWriteFault; } pFlash ++; pBuffer ++; } pBuffer = (UINT16 *)&awBuffForOneSector; if ( memcmp( (void *) pTemp, (void *)pBuffer, pVol->erasableBlockSize) )/* check the entire sector */ { logMsg("s29glProgram() memcmp fail.\n",0,0,0,0,0,0); return flWriteFault; } } return flOK ;}/******************************************************************************** s29glSectorRangeErase - MTD erase routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL FLStatus s29glSectorRangeErase ( FLFlash* pVol, int sectorNum, int sectorCount ){ int ii,jj; UINT16 wTemp1,wTemp2; volatile UINT16* pFlash; int timeout; /* Check for valid range */ if ( pVol->type == 0x017E ) /* s29gl128N */ { if ( sectorNum < S29GL_FIRST_SECTOR_NUM ) { logMsg("s29glSectorRangeErase() sectorNum too little = %x\n", sectorNum ,0,0,0,0,0); return ( flBadParameter ); } if ( sectorNum + sectorCount > S29GL_128_LAST_SECTOR_NUM + 1 ) { logMsg("s29glSectorRangeErase() sectorNum too large = %x\n",sectorNum + sectorCount,0,0,0,0,0); return ( flBadParameter ); } } else { logMsg("s29glSectorRangeErase() Error pVol->type =%x\n",pVol->type,0,0,0,0,0); return ( flBadParameter ); } for ( ii = 0; ii < sectorCount; ii++ ) { pFlash = ( UINT16 * ) ( ( sectorNum + ii ) * ( pVol->erasableBlockSize ) ); FLASH_REGISTER_WR(0x00, 0xf0f0);/* RESET ????*/ FLASH_REGISTER_WR(0x555,0xaaaa); FLASH_REGISTER_WR(0x2aa,0x5555); FLASH_REGISTER_WR(0x555,0x8080); FLASH_REGISTER_WR(0x555,0xaaaa); FLASH_REGISTER_WR(0x2aa,0x5555); FLASH_REGISTER_WR((((UINT32)pFlash)>>1),0x3030); wTemp1 = *pFlash & 0x40; timeout = 0x1000000; while ( 1 ) { wTemp2 = *pFlash & 0x40; if ( wTemp1 == wTemp2 ) break; else wTemp1 = wTemp2; if ( timeout-- <= 0 ) { logMsg("s29glSectorRangeErase() return flTimedOut.\n",0,0,0,0,0,0); return ( flWriteFault ); } } FLASH_REGISTER_WR(0x00, 0xf0f0);/* RESET ????*/ for ( jj = 0; jj < pVol->erasableBlockSize/2; jj++ )/* Maybe too long time */ { if ( *pFlash != 0xffff ) { logMsg("s29glSectorRangeErase() *pFlash not 0xffff.\n",0,0,0,0,0,0); return ( flWriteFault ); } pFlash ++; } } return(flOK); }/******************************************************************************** s29glMap - MTD map routine (see TrueFFS Programmer's Guide)** RETURNS: FLStatus**/LOCAL void FAR0* s29glMap ( FLFlash* pVol, CardAddress address, int length ) { UINT32 flashBaseAddr = (pVol->socket->window.baseAddress << 12); void FAR0* pFlash = (void FAR0*) (flashBaseAddr + address); return(pFlash); } /******************************************************************************** flashIdGet - Get flash man. and device codes.** RETURNS: N/A**/LOCAL void flashIdGet ( FLFlash* pVol, UINT16* manCode, UINT16* devCode ){ FLASH_REGISTER_WR(0x00, 0xf0f0);/* RESET ????*/ FLASH_REGISTER_WR(0x555,0xaaaa); FLASH_REGISTER_WR(0x2aa,0x5555); FLASH_REGISTER_WR(0x555,0x9090); *manCode = FLASH_REGISTER_RD(0x00); FLASH_REGISTER_WR(0x00, 0xf0f0);/* RESET ????*/ FLASH_REGISTER_WR(0x555,0xaaaa); FLASH_REGISTER_WR(0x2aa,0x5555); FLASH_REGISTER_WR(0x555,0x9090); *devCode = FLASH_REGISTER_RD(0x01); FLASH_REGISTER_WR(0x00, 0xf0f0);/* RESET ?????*/ logMsg("Manufacture ID(0x0001)=%4x, Device ID(0x22xx)=%4x\n",*manCode, *devCode, 0, 0, 0, 0 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -