├── checkblocksize.py ├── utils.ino ├── NANDDump.ino └── nand.ino /checkblocksize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # cat | ./checkblocksize.py 3 | import sys 4 | 5 | # Define "Expected Blocksize" and only those not matching will print 6 | expectedsize = 2112 7 | 8 | buf = '' 9 | blocknum = None 10 | while True: 11 | c = sys.stdin.read(1) 12 | if not c: 13 | break 14 | 15 | buf += c 16 | if buf.endswith('BLOCK '): 17 | if blocknum and ('expectedsize' not in globals() or len(buf) < 2112): 18 | print "%8d block size %5d (0x%x)"%(blocknum, len(buf)-6, len(buf)-6) 19 | blocknum = int(sys.stdin.read(25)) 20 | sys.stdin.read(1) # '\n' 21 | buf = '' 22 | 23 | print "last block number:", blocknum 24 | -------------------------------------------------------------------------------- /utils.ino: -------------------------------------------------------------------------------- 1 | 2 | void printbin (int out) { 3 | int j; 4 | for (j=7; j>=0; j--) { 5 | if (out & (1 << j)) { 6 | Serial.print("1"); //49= "1" 7 | } 8 | else { 9 | Serial.print("0"); //48= "0" 10 | } 11 | } 12 | } 13 | /* printf. maxlength output of 128. cannot pass arguments twice*/ 14 | void p(char *fmt, ... ) 15 | { 16 | char tmp[128]; 17 | va_list args; 18 | va_start (args, fmt ); 19 | vsnprintf(tmp, 128, fmt, args); 20 | va_end (args); 21 | Serial.print(tmp); 22 | } 23 | /* set the global pin array to mode, with or without pullsups */ 24 | void io_pin_mode (uint8_t mode, uint8_t pullups) 25 | { 26 | for (int i = 0; i < io_pinslen; i++) { 27 | pinMode(io_pins[i], mode); 28 | if (mode == INPUT && pullups == true) 29 | digitalWrite(io_pins[i], HIGH); 30 | } 31 | } 32 | void io_pin_mode (uint8_t mode) 33 | { 34 | io_pin_mode(mode, false); 35 | } 36 | // 8bit 37 | void io_write_byte(byte b) 38 | { 39 | for (int i = 0; i < 8; i++) { 40 | digitalWrite(io_pins[i], (b >> i ) & 1 ); 41 | } 42 | } 43 | byte io_read_byte() 44 | { 45 | byte ret = 0; 46 | int val; 47 | for (int i = 0; i < 8; i++) { 48 | val = digitalRead(io_pins[i]); 49 | ret |= val << i; 50 | } 51 | return ret; 52 | } 53 | -------------------------------------------------------------------------------- /NANDDump.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This NAND reading code should work with minor modification for 3 | NAND with these characteristics: 4 | * Large Page (mem size over 1Gbit) 5 | * x8 bit io bus (for x16 modify addressing schemas) 6 | 7 | CHANGELOG: 8 | 20100930 cyphunk 9 | 20120912 luca melette+cyphunk 10 | 20140522 cyphunk 11 | 20150908 gina hortenbach+cyphunk 12 | 13 | Before using change: 14 | * Teensy/Arduino pin definitions for how you have connected 15 | your target (breakout board) 16 | * Page/Block size for target chip 17 | * Turning on/off interactive mode 18 | 19 | Use interactive mode (the define below) to query the chips 20 | block size and ID. When interactive mode is on you can open 21 | the serial terminal and execute: 22 | 23 | > readid 24 | This will print the ID. 25 | 26 | > scan 27 | This will print the first 128 bytes of the first 512 pages 28 | 29 | > read page 30 | You can then provide a page number and size to dump. 31 | 32 | Once you feel satisfied that the code is working somewhat 33 | with your target, you can turn the INTERACTIVE mode off. 34 | Now when you connect the serial console you will get raw 35 | data. To record this as a binary blob you can try: 36 | 37 | Linux: 38 | stty -F /dev/ttyACM* 115200 -icrnl -imaxbel -opost -onlcr -isig -icanon -echo 39 | cat /dev/ttyACM* > dump 40 | tail -f dump | xxd -c 66 | cat 41 | OSX: 42 | stty -f /dev/tty.usb* 115200 43 | cat /dev/cu.usb* > dump 44 | tail -f dump | xxd -c 66 | cat -c 45 | 46 | The dump will start 10 seconds after loading the code. 47 | 48 | Do not use `screen -L /dev/tty.usb*` as it will interpret 49 | some bytes rather that log them. 50 | 51 | The raw output by default includes a 32 byte ASCII prefix 52 | before each block in the form of: 53 | 54 | printf("BLOCK %025lu\n", page) 55 | 56 | This can be useful when the dump includes some sort of 57 | virtualised blocking mechanism of the filesystem (such as 58 | with UBIFS). You can turn this off by commenting out the 59 | PRINTBLOCKIDENT define. However leaving it on helps debug 60 | the output as it arrives. The checkblocksize.py can be 61 | used to monitor the dump. 62 | */ 63 | 64 | //#define INTERACTIVE 65 | // invert the data portion of blocks (and not oob): 66 | //#define INVERTDATA 67 | 68 | 69 | #define PRINTBLOCKIDENT // 32 byte block prefix 70 | // When monitoring dump in non-interactive mode the following commands have 71 | // been used in the past: 72 | // stty -f /dev/tty.usb* 115200; cat /dev/cu.usb* > dump 73 | // tail -f dump | xxd -c 66 | cat -c 74 | // tail -100000f dump | xxd -c 66 | cat -n | awk '{printf "0x%04X", $1; $1=""; print $0}' 75 | // Count number of blocks: 76 | // grep -c "BLOCK " dump 77 | 78 | 79 | // DEFINE CHIP TARGET 80 | // FOR K9F2G08X0M 81 | //#define PAGESIZE 2112 82 | //#define NUMPAGES 131072 // (2048*64) // num of blocks (2048) times pages per block (64) 83 | // FOR K9F1G08U0C 84 | //#define PAGESIZE 2112 85 | //#define NUMPAGES 65536 //(1024*64) // num of blocks (1024) times pages per block (64) 86 | // FOR NAND02G-B2D 87 | //#define PAGESIZE 2112 88 | //#define NUMPAGES (2048*64) // num of blocks (2048) times pages per block (64) 89 | // FOR NAND512W3A2S 90 | //#define PAGESIZE 512 // without spare/oob data 91 | //#define NUMPAGES 131072 // 0x20000 //(4096*32) // num of blocks (4096) times pages per block (32) 92 | // FOR HY27UF082G2B 93 | //#define PAGESIZE 2112 94 | //#define NUMPAGES 131072 // (2048*64) // num of blocks (2038) times pages per block (64) 95 | // FOR MT29F4G08ABBDAH4-IT_D 96 | //#define PAGESIZE 2112 97 | //#define NUMPAGES 262144 // (4096*64) // num of blocks (4096) times pages per block (64) 98 | //Device ID: 2C AC 90 15 56 99 | // FOR MT29F2G08AAD 100 | //#define PAGESIZE 2112 101 | //#define NUMPAGES 131072 // (2048*64) 102 | // FOR MT29F1G08ABA 103 | #define PAGESIZE 2112 104 | #define NUMPAGES 65536 //(1024*64) 105 | //Device ID: 2C F1 80 95 04 106 | 107 | /* 108 | ADDING NEW CHIPS 109 | 110 | 1. Define PAGESIZE and NUMPAGES 111 | Consult the general description of target chip to determine PAGESIZE. 112 | NUMPAGES will often be found in a diagram describing the layout of planes. 113 | This diagram may define "Number of blocks per device". That number * 114 | number of pages per block should give you the total number of pages. 115 | If it helps compare with example datasheets whose chips are defined above. 116 | 117 | 2. Check ADDRESSING format 118 | The address to read from is typically larger than the IO bus so it is 119 | sent in blocks. The mask can be different for different chips. There is 120 | probably a few common formats which we have not defined yet. So compare 121 | the address format with other chips defined here in. For each chip there 122 | is a function for writing the address for that chip that is not used but 123 | can be checked for reference. Each chip will have a table/figure defining 124 | the address layout. You will then need to change the code in 125 | nand_read_page_lp() accordingly. 126 | 127 | Example comparison: 128 | 129 | * K9F1G08X0C 130 | Pins: io0 io1 io2 io3 io4 io5 io6 io7 MASK 131 | 1st Cycle: a0 a1 a2 a3 a4 a5 a6 a7 column & 0xFF 132 | 2nd Cycle: a8 a9 a10 a11 low low low low (column>>8) & 0x0F 133 | 3rd Cycle: a12 a13 a14 a15 a16 a17 a18 a19 page_addr & 0xFF 134 | 4th Cycle: a20 a21 a22 a23 a24 a25 a26 a27 (page_addr>>8) & 0xFF 135 | 136 | The currentcode add's a 5th cycle for page_addr if 137 | NUMPAGES*PAGESIZE > 0x8000000 //128<<20 = 128MiB 138 | 139 | * HY27UF082G2B (x8 bus) 140 | Pins: io0 io1 io2 io3 io4 io5 io6 io7 MASK 141 | 1st Cycle: a0 a1 a2 a3 a4 a5 a6 a7 column & 0xFF 142 | 2nd Cycle: a8 a9 a10 a11 low low low low (column>>8) & 0x0F 143 | 3rd Cycle: a12 a13 a14 a15 a16 a17 a18 a19 page_addr & 0xFF 144 | 4th Cycle: a20 a21 a22 a23 a24 a25 a26 a27 (page_addr>>8) & 0xFF 145 | 5th Cycle: a28 low low low low low low low (page_addr>>16) & 0x01 146 | 147 | * MT29F4G08ABBDAH4-IT_D 148 | NOTE the pin order of the table in doc is reversed (io7 first, io0 last) 149 | not important for comparison or operation of code. We have also changed 150 | the address names slightly. 151 | 152 | Actual doc: 153 | Pins: io0 io1 io2 io3 io4 io5 io6 io7 MASK 154 | 1st Cycle: c0 c1 c2 c3 c4 c5 c6 c7 column & 0xFF 155 | 2nd Cycle: c8 c9 c10 c11 low low low low (column>>8) & 0x0F 156 | 3rd Cycle: p1 p2 p3 p4 p5 p6 b6 b7 page_addr & 0xFF 157 | 4th Cycle: b8 b9 b10 b11 b12 b13 b14 b15 (page_addr>>8) & 0xFF 158 | 5th Cycle: b17 b18 low low low low low low (page_addr>>8) & 0xFF 159 | c=column, p=page, b=block 160 | block addr concated with page addr = actual page addr 161 | if c11==1 c6..10 must be 0 (why?) 162 | 163 | How we compare this with the other chips 164 | Pins: io0 io1 io2 io3 io4 io5 io6 io7 MASK 165 | 1st Cycle: a0 a1 a2 a3 a4 a5 a6 a7 column & 0xFF 166 | 2nd Cycle: a8 a9 a10 a11 low low low low (column>>8) & 0x0F 167 | 3rd Cycle: a12 a13 a14 a15 a16 a17 a18 a19 page_addr & 0xFF 168 | 4th Cycle: a20 a21 a22 a23 a24 a25 a26 a27 (page_addr>>8) & 0xFF 169 | 5th Cycle: a20 a21 low low low low low low (page_addr>>16) & 0x3 170 | 171 | current addressing code in nand_read_page_lp() will already handle this 172 | addressing scheme except for the odd c11==1 condition. If we really needed 173 | to take into account c11==1 (a11 above) the mask in this condition: 174 | 1nd Cycle: if a11==1: column & 0x3F 175 | 2nd Cycle: if a11==1: (column>>8) & 0x8 176 | 177 | */ 178 | 179 | // bit order: lowest i/o bit at io_pins[0] 180 | //int io_pins[] = { PIN_B6 , PIN_B5 , PIN_B1 , PIN_B0 , PIN_F0 , PIN_F1 , PIN_F6 , PIN_F7 }; 181 | //int io_pins[] = { PIN_B0 , PIN_B1 , PIN_B2 , PIN_B3 , PIN_B4 , PIN_B5 , PIN_B6 , PIN_B7 }; // smp d 182 | //int io_pins[] = { PIN_B0 , PIN_B6 , PIN_B5 , PIN_B4 , PIN_B3 , PIN_B7 , PIN_D2 , PIN_D3 }; // mit gina 183 | int io_pins[] = { PIN_D0 , PIN_D1 , PIN_D2 , PIN_D3 , PIN_C4 , PIN_C5 , PIN_C6 , PIN_C7 }; // workshop 184 | int io_pinslen = sizeof(io_pins)/sizeof(io_pins[0]); 185 | 186 | //R/B READY BUSY 187 | // The Ready/Busy output is an Open Drain pin that signals the state of the memory. 188 | //RE READ ENABLE 189 | // The RE input is the serial data-out control, and when active drives the data 190 | // onto the I/O bus. Data is valid tREA after the falling edge of RE which also 191 | // increments the internal column address counter by one. 192 | //CE CHIP ENABLE 193 | // This input controls the selection of the device. 194 | //CLE COMMAND LATCH ENABLE 195 | // This input activates the latching of the IO inputs inside the Command Register 196 | // on the Rising edge of Write Enable (WE). 197 | //ALE ADDRESS LATCH ENABLE 198 | // This input activates the latching of the IO inputs inside the Address Register 199 | // on the Rising edge of Write Enable (WE). 200 | //WE WRITE ENABLE 201 | // This input acts as clock to latch Command, Address and Data. The IO inputs are 202 | // latched on the rise edge of WE. 203 | //WP WRITE PROTECT 204 | // The WP pin, when Low, provides an Hardware protection against undesired modify 205 | // (program / erase) operations. 206 | /*int RB = PIN_C6; 207 | int RE = PIN_C1; 208 | int CE = PIN_C0; 209 | int CLE = PIN_D7; 210 | int ALE = PIN_D6; 211 | int WE = PIN_D1; 212 | int WP = PIN_D0;*/ 213 | 214 | int RB = PIN_F0; // not connected actually 215 | int RE = PIN_F4; 216 | int CE = PIN_F3; 217 | int CLE = PIN_B1; 218 | int ALE = PIN_B0; 219 | int WE = PIN_B3; 220 | int WP = PIN_B2; 221 | 222 | void p(char *fmt, ...); 223 | 224 | void setup (void) { 225 | //pinMode(RB, INPUT); 226 | pinMode(RE, OUTPUT); 227 | pinMode(CE, OUTPUT); 228 | pinMode(CLE, OUTPUT); 229 | pinMode(ALE, OUTPUT); 230 | pinMode(WE, OUTPUT); 231 | pinMode(WP, OUTPUT); 232 | 233 | //Serial.begin(9600); 234 | //Serial.begin(38400); 235 | 236 | // 230400 is the MAX i've been able to get with 16Mhz at 3.3v, and only when doubled from 115200 237 | Serial.begin(115200); 238 | //UCSR0A |= 2; //double the baud to 230400 - doesnt seem to work 239 | //Serial.begin(230400); 240 | //UCSR0A |= 2; //double the baud to 460800 241 | //Serial.begin(460800); 242 | //UCSR0A |= 2; //double the baud to 921600 243 | //Serial.begin(921600); 244 | //UCSR0A |= 2; //double the baud to 1843200 245 | } 246 | 247 | #define CMDLEN 20 248 | char command[CMDLEN]; 249 | int dummy; 250 | void loop () { 251 | #ifdef INTERACTIVE 252 | if (Serial.available()) 253 | { 254 | // READ COMMAND 255 | delay(5); // hoping read buffer is idle after 5 ms 256 | int i = 0; 257 | while (Serial.available() && i < CMDLEN-1) 258 | command[i++] = Serial.read(); 259 | 260 | Serial.flush(); 261 | command[i] = 0; // terminate string 262 | Serial.println(command); // echo back 263 | 264 | // EXECUTE COMMAND 265 | if (strcmp(command, "test") == 0 || strcmp(command, "t") == 0) { 266 | nand_status_verbose(); 267 | } 268 | if (strcmp(command, "readid") == 0 || strcmp(command, "i") == 0) { 269 | nand_reset(); 270 | nand_read_id(); 271 | } 272 | if (strcmp(command, "readid noreset") == 0 || strcmp(command, "I") == 0) { 273 | p("doesnt work\n"); 274 | nand_read_id(); 275 | } 276 | if (strcmp(command, "status") == 0 || strcmp(command, "s") == 0) { 277 | nand_reset(); 278 | nand_status(); 279 | } 280 | if (strcmp(command, "status noreset") == 0 || strcmp(command, "S") == 0) { 281 | p("doesnt work\n"); 282 | nand_status(); 283 | } 284 | if (strcmp(command, "scan pages") == 0 || strcmp(command, "R") == 0) { 285 | for (uint32_t i=0; i<512 /*NUMPAGES*/; i++) { 286 | p("Page %lu: ",i); 287 | nand_reset(); 288 | nand_read_page(i,0,128); 289 | p("\n"); 290 | } 291 | } 292 | if (strcmp(command, "read page") == 0 || strcmp(command, "P") == 0) { 293 | Serial.println("Format of input command is important. '.' ends command."); 294 | Serial.println(" pageN. Dumps full page"); 295 | Serial.println(" pageN,size. Dumps size bytes from page"); 296 | Serial.println(" ,size. Dumps size bytes from all pages"); 297 | Serial.println(" ,size. Dumps size bytes from all pages"); 298 | Serial.println(" . End"); 299 | char page[20]=""; 300 | char size[20]=""; 301 | char *ptr = page; 302 | char c; 303 | while(1) { 304 | c = Serial.read(); 305 | if (c >= '0' && c <= '9') { 306 | *ptr++=c; 307 | } 308 | else if (c == ',') { 309 | *ptr = 0; 310 | ptr = size; 311 | continue; 312 | } 313 | else if (c == '.') { 314 | *ptr = 0; 315 | nand_reset(); 316 | if (strlen(page) > 0 && strlen(size) == 0) { 317 | p("> %s.\n", page); 318 | nand_read_page(atoi(page)); 319 | } 320 | else if (strlen(page) > 0 && strlen(size) > 0) { 321 | p("> %lu,%lu.\n", atoi(page), atoi(size)); 322 | nand_read_page(atoi(page),0,atoi(size)); 323 | } 324 | else if (strlen(page) == 0 && strlen(size) > 0) { 325 | p("> ,%s.\n", size); 326 | for (uint32_t i=0; i "); 336 | } 337 | } 338 | } 339 | Serial.print("\n> "); 340 | } 341 | #else 342 | delay(10000); 343 | for (uint32_t i=0; i>8) & 0xFF); 271 | if (page_addr != -1) { 272 | nand_write_byte( (page_addr) & 0xFF); 273 | nand_write_byte( (page_addr>>8) & 0xFF); 274 | if (NUMPAGES*PAGESIZE > 0x8000000 /*128<<20 = 128MiB*/) 275 | nand_write_byte((page_addr>>16) & 0xFF); //BUGBUG with function argument. signed,unsigned 276 | } 277 | digitalWrite(ALE, LOW); 278 | } 279 | } 280 | void nand_reset () 281 | { 282 | digitalWrite(CE, LOW); // chip on 283 | delay(10); 284 | io_pin_mode(OUTPUT); 285 | // default state: 286 | digitalWrite(WP, LOW); // X 287 | digitalWrite(ALE, LOW); // addr off 288 | digitalWrite(RE, HIGH); // read off 289 | digitalWrite(CE, LOW); // chip on 290 | digitalWrite(WE, LOW); // write off 291 | 292 | digitalWrite(CLE, HIGH); 293 | nand_write_byte(NAND_CMD_RESET); 294 | digitalWrite(CLE, LOW); // CLE off 295 | 296 | delayMicroseconds(500); // tRST = Device Resetting Time (Read/Program/Erase) = max 500us 297 | } 298 | 299 | byte maf_id, dev_id, cellinfo, extid, reserved; 300 | uint32_t writesize, erasesize; 301 | uint16_t oobsize, buswidth; 302 | 303 | void nand_read_id () 304 | { 305 | //io_write_byte(0x00); // not required. was suggested by someone online that looked at some nand chips 306 | delay(10); 307 | digitalWrite(CE, LOW); // chip on 308 | 309 | // nand_command_lp(NAND_CMD_READID, 0x00, -1); 310 | nand_command_lp(NAND_CMD_READID, -1, -1); 311 | digitalWrite(ALE, HIGH); 312 | nand_write_byte(0x00); 313 | digitalWrite(ALE, LOW); 314 | 315 | maf_id = nand_read_byte(); // maker code 316 | dev_id = nand_read_byte(); // device code 317 | 318 | // UBOOT nand_base.c nand_get_flash_type() suggest repeating: 319 | /* Try again to make sure, as some systems the bus-hold or other 320 | * interface concerns can cause random data which looks like a 321 | * possibly credible NAND flash to appear. If the two results do 322 | * not match, ignore the device completely. 323 | */ 324 | // nand_command_lp(NAND_CMD_READID, 0x00, -1); 325 | nand_command_lp(NAND_CMD_READID, -1, -1); 326 | digitalWrite(ALE, HIGH); 327 | delay_test(); 328 | nand_write_byte(0x00); 329 | delay_test(); 330 | digitalWrite(ALE, LOW); 331 | delay_test(); 332 | byte maf_verify = nand_read_byte(); // maker code 333 | byte dev_verify = nand_read_byte(); // device code 334 | if (maf_verify != maf_id || dev_verify != dev_id) { 335 | p("second ID read did not match " 336 | "%02x,%02x against %02x,%02x\n", maf_id, dev_id, maf_verify, dev_verify); 337 | digitalWrite(CE, HIGH); // chip off 338 | return; 339 | } 340 | cellinfo = nand_read_byte(); // 3rd 341 | extid = nand_read_byte(); // 4th 342 | reserved = nand_read_byte(); // 5th 343 | p("Your device ID: %02X %02X %02X %02X %02X \n", maf_id, dev_id, cellinfo, extid, reserved); 344 | p("\ntested...\n"); 345 | p("K9F2G08X0M: EC DA 80 15 50\n"); 346 | p("NAND02GW3B2D: 20 DA 10 95 44\n"); 347 | p("HY27UF082G2B: AD DA 10 95 44\n"); 348 | p("NAND512W3A2S: 20 76\n"); 349 | p("\nvia docs...\n"); 350 | p("K9F1G08U0C: EC F1 00 95 40\n"); 351 | p("K9F2G08U0M: EC DA 80 15\n"); 352 | p("K9F2G16U0M: EC CA 80 55\n"); 353 | p("K9F2G08U0C: EC DA 10 15 44\n"); 354 | 355 | 356 | const nand_flash_dev *type = nand_flash_ids; 357 | for (; type->name != NULL; type++) 358 | if (maf_id == type->id) 359 | break; 360 | const nand_manufacturers *maf = nand_manuf_ids; 361 | for (; maf->id != 0; maf++) 362 | if (maf_id == maf->id) 363 | break; 364 | 365 | p("\nExtended details\n"); 366 | p("%s: %s\n\n", maf->name, type->name); 367 | 368 | printbin(extid); p(" Extid (4thbyte %02X):\n", extid); 369 | 370 | if (!type->pagesize) { 371 | /* Calc pagesize */ 372 | writesize = 1024 << (extid & 0x03); 373 | extid >>= 2; 374 | /* Calc oobsize */ 375 | oobsize = (8 << (extid & 0x01)) * (writesize >> 9); 376 | extid >>= 2; 377 | /* Calc blocksize. Blocksize is multiples of 64KiB */ 378 | //erasesize = (64 * 1024) << (extid & 0x03); 379 | erasesize = 65536 << (extid & 0x03); // on AVR 64*1024=1 instead of 65536 380 | extid >>= 2; 381 | /* Get buswidth information */ 382 | buswidth = (extid & 0x01) ? 16 : 8; 383 | p(" Pagesize %lu bytes + OBB %u\n", writesize, oobsize); 384 | p(" Blocksize %lu bytes (%uKB)\n", erasesize, erasesize/1024); 385 | p(" Buswidth %u bits\n", buswidth); 386 | } 387 | else { 388 | erasesize = type->erasesize; 389 | writesize = type->pagesize; 390 | //oobsize = type->writesize / 32; 391 | buswidth = 8; // only supporting 8 bit atm. type->options & NAND_BUSWIDTH_16; 392 | p(" Pagesize %lu bytes\n", writesize); 393 | p(" Blocksize %lu bytes (%uKB)\n", erasesize, erasesize/1024); 394 | p(" Buswidth %u bits\n", buswidth); 395 | } 396 | digitalWrite(CE, HIGH); // chip off 397 | } 398 | 399 | void nand_status () 400 | { 401 | io_pin_mode(OUTPUT); 402 | digitalWrite(CE, LOW); // chip o 403 | delay(10); 404 | 405 | digitalWrite(CLE, HIGH); 406 | nand_write_byte(NAND_CMD_STATUS); 407 | digitalWrite(CLE, LOW); 408 | 409 | io_pin_mode(INPUT); 410 | int input[5]; 411 | input[0] = nand_read_byte(); 412 | 413 | p(" 0x%02x\n", input[0]); 414 | printbin(input[0]); 415 | 416 | digitalWrite(CE, HIGH); // chip off 417 | } 418 | void nand_status_verbose () 419 | { 420 | printbin(NAND_CMD_STATUS); 421 | io_pin_mode(OUTPUT); 422 | digitalWrite(CE, LOW); // chip o 423 | delay(10); 424 | 425 | digitalWrite(CLE, HIGH); 426 | nand_write_byte(NAND_CMD_STATUS); 427 | digitalWrite(CLE, LOW); 428 | 429 | io_pin_mode(INPUT); 430 | int input[5]; 431 | input[0] = nand_read_byte(); 432 | 433 | p(" 0x%02x\n", input[0]); 434 | printbin(input[0]); 435 | 436 | digitalWrite(CE, HIGH); // chip off 437 | } 438 | 439 | // DETAILS FOR K9F2G08X0M 440 | // 1 page is 2112 bytes 441 | // 1 block is 64 pages... hence 442 | // 1 block is 135168 bytes 443 | // Total blocks = 2048 444 | // Total pages = 131072 445 | // Total bytes = 276824064 2Mbits 446 | // Address size for cols is 12bit (4096) 447 | // Address size for rows is 17bit 448 | void K9F2G08X0M_write_addr (uint32_t page, uint16_t col) 449 | { 450 | p("addr %i,%i\n", page, col); 451 | nand_write_byte(col & 0xFF); 452 | nand_write_byte((col>>8) & 0xF); 453 | nand_write_byte(page & 0xFF); 454 | nand_write_byte((page>>8) & 0xFF); 455 | nand_write_byte((page>>16) & 0x1); 456 | } 457 | 458 | // DETAILS FOR K9F1G08U0C 459 | //(2K+64)Byte 2048+64 2112 page size 460 | //(128K+4K)Byte 1024*128+(1024*4) 135168 block size 461 | // 1 page is 2112 bytes (2048+64) 462 | // 1 block is 64 pages... hence 463 | // 1 block is 135168 bytes 464 | // Total blocks = 1024 465 | // Total pages = 65536 (1024*64) < 466 | // Total bytes = 138412032 1Mbits 467 | // addressing: 468 | // "row" = page 469 | // "col" = byte in row 470 | // Address size for cols is 12bits (4096) enough for 2112 471 | // Address size for rows is 16bits (65536) enough for all pages. 472 | // read operations are page basis 473 | void K9F1G08U0C_write_addr (uint32_t page, uint16_t col) 474 | { 475 | nand_write_byte(col & 0xFF); 476 | nand_write_byte(col>>8 & 0xF ); 477 | nand_write_byte(page & 0xFF); 478 | nand_write_byte(page>>8 & 0xFF); 479 | } 480 | // DETAILS FOR NAND02G-B2D 8BIT 481 | // 1 page is 2112 bytes (2048+64) 482 | // 1 block is 64 pages... hence 483 | // 1 block is 135168 bytes 484 | // Total blocks = 2048 485 | // Total pages = 131072 (2048*64) < 486 | // Total bytes = 276824064 2Gbits 487 | // addressing VERY DIFFERNT but probably works just as well 488 | // Address size for cols is 12bit (4096) 489 | // Address size for rows is 17bit 490 | void NAND02GB2D_write_addr (uint32_t page, uint16_t col) 491 | { 492 | nand_write_byte(col & 0xFF); 493 | nand_write_byte((col>>8) & 0xF); 494 | nand_write_byte(page & 0xFF); 495 | nand_write_byte((page>>8) & 0xFF); 496 | nand_write_byte((page>>16) & 0x1); 497 | } 498 | // DETAILS FOR NAND512W3A2S 499 | // 1 page is 528 bytes (512+16) 500 | // 1 block is 32 pages... hence 501 | // 1 block is 16896 bytes (without oob 502 | // Total blocks = 4096 503 | // Total pages = 131072 (4096*32) 504 | // Total bytes = 69206016 512Mbits (4096*32*528) 505 | // addressing: 506 | // Address size for cols is 507 | // Address size for rows is 508 | void NAND512W3A2S_write_addr (uint32_t page, uint16_t col) 509 | { 510 | nand_write_byte(col & 0xFF); 511 | col>>=1; // the 9th bit gets send in the command before address!! 512 | nand_write_byte((col>>8) & 0xFF); 513 | nand_write_byte(page & 0xFF); 514 | nand_write_byte((page>>8) & 0x1); 515 | } 516 | 517 | void nand_read_page(uint32_t page, uint16_t col, uint16_t size) 518 | { 519 | digitalWrite(CE, LOW); // chip on 520 | delay(1); 521 | 522 | nand_command_lp(NAND_CMD_READ0, col, page); 523 | nand_command_lp(NAND_CMD_READSTART, -1, -1); 524 | 525 | int thresh=150; // will wait 150*10, aka 1.5 milisecond 526 | while (digitalRead(RB) && thresh--) delayMicroseconds(1); // loop until RB=LOW, ready 527 | delayMicroseconds(25); // tR = Data Transfer from Cell to Register tR = 25us max 528 | 529 | byte input[PAGESIZE]; 530 | for (int i=0; i= 32 && input[i] <= 126) || input[i] == 9/*\t*/|| input[i] == 10/*\n*/ || input[i] == 13/*\n*/ ) // only check printable text 546 | p("%c", input[i]); 547 | //else 548 | // p(" "); 549 | } 550 | p("\n"); 551 | #else 552 | #ifdef PRINTBLOCKIDENT 553 | p("BLOCK %025lu\n", page); // prints a marking of exactly 32 bytes (including \n) 554 | #endif 555 | for (uint16_t i=0; i