/************************************************************************************ * flash.c * * synopsis: Contains flash memory writing routines * * in this file: flashProductInfo, waitFlashComplete, programFlashSector, * programFlash * * author: Joseph Virzi U.C. Berkeley LBNL jsvirzi@lbl.gov ************************************************************************************/ #include "fxnProto.h" #pragma CODE_SECTION(flashProductInfo, "xcode"); #pragma CODE_SECTION(waitFlashComplete, "xcode"); #pragma CODE_SECTION(programFlashSector, "xcode"); #pragma CODE_SECTION(programFlash, "xcode"); #define FLASH_BASE 0x1400000 #define SECTOR_LEN 0x1000 #define SECTOR_LEN_LOG 12 /* 128 sectors * 4096 bytes per sector = 512K bytes = 4 Mbits */ #define N_SECTORS 128 INT32 flashProductInfo(void) { INT32 returnCode; volatile unsigned char *cptr; unsigned char manufacturer, device; /* software id enter */ cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xaa; cptr = (unsigned char *)(FLASH_BASE + (0x2aaa << 2)); *cptr = 0x55; cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0x90; /* wait some time. very little */ for(returnCode = 0; returnCode < 0x100; ) returnCode += 1; cptr = (unsigned char *)FLASH_BASE; manufacturer = *cptr++; device = *cptr; /* software id exit */ cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xaa; cptr = (unsigned char *)(FLASH_BASE + (0x2aaa << 2)); *cptr = 0x55; cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xf0; /* wait some time. very little */ for(returnCode = 0; returnCode < 0x100; ) returnCode += 1; returnCode = manufacturer; returnCode <<= 16; returnCode |= device; return returnCode; } void waitFlashComplete(unsigned char *ptr) { volatile unsigned char d0, d1, *cptr; /* wait for completion of erase or program process */ cptr = (volatile unsigned char *)ptr; d0 = (*cptr) & 0x40; d1 = (*cptr) & 0x40; d0 = (*cptr) & 0x40; d1 = (*cptr) & 0x40; while(d0 != d1) { d0 = d1; d1 = (*cptr) & 0x40; } } int programFlashSector(int sector, unsigned char *buff) { int k, addr, status, blank; unsigned int *wptr; volatile unsigned char *cptr; /* erase sector */ addr = (sector << SECTOR_LEN_LOG); cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xaa; cptr = (unsigned char *)(FLASH_BASE + (0x2aaa << 2)); *cptr = 0x55; cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0x80; cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xaa; cptr = (unsigned char *)(FLASH_BASE + (0x2aaa << 2)); *cptr = 0x55; cptr = (unsigned char *)(FLASH_BASE + (addr << 2)); *cptr = 0x30; waitFlashComplete((unsigned char *)cptr); blank = 1; wptr = (unsigned int *)buff; k = SECTOR_LEN / sizeof(unsigned int); while(k--) { if(*wptr++ != ~0) { blank = 0; break; } } if(blank) return 0; /* nothing to do because the buffer was blank */ /* program sector */ for(k = 0; k < SECTOR_LEN; ++k, ++addr) { cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xaa; cptr = (unsigned char *)(FLASH_BASE + (0x2aaa << 2)); *cptr = 0x55; cptr = (unsigned char *)(FLASH_BASE + (0x5555 << 2)); *cptr = 0xa0; cptr = (unsigned char *)(FLASH_BASE + (addr << 2)); *cptr = buff[k]; waitFlashComplete((unsigned char *)cptr); } /* verify sector */ addr = (sector << SECTOR_LEN_LOG); cptr = (unsigned char *)(FLASH_BASE + addr); status = 0; for(k = 0; k < SECTOR_LEN; ++k) { if(*buff++ != *cptr++) ++status; } return status; } INT32 programFlash(INT32 len, void *base) { INT32 nSectors, sector, status; UINT8 *buff; status= 0; nSectors= (len + SECTOR_LEN - 1) >> SECTOR_LEN_LOG; buff= (UINT8 *)base; for(sector= 0; sector < nSectors; ++sector) { if(status= programFlashSector(sector, buff)) { status= (sector << 16) +(status & 0xffff); break; } buff += SECTOR_LEN; } return status; }