Hi kerryzhou,
Sure -
One more piece of information, I contacted the Toshiba reps and they confirmed that the Toshiba NAND FLASH requires setting the page before reading. Here is what I said when I asked if set page was required before read:
Correct. The serial NAND buffer won’t have valid data in it until the read cell array command finishes executing correctly (assuming no uncorrectable ECC errors).
There is no autoloading of a page out of reset
And from their manual (note that you have to wait for busy after set page (AKA "Read Cell Array"):

To your questions - here is the code for both:
int testErase(uint8_t *post_erase_read_buffer, uint8_t *s_nand_program_buffer){
status_t status;
#ifdef TEST_AHB_READ
uint32_t flashBaseAddress = EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_BLOCK_TO_ERASE * BLOCK_SIZE;
#endif
/* Erase */
status = flexspi_nand_flash_erase_block(EXAMPLE_FLEXSPI, EXAMPLE_BLOCK_TO_ERASE * BLOCK_SIZE);
if (status != kStatus_Success) {
//Erase Failed
return -1;
}
delay();
#ifndef TEST_AHB_READ
status = flexspi_nand_flash_read_block(EXAMPLE_FLEXSPI, 0x00000000, (uint32_t*) &post_erase_read_buffer[0], FLASH_PAGE_SIZE);
if (status != kStatus_Success) {
return -1;
}
#else
// AHB read doesn't work until we have set page in AHB somehow...
DCACHE_CleanInvalidateByRange(flashBaseAddress, FLASH_PAGE_SIZE);
memcpy(post_erase_read_buffer, (void *)(flashBaseAddress), FLASH_PAGE_SIZE);
#endif
memset(s_nand_program_buffer, 0xFFU, FLASH_PAGE_SIZE);
if (memcmp(s_nand_program_buffer, post_erase_read_buffer, FLASH_PAGE_SIZE)) {
//Erase Failed
return -1;
}
delay();
return 0;
}
where if i do a #define TEST_AHB_READ 1 - then it tests the AHB read, otherwise it uses the API "manual" read -note that i'm using ifNOTdefined above in the 2nd #if.
Here's the manual read block function:
status_t flexspi_nand_flash_read_block(FLEXSPI_Type *base, uint32_t addr, uint32_t *data, uint32_t byteCount){
status_t status;
flexspi_transfer_t flashXfer;
status = flexspi_nand_wait_bus_busy(base);
if (status != kStatus_Success) {
return status;
}
//set page:
flashXfer.deviceAddress = addr & 0xFFFF8000;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Command;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NAND_CMD_LUT_SEQ_IDX_READ_PAGE;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nand_wait_bus_busy(base);
if (status != kStatus_Success) {
return status;
}
//read flash:
flashXfer.deviceAddress = addr & 0x00007FFF;
flashXfer.port = kFLEXSPI_PortA1;
flashXfer.cmdType = kFLEXSPI_Read;
flashXfer.SeqNumber = 1;
flashXfer.seqIndex = NAND_CMD_LUT_SEQ_IDX_READ_FROM_CACHE;
flashXfer.data = data;
flashXfer.dataSize = byteCount;
status = FLEXSPI_TransferBlocking(base, &flashXfer);
if (status != kStatus_Success) {
return status;
}
status = flexspi_nand_wait_bus_busy(base);
return status;
}
I also have a testProgram that runs after testErase.
Results are:
Out of reset - if i run with TEST_AHB_READ undefined, then this test passes (I read back 0xFF's).
Out of reset - if I run with TEST_AHB_READ 1, then this test fails (might read back what was programmed in previously, etc).
Also - if i remove the #ifndef's all together- meaning I run the manual API read command, immediately followed by the AHB read command via memcpy - then the test passes because the manual read command set the page in FLASH so that all subsequent reads are reading from the correct page.
If I reverse the order with the #ifndef's removed - then the data loaded in my memcpy will be incorrect, but then it will be overwritten by the flexspi_nand_flash_read_block call.