/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2009, Martin Schoeberl (martin@jopdesign.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /** * */ package util; import com.jopdesign.sys.Native; /** * Test program for the NAND Flash. * * @author Martin Schoeberl (martin@jopdesign.com) * */ public class NandTest extends Nand { /** * Test the NAND Flash. A static method to be used in the * board test. * * @return true when NAND Flash is available. */ public static boolean test() { int i, j; boolean ret = true; /* read ID and status from NAND */ Native.wrMem(SIGNATURE, CLE); Native.wrMem(0x00, ALE); // // should read 0x98 and 0x73 // i = Native.rdMem(NAND_ADDR); // Manufacturer j = Native.rdMem(NAND_ADDR); // Size System.out.print("NAND "); System.out.print(i); System.out.print(" "); System.out.print(j); System.out.print(" "); if (i == 0x98) { System.out.print("Toshiba "); } else if (i == 0x20) { System.out.print("ST "); } else { System.out.println("Unknown manufacturer"); } if (j == 0x73) { System.out.println("16 MB"); } else if (j == 0x75) { System.out.println("32 MB"); } else if (j == 0x76) { System.out.println("64 MB"); } else if (j == 0x79) { System.out.println("128 MB"); } else { System.out.println("error reading NAND"); ret = false; } // // read status, should be 0xc0 // Native.wrMem(STATUS, CLE); i = Native.rdMem(NAND_ADDR) & 0xc1; j = Native.rdMem(NAND_ADDR) & 0xc1; System.out.print(i); System.out.print(" "); System.out.print(j); System.out.print(" "); if (i == 0xc0 && j == 0xc0) { System.out.println("status OK"); } else { System.out.println("error reading NAND status"); ret = false; } return ret; } void findBadBlocks() { int[] spare = new int[SPARE_WORDS]; for (int i=0; i<getNrOfBlocks(); ++i) { for (int j=0; j<PAGES_PER_BLOCK; ++j) { readPage(null, spare, i, j); boolean bad = false; for (int k=0; k<SPARE_WORDS; ++k) { if (spare[k]!=-1) { bad = true; } } if (bad) { System.out.println("Bad block "+i); for (int k=0; k<SPARE_WORDS; ++k) { System.out.println(Integer.toHexString(spare[k])); } } } } } /** * Program the whole NAND flash and check it. * @return */ void testFull() { int block, page; int[] data = new int[WORDS]; int[] spare = new int[SPARE_WORDS]; int magic; int badPage=0; int badSpare=0; int time; int nrBlocks = getNrOfBlocks(); int[] badBlocks = new int[nrBlocks]; // nrBlocks = 100; time = (int) System.currentTimeMillis(); System.out.println("Erase"); if (eraseAll()) { System.out.println("Not all blocks erased"); } time = ((int) System.currentTimeMillis()) - time; System.out.println("Erase finished after "+time+" ms"); System.out.println("Program"); time = (int) System.currentTimeMillis(); for (block=0; block<nrBlocks; ++block) { System.out.print("+"); for (page=0; page<PAGES_PER_BLOCK; ++page) { for (int i=0; i<WORDS; ++i) { magic = OFF+i+(block<<7)+(page<<2); data[i] = magic; } for (int i=0; i<SPARE_WORDS; ++i) { magic = OFF+i+(block<<7)+(page<<2)+0xabcd; spare[i] = magic; } if (!writePage(data, spare, block, page)) { System.out.println("Error on write at block "+block+" page "+page); badBlocks[block]++; } } } time = ((int) System.currentTimeMillis()) - time; System.out.println(); System.out.println("Program finished after "+time+" ms"); System.out.println("Read back"); time = (int) System.currentTimeMillis(); for (block=0; block<nrBlocks; ++block) { System.out.print("."); for (page=0; page<PAGES_PER_BLOCK; ++page) { for (int i=0; i<WORDS; ++i) { data[i] = 0; } for (int i=0; i<SPARE_WORDS; ++i) { spare[i] = 0; } if (!readPage(data, spare, block, page)) { System.out.println("Error on read at block "+block+" page "+page); badBlocks[block]++; } for (int i=0; i<WORDS; ++i) { magic = OFF+i+(block<<7)+(page<<2); if (data[i] != magic) { // System.out.println("Read error data "+(block*32+page)); badBlocks[block]++; ++badPage; break; } } for (int i=0; i<SPARE_WORDS; ++i) { magic = OFF+i+(block<<7)+(page<<2)+0xabcd; if (spare[i] != magic) { // System.out.println("Read error spare "+(block*32+page)); badBlocks[block]++; ++badSpare; break; } } } } time = ((int) System.currentTimeMillis()) - time; System.out.println(); System.out.println("Read back finished after "+time+" ms"); System.out.println("Bad pages: "+badPage+" from "+(nrBlocks*32)); System.out.println("Bad spares: "+badSpare+" from "+(nrBlocks*32)); int cnt = 0; for (int i=0; i<badBlocks.length; ++i) { if (badBlocks[i]!=0) { ++cnt; } } System.out.println("Bad blocks: "+cnt+" from "+nrBlocks); } final static int OFF = 1234; /** * @param args */ public static void main(String[] args) { int block, page; test(); NandTest n = new NandTest(); System.out.println(n.getNrOfBlocks() + " blocks"); System.out.println(n.size() + " usable blocks"); System.out.println(n.size()*16 + " KB"); // System.out.println("Physical block "+n.getPhysicalBlock(3)); // System.out.println("Physical block "+n.getPhysicalBlock(488)); // System.out.println("Physical block "+n.getPhysicalBlock(1000)); // System.out.println("Physical block "+n.getPhysicalBlock(1920)); // n.eraseAll(); // for (int i=0; i<1000; ++i) { // n.erase(i); // System.out.print('.'); // } // n.testFull(); // n.findBadBlocks(); // System.out.println("Start wearing out test"); // int data[] = new int[128]; // for (int cnt=0; cnt<10000; ++cnt) { // System.out.print(" "); // System.out.print(cnt); // for (int i=450; i<500; ++i) { // for (int j=0; j<PAGES_PER_BLOCK; ++j) { // for (int k=0; k<128; ++k) { // data[k] = i*128*PAGES_PER_BLOCK+j*PAGES_PER_BLOCK+k+cnt; // } // n.write(data, i, j, 512); // } // } // for (int i=450; i<500; ++i) { // for (int j=0; j<PAGES_PER_BLOCK; ++j) { // n.read(data, i, j); // for (int k=0; k<128; ++k) { // if (data[k] != i*128*PAGES_PER_BLOCK+j*PAGES_PER_BLOCK+k+cnt) { // System.out.println("Data error! "+i+" "+j+" "+(k+cnt)); // System.exit(-1); // } // } // } // } // for (int i=450; i<500; ++i) { // n.erase(i); // } // } } }