Hello, I am using Arduino UNO as a master and try to write and read data from 1GB NAND flash memory(MT29F1G01ABBFDSF // micron).
I am trying to write 0x00 to certain page(page #1, block #36). However, whenever I tried to read the data, the device kept returning 0xFF.
Plus, I was trying to disable block protection in void flash_reset() function,
Please kindly give your advice if I misunderstand anything.
// NAND FLASH SPI SETTING
// Master Device Setup
/* PAGE READ SEQUENCE
• 13h (PAGE READ command to cache) followed by 24-bit address
• 0Fh (GET FEATURES command to read the status) followed by 8-bit status register address
• 03h or 0Bh (READ FROM CACHE) followed by 4-bit dummy, 12-bit column address, 8-bit dummy
• 3Bh (READ FROM CACHE x2)
• 6Bh (READ FROM CACHE x4)
• BBh (READ FROM CACHE Dual I/O)
• EBh (READ FROM CACHE Quad I/O)
PAGE PROGRAM SEQUENCE
• 06h (WRITE ENABLE command)
• 02h (PROGRAM LOAD command)
• 10h (PROGRAM EXECUTE command)
• 0Fh (GET FEATURES command to read the status)
*/
#include <SPI.h>
#define CLOCK_SPEED 8000000
#define CS 10 // Chip select
#define COM_RESET 0xFF
#define COM_READ_ID 0x9F
#define COM_PAGE_READ 0x13 // Transfer data from the NAND Flash array to the cache register
#define COM_READ_FROM_CACHE 0x03 // Enable sequential reading from the cache buffer
#define COM_WRITE_ENABLE 0x06 // Enable PAGE PROGRAM OTP AREA PROGRAM, BLOCK ERASE
#define COM_WRITE_DISABLE 0x04 // Disable PAGE PROGRAM OTP AREA PROGRAM, BLOCK ERASE
#define COM_BLOCK_ERASE 0xD8
#define COM_PROGRAM_LOAD 0x02 // Erase(set all bits to 1) and write and move data bytes to the cache register (2176 bytes long)
#define COM_PROGRAM_EXECUTE 0x10 // Transfer data from cache register to the main array. Busy for T_PROG
#define COM_GET_FEATURES 0x0F
#define COM_SET_FEATURES 0x1F
#define READ_BLOCK_STATUS 0xA0
#define READ_CFG_STATUS 0xA0
#define READ_STATUS 0xC0
#define COM_UNLOCK_ALL 0x00
#define COM_LOCK_ALL 0xFF
#define COM_BLOCK_ERASE 0xD8
#define DUMMY_BYTE 0x00 // 0000 0000 Dummy
#define ROW_ADD_1 0x08 // 0000 1000 Block 36
#define ROW_ADD_2 0x80 // 1000 0000 Page 1
#define COL_ADD_1 0x00 // Dummy bits + byte 0
#define COL_ADD_2 0x00 // Addressable up to 1000 0111 1111 (~ 2175 bytes)
#define TIME_POR 1000
#define TIME_CS 500 // Command deselect time
#define TIME_RD 500 // Read time
#define PAGE_NUM 2176
void setup() {
Serial.begin(9600);
SPI.begin();
SPI.beginTransaction(SPISettings(CLOCK_SPEED, MSBFIRST, SPI_MODE0));
SPCR |= _BV(MSTR); // Master Setting
digitalWrite(CS, HIGH);
}
void loop() {
flash_reset();
delay(TIME_POR); // reset command requires settling time(t_por). GET_FEATURES command could be issued during this time.
read_id();
delay(TIME_POR);
block_erase();
delay(TIME_POR);
page_program();
delay(TIME_POR);
page_read();
delay(TIME_POR);
while(true){
// Do nothing.
}
}
void flash_reset(){
byte block_status;
byte cfg_status;
byte sr_status;
Serial.println("Resetting the device..");
/*
// 1. Reset device
digitalWrite(CS, LOW);
SPI.transfer(COM_RESET);
digitalWrite(CS, HIGH);
*/
// 2. Write Enable
digitalWrite(CS, LOW);
SPI.transfer(COM_WRITE_ENABLE);
digitalWrite(CS, HIGH);
// 3. Unlock Block Protection
digitalWrite(CS, LOW);
SPI.transfer(COM_SET_FEATURES);
SPI.transfer(READ_BLOCK_STATUS);
SPI.transfer(COM_UNLOCK_ALL);
digitalWrite(CS, HIGH);
// 4. Read Status register
digitalWrite(CS, LOW);
SPI.transfer(COM_GET_FEATURES);
SPI.transfer(READ_BLOCK_STATUS);
block_status = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
SPI.transfer(COM_GET_FEATURES);
SPI.transfer(READ_CFG_STATUS);
cfg_status = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
digitalWrite(CS, LOW);
SPI.transfer(COM_GET_FEATURES);
SPI.transfer(READ_STATUS);
sr_status = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
Serial.print("Block Status: ");
Serial.println(block_status, BIN);
Serial.print("CFG Status: ");
Serial.println(cfg_status, BIN);
Serial.print("SR Status: ");
Serial.println(sr_status, BIN);
}
void read_id(){
uint16_t manufacture_ID;
uint16_t device_ID;
byte read_status;
digitalWrite(CS, LOW);
SPI.transfer(COM_READ_ID);
SPI.transfer(DUMMY_BYTE);
manufacture_ID = SPI.transfer(0xFF);
device_ID = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
Serial.print("Manufacture ID: ");
Serial.println(manufacture_ID, HEX);
Serial.print("Device ID: ");
Serial.println(device_ID, HEX);
}
void block_erase(){
byte read_status;
// 1. Write Enable
digitalWrite(CS, LOW);
SPI.transfer(COM_WRITE_ENABLE);
digitalWrite(CS, HIGH);
// 2. Block Erase, 24-bit address (8bits dummy + 16bits RA)
digitalWrite(CS, LOW);
SPI.transfer(COM_BLOCK_ERASE);
SPI.transfer(DUMMY_BYTE);
SPI.transfer(ROW_ADD_1);
SPI.transfer(ROW_ADD_2);
delay(TIME_CS);
digitalWrite(CS, HIGH);
// 3. Get Features
digitalWrite(CS, LOW);
SPI.transfer(COM_GET_FEATURES);
SPI.transfer(READ_STATUS);
read_status = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
Serial.print("Status after erasing: ");
Serial.println(read_status, BIN);
}
void page_program(){
byte my_data = 0x00;
byte read_status;
Serial.println("Programming pages...");
delay(1000);
// 1. Write Enable
digitalWrite(CS, LOW);
SPI.transfer(COM_WRITE_ENABLE);
digitalWrite(CS, HIGH);
// 2. Program Load, 16-bit address (4bits dummy + 12bits CA)
digitalWrite(CS, LOW);
SPI.transfer(COM_PROGRAM_LOAD);
SPI.transfer(COL_ADD_1);
SPI.transfer(COL_ADD_2);
for(int page = 0; page < PAGE_NUM; page++){
SPI.transfer(my_data);
}
digitalWrite(CS, HIGH);
// 3. Program Execute, 24-bit address (8bits dummy + 16bits RA)
digitalWrite(CS, LOW);
SPI.transfer(COM_PROGRAM_EXECUTE);
SPI.transfer(DUMMY_BYTE);
SPI.transfer(ROW_ADD_1);
SPI.transfer(ROW_ADD_2);
delay(TIME_CS);
digitalWrite(CS, HIGH);
// 4. Get Features
digitalWrite(CS, LOW);
SPI.transfer(COM_GET_FEATURES);
SPI.transfer(READ_STATUS);
read_status = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
Serial.print("Status after program: ");
Serial.println(read_status, BIN);
}
void page_read(){
byte my_rx;
byte read_status;
// 1. Page Read (13h), 24-bit addressing (8bits dummy + 16bits RA)
digitalWrite(CS, LOW);
SPI.transfer(COM_PAGE_READ);
SPI.transfer(DUMMY_BYTE);
SPI.transfer(ROW_ADD_1);
SPI.transfer(ROW_ADD_2);
delay(TIME_RD);
digitalWrite(CS, HIGH);
// 2. Get Features
digitalWrite(CS, LOW);
SPI.transfer(COM_GET_FEATURES);
SPI.transfer(READ_STATUS);
read_status = SPI.transfer(0xFF);
digitalWrite(CS, HIGH);
Serial.print("Status before reading: ");
Serial.println(read_status, BIN);
// 3. Read from Cache, 16-bit addressing (4bits wrap + 12bits CA) + following 8bits dummy
digitalWrite(CS, LOW);
SPI.transfer(COM_READ_FROM_CACHE);
SPI.transfer(COL_ADD_1);
SPI.transfer(COL_ADD_2);
SPI.transfer(DUMMY_BYTE);
for(int pos = 0; pos < PAGE_NUM; pos++){
my_rx = SPI.transfer(0xFF);
if(pos%20 == 0){
Serial.println("");
}
Serial.print(my_rx, HEX);
Serial.print(" ");
}
digitalWrite(CS, HIGH);
}