NAND flash support in 1.54

It looks like its persisting. Have to go through you code to see what you did. Right now it looks like its only works if you stay on 1 page. Try this:
Code:
  //Serial.println("Test Write");
  for (uint16_t i = 0; i < 4096; i++) buffer[i] = 42;
  //myNAND.writeBytes(20480, buffer, 4096);
  //myNAND.writeBytes(20480, buffer, 16);

  Serial.println();
  Serial.println("Test Read");
  memset(buffer, 0xFF, 4096);
  myNAND.readBytes(20480, buffer, 4096);
  for (uint16_t i = 0; i < 4096; i++) {
    Serial.printf("0x%02x, ", buffer[i]); Serial.print(", ");
    if(i == 2048) { Serial.println();Serial.println();}
    if(i % 20 == 0) Serial.println();
  }
 
Staying with a single page write to try and tackle one issue at a time. There's something address related to the odd/even pages.
Code:
  uint8_t page = 2;

  Serial.println("Non-Zero Test Write");
  for (uint16_t i = 0; i < 2048; i++) buffer[i] = page;
  myNAND.writeBytes(2048 * page, buffer, 16);

  Serial.println();
  Serial.println("Non-Zero Test Read");
  memset(buffer, 0xFF, 2048);
  myNAND.readBytes(2048 * page, buffer, 2048);

  Serial.println();
  for (uint16_t j = 0; j < 8; j++) {
    for (uint16_t i = 0; i < 16; i++) {
      Serial.printf("0x%02x, ", buffer[j * 16 + i]);
    } Serial.println();
  }

page = 1; 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
page = 2; 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
page = 3; 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
page = 4; 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,

page = 10; 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
page = 11; 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

EDIT: with 128 byte writes:
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
Last edited:
Hmm, the column address is 12 bits, but it only "needs" 11 (maybe so you can access the ECC data?) But that means there's no continuous addresses.
 
I thought it was broken when I tried to set Column bits to 11 but I think I had just messed up the ECC during my previous testing. So I think that will work with the caveat that we'll have to do some special case code if we ever want to directly interact with the on chip ECC storage.

Non-Zero Test Read

0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

View attachment NAND_SPI_TEST_7_16.zip
 
Doesnt looking like its working for me. I ran this in the setup:
Code:
  uint8_t page = 1;

  Serial.println("Non-Zero Test Write");
  for (uint16_t i = 0; i < 2048; i++) buffer[i] = i;
  myNAND.writeBytes(2048 * page, buffer, 128);

  Serial.println();
  Serial.println("Non-Zero Test Read");
  memset(buffer, 0xFF, 2048);
  myNAND.readBytes(2048 * page, buffer, 2048);
and got this:
Code:
Begin Init

Found W25N01G Flash Chip

Status of reg 0xa0: 
(HEX: ) 0x00, (Binary: )0

Status of reg 0xb0: 
(HEX: ) 0x18, (Binary: )11000

Non-Zero Test Write
writeBytes: 2048, 536875068, 128
writeBytes 2: 2048, 536875068, 128

Non-Zero Test Read
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x08, 0x08, 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x0a, 
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x08, 0x08, 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x0a, 
0x20, 0x20, 0x22, 0x22, 0x20, 0x20, 0x22, 0x22, 0x28, 0x28, 0x2a, 0x2a, 0x28, 0x28, 0x2a, 0x2a, 
0x20, 0x20, 0x22, 0x22, 0x20, 0x20, 0x22, 0x22, 0x28, 0x28, 0x2a, 0x2a, 0x28, 0x28, 0x2a, 0x2a, 
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x08, 0x08, 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x0a, 
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x08, 0x08, 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x0a, 
0x20, 0x20, 0x22, 0x22, 0x20, 0x20, 0x22, 0x22, 0x28, 0x28, 0x2a, 0x2a, 0x28, 0x28, 0x2a, 0x2a, 
0x20, 0x20, 0x22, 0x22, 0x20, 0x20, 0x22, 0x22, 0x28, 0x28, 0x2a, 0x2a, 0x28, 0x28, 0x2a, 0x2a, 
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
 
Try erasing sector 0 (or the entire chip) first. The addressing was changed so it's unclear what would have been on there previously.
 
Try erasing sector 0 (or the entire chip) first. The addressing was changed so it's unclear what would have been on there previously.

Ok that got it:
Code:
Non-Zero Test Read
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 
Excellent. Hopefully that will be enough of a working baseline to build up the missing features.

Oh definitely!

Made that CAS(11) change and programExecute change and its now working with my version of readBytes/writeBytes! Going to do some testing and then post it and you can see what you think.

Can't believe that simple change from 12 to 11 resolved the issue, never would have guessed.

EDIT: the version i have has a few more features like checking ECC block and BBLut table.
 
With myNAND.eraseSector(0); I can put the values of choice on that page.

Looks similar to @mjs513 with ::
Code:
  for (uint16_t i = 0; i < 2048; i++) buffer[i] = i%256;//page;
  const uint8_t beefy[] = {[B]0xD, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF, 0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf[/B]};
  for (uint16_t i = 256, jj=0; i < 256+16; i++,jj++) buffer[i] = beefy[jj];//page;
  myNAND.writeBytes(2048 * page, buffer, 256+16);

Then ran the output to 17 sets of 16:
Code:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 
[B]0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0x0e, 0x0f, 0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0x0e, 0x0f[/B],
 
There's a bug I forgot to mention in setTimeout / waitForReady. It should probably be updated to just use an ElapsedMillis object and a numerical timeout value? Anyway the version in GitHub is wrong.
 
Cool - good to see PROOF of life - though the illusion looked good while it lasted :)

Updated from github - old sketch gone - have new folder with examples.

So the Block format/Erase is not native to the write? That sounds like some overhead of buffer read - data merge in RAM - Erase the area - write the data? Paul does this 'in some more extraordinary' fashion for EEPROM.

Device Erase is Per Page IIRC? NOT :: "Unfortunately erase is per block"

For posterity: NAND is pages (2048 Bytes) per block*block on die == 134217728 Bytes or 0x8000000
Code:
// Device size parameters
#define PAGE_SIZE         2048
#define PAGE_ECCSIZE	  2112
#define PAGES_PER_BLOCK   64
#define BLOCKS_PER_DIE    1024

Would be interesting to mock up a startup.c equivalent configure_external_ram() for NAND (NOR) when (external_psram_size <= 8) - {inbuilt version of myNAND.begin(); }: Not sure if Paul will want that directly on startup - but as a FileSystem becomes a thing - it will need that - and maybe integrated?

BTW: Good news - confirmed this with last code sketch rename :: the TSET edit to hardcode a 'suggested' INO detects that sketch name not existing and then does the old school INO search.
 
Last edited:
There's a bug I forgot to mention in setTimeout / waitForReady. It should probably be updated to just use an ElapsedMillis object and a numerical timeout value? Anyway the version in GitHub is wrong.

More like these two lines when swapped?
Code:
[B]    uint32_t now = millis();[/B] // outside while()
  while (!w25n01g_t4::isReady()) {
 
Unfortunately erase is per block, so it has to be separate from the write.
setTimeout() is treating timeoutAt as a time, but waitForReady() is using it as if it was a period.
 
Unfortunately erase is per block, so it has to be separate from the write.
setTimeout() is treating timeoutAt as a time, but waitForReady() is using it as if it was a period.

Bummer - Blocks are like 64 times bigger!

You are correct on the timeoutAt usage.

Also it would NEVER timeout as NOW always equals millis() inside that while(), so it will be zero or at most 1:
Code:
void w25n01g_t4::setTimeout(uint32_t timeoutMillis)
{
  uint32_t now = millis();
  timeoutAt = now + timeoutMillis;
}

void w25n01g_t4::deviceReset()
{
  flexspi_ip_command(9, flashBaseAddr); //reset

  setTimeout(TIMEOUT_RESET_MS);
  waitForReady();
...
}

bool w25n01g_t4::waitForReady()
{
  while (!w25n01g_t4::isReady()) {
[B][COLOR="#FF0000"]    uint32_t now = millis();
[/COLOR][/B]    //if (now >= timeoutAt) {
    if (millis() - now >= timeoutAt) {
      return false;
    }
  }
  timeoutAt = 0;

  return true;
}
 
ecurtz said:
There's a bug I forgot to mention in setTimeout / waitForReady. It should probably be updated to just use an ElapsedMillis object and a numerical timeout value? Anyway the version in GitHub is wrong.
Yep - keep forgetting about that one - probably because of the other issues. Just woke up so now time to get that fixed.

Unfortunately erase is per block, so it has to be separate from the write.
Yeah - block erase is separate instruction from write's. From the datasheet all erases are in 128Kbyte chunks or 64 pages as already stated. All it does is to cells to 0xff's. So if you want to erase a smaller size you have to do it manually.

Also going to be looking at returning some values from the function if you want to use them in your sketch but think that may be later project.
 
Yeah - block erase is separate instruction from write's. From the datasheet all erases are in 128Kbyte chunks or 64 pages as already stated. All it does is to cells to 0xff's. So if you want to erase a smaller size you have to do it manually.

Unfortunately that's not how NAND flash works, you can clear bits from a 1 to 0 but not the other way, so you can't erase a single page, you have to use the block erase command.
 
Unfortunately that's not how NAND flash works, you can clear bits from a 1 to 0 but not the other way, so you can't erase a single page, you have to use the block erase command.

Hmm interesting. Reading the datasheet that was how I was interpreting it:
The 128KB Block Erase instruction sets all memory within a specified block (64-Pages, 128K-Bytes) to the erased state of all 1s (FFh).
But there are alot of things i dont know about this chip.
 
Ok just pushed a change to the lib.

Added an example of writing a structure to the chip. PS: if you are going to logger you will need to self manage to write a buffer of multiple of 2048's. Easiest way.

Also found setting CAS makes things worse.
 
If CAS isn't set, isn't it going to fail on any address with bit 12 set because those aren't real pages, but ECC sections? What issue were you trying to fix with that change?
 
If CAS isn't set, isn't it going to fail on any address with bit 12 set because those aren't real pages, but ECC sections? What issue were you trying to fix with that change?

Was experimenting as a result of getting ecc errors on reads. For instance: alot of times with the arrays i was using I would get an ecc error on the read with setting of 0x18 (looks like it was 16_bits plus 8_bits for Dummy, just guessing when bouncing against the data sheet). If i then changed it to 0x20 no ecc errors and would read no problem. But wouldn't save on power off. Just experimenting and looks like 16 would work as well.

Note will work with 11 but when bouncing against the data sheets page and column addressing is suppose to be 16-bits? Looked like 16 would work as well. Think it went back to reading the datasheet that said CAS is 12-bit. Again was experimenting to see what would happen. Its one way to see the effect of the settings.
 
This is how I understand it. Any of this could be wrong.

On the 1062 side
CAS is where the 1062 divides a 32 bit address into the column and the page.
The value in the LUT defines how many bits are actually sent, so if it's larger than CAS for a CADDR_SDR command (or larger than 32 - CAS for a ADDR_SDR) it will be 0 padded.

On the NAND side
Each page contains 2048 bytes of data plus 64 bytes of ECC data.
Any column address with bit 11 set isn't addressing data, it's addressing the ECC block after the data, so e.g.
address 2050 (0b1000 0000 0000 0010) isn't byte 2 in page 1, it's part of the page 0 ECC

If this is correct then any scheme that tries to use continuous addresses without some kind of accommodation for the ECC regions is going to break. By setting CAS to 11 I believe we can work around that, with the potential downside that we can't directly access the ECC data areas, but that shouldn't be necessary if the onboard ECC is enabled for the chip.
 
Back
Top