Pages: [1] 2 3   Go Down
Author Topic: [Solved] Flash Memory Programmer "AM29F040B"  (Read 4055 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

This is my first post in arduino forum, and I'm very glad to use this great device.
I have used arduino a couple of months, I have made a different projects using it, such as (Car robot, little Game Console with 3310 LCD ...).
Now, Searching for new project and especially in GameBoy console, I have found that some people have made programmable gameboy cartridge, changing its Rom and replace it with AM29F040 Flash Memory. So, I decided to make a one for me too.

Before I  purchased this Flash memory "AM29F040B", I did some research on internet to be sure if it's possible to replace the gameboy cartridge ROM with this Flash Mem. The answer was yes.

This Flash memory has 32 pins, and arduino UNO has just 11 pins without using the 0 & 1 (for some Serial problem reasons), and A0 to A6 for the analog pins.
To come to this lack of pins, Shift registers should be used, therefore, I bought 2 shift registers (74HC595) and wire them in cascading which will give us 16 outputs

After that, the big problem has appeared: How can I Read/Write/Erase this memory  using Arduino since it's so versatil, cheap and easy to use. (Programmers are so expensive).

I read some replies from people in some forums, they claimed that arduino UNO which I use, is not fast enough to drive correctly AM29F040B (because arduino can't drive 20ns or something like that), in other hand some others confirm that's possible to do.

I have read the datasheet but my weakness is the Timing Diagram (I'm not an electronic engineer) I can't understand it correctly, which means that I can't write a functionnal code.

Below, Is the circuit:

Arduino pin 10 -> Shift Register Serial Data
Arduino pin 11 -> Latch pin (SR)
Arduino pin 12 -> Serial Clock (SR)

Arduino pin 2 to 9 -> Flash memory D0 - D7

Arduino A0 -> Flash memory pin 18
Arduino A1 -> Flash memory pin 17
Arduino A2 -> Flash memory pin 16
Arduino A3 -> Flash memory WE#
Arduino A4 -> Flash memory OE#
Arduino A5 -> Flash memory CE#

Shift Register 1 Q0 - Q7 -> Flash memory A0 - A7
Shift Register 2 Q0 - Q7 -> Flash memory A8 - A15

And here is the code to read the memory (Don't know if it's correct or not):

Code:
#define SERIALDATA 10
#define SERIALCLK 12
#define STORECLK 11

#define WE A3
#define OE A4
#define CE A5

#define OUT 0
#define IN  1

unsigned int addr = 0;
byte data = 0;
int counter = 0;
boolean val = LOW;

void ChangeMode(byte io)
{
  if (io) {
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    pinMode(4, INPUT);
    pinMode(5, INPUT);
    pinMode(6, INPUT);
    pinMode(7, INPUT);
    pinMode(8, INPUT);
    pinMode(9, INPUT);
  }
  else
  {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
  }
}

void setup()
{
  Serial.begin(19200);
  //Data read or write D0 - D7 - Pin9 - Pin2
  ChangeMode(IN);
  
  //Shiftregister pins
  pinMode(STORECLK, OUTPUT);
  pinMode(SERIALCLK, OUTPUT);
  pinMode(SERIALDATA, OUTPUT);
  
  //Command register
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(CE, OUTPUT);
  
  digitalWrite(WE, LOW);
  digitalWrite(CE, LOW);
  digitalWrite(OE, LOW);
}

void loop()
{
  Serial.println("START READING");
  
  for (addr = 0; addr < 0xFF; addr++)
  {
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, LSBFIRST, (addr&0xFF));
    shiftOut(SERIALDATA, SERIALCLK, LSBFIRST, (addr>>8));
    digitalWrite(STORECLK, HIGH);
    
    digitalWrite(CE, HIGH); // Chip Enabled
    digitalWrite(OE, HIGH); //Read Enabled
    digitalWrite(WE, LOW);
    
    for (int i = 2, j = 0; i <= 9; i++, j++)
    {
        val = digitalRead(i);
        if (val == HIGH)
            bitWrite(data, j, HIGH);
    }
    
    digitalWrite(OE, LOW);
    digitalWrite(CE, LOW);
    
    Serial.print(data, HEX);
    Serial.print(" ");
    if (++counter == 32) {
      Serial.println("");
      counter = 0;
    }
    
  }
  
  Serial.println("");
  Serial.println("Finish");
  
  while(1);
}


And over here is the code to write the same data just for test:

Code:

#define SERIALDATA 10
#define SERIALCLK 12
#define STORECLK 11

#define WE A3
#define OE A4
#define CE A5

//Change the pinMode
#define OUT 0
#define IN  1

unsigned int addr = 0;
int count = 0;

void ChangeMode(byte io)
{
  if (io) {
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    pinMode(4, INPUT);
    pinMode(5, INPUT);
    pinMode(6, INPUT);
    pinMode(7, INPUT);
    pinMode(8, INPUT);
    pinMode(9, INPUT);
  }
  else
  {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
  }
}

void setup()
{
  Serial.begin(19200);
  //Data read or write D0 - D7 - Pin9 - Pin2
  ChangeMode(OUT);
  
  //Shiftregister pins
  pinMode(STORECLK, OUTPUT);
  pinMode(SERIALCLK, OUTPUT);
  pinMode(SERIALDATA, OUTPUT);
  
  //command pins
  pinMode(WE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(CE, OUTPUT);
  
  //Disable the command pins
  digitalWrite(WE, LOW);
  digitalWrite(CE, LOW);
  digitalWrite(OE, LOW);
  
}

void loop()
{
  Serial.println("START WRITING ...");
  
  //Setup the chip
  digitalWrite(WE, LOW);
  digitalWrite(CE, LOW);
  digitalWrite(OE, HIGH);
  
  digitalWrite(STORECLK, LOW);
  shiftOut(SERIALDATA, SERIALCLK, LSBFIRST, (0x0555&0xFF));
  shiftOut(SERIALDATA, SERIALCLK, LSBFIRST, (0x0555>>8));
  digitalWrite(STORECLK, HIGH);
  
  delay(1);
  digitalWrite(OE, LOW);  //Read disable
  delay(1);
  digitalWrite(CE, HIGH); //Chip enable
  delay(1);
  digitalWrite(WE, HIGH); //Write Enable
  delay(1);  
  
  for (addr = 0; addr <= 0x3FFF; addr++)
  {
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, LSBFIRST, (addr&0xFF));
    shiftOut(SERIALDATA, SERIALCLK, LSBFIRST, (addr>>8));
    digitalWrite(STORECLK, HIGH);
    
    delay(1);
    
    digitalWrite(OE, LOW);  //Read disable
    delay(1);
    digitalWrite(CE, HIGH); //Chip enable
    delay(1);
    digitalWrite(WE, HIGH); //Write Enable
    delay(1);
    
//Write the same data in the block
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
    
    delay(1);
    
    digitalWrite(WE, LOW); //Write disabled
    delay(1);
    digitalWrite(CE, LOW); //Chip disable
    delay(1);
    digitalWrite(OE, HIGH); //reads enable
    delay(1);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
  }
  
  delay(1000);
  Serial.println("");
  Serial.println("WRITING COMPLETE.");
  
  while(1)
  delay(50);
}


Now, I'm very confused, I don't know if this code is working correctly or not. (The reading program always return 0xFF and Writing seems not working).
Please help me, I would like if someone can see the  Timing diagram of this Flash memory and correct me in the code if somethings are wrong. And Why not, if it'll work we can make this as library for future use.

If you need any further informations I'm here.

Many thanks.

« Last Edit: December 07, 2013, 06:40:34 pm by BlackSharp » Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would recommend you a step by step approach.
First, try the shift registers stuff to get work. Send out a 16 bit address only and do check you see the address there (with a voltmeter for example). Then, set the other signals and do check you see them all as required.
After that you may start to think about the reading/writing the flash.

Quote
I read some replies from people in some forums, they claimed that arduino UNO which I use, is not fast enough to drive correctly AM29F040B (because arduino can't drive 20ns or something like that), in other hand some others confirm that's possible to do.
It will work.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your reply Pito,

Concerning about what you have said, below is the test result that I have made:

Main Shift Register:
Q0 - Q7 are connected to A0 - A7
Second shift register:
Q0 - Q7 are connected to A8 - A15.

For example if I send "0xABCD" "1010101111001101 in binary"  to the shift registers, it will gives:
-----------------------------------------------------------------

A15 A14 A13 A12 A11 A10 A9 A8    A7 A6 A5 A4 A3 A2 A1 A0
    1    0    1     0    1    0     1     1       1    1    0   0   1    1    0   1
   '-----------------------------'   '-------------------------'

              MSB                                                  LSB


 1: HIGH
0: LOW
---------------------------------------------------------------

For the other pins, they are directly connected to the arduino, despite of this I have test them out with Voltmeter too to be sure.
So, I think the shift registers work well and arduino pins too.

What's the next step now.

Thanks for help.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When it works then try to read the flash. If the flash is programmed you may try to read first 8 addresses for example (when the flash is not programmed, erased, you will read FF).
Usually reading a byte from flash means:
0. CS, WE, OE are high - the default (these 3 signals must be normally high, except the read/write sequence)
1. set the address
2. CS to low
3. OE to low
4. small delay (ie 70ns) but not important to do it with arduino, as the arduino is slow enough
5. read the data bus
6. OE high
7. CS high

Writing the flash is more complicated - to write a byte into the flash require ie. 4 bytes to be written at specific addresses in a special sequence (see datasheet):
5555H: AAH
2AAAH: 55H
5555H: A0H
Your_Address: Your_Data
Wait 10ms or do DATA POLLING

A byte is written:
0. CS, WE, OE are high - the default
1. set the address and data
2. CS to low
3. WE to low
4. if you write the special sequence byte a small delay (ie 70ns) but not important to do it with arduino, as the arduino is slow enough
4. if you write Your_Data - wait ie 10ms or do POLLING of a specific DATA bit (see datasheet)
5. WE high
6. CS high

Erasing requires a special sequence too.

You have to study the writing algorithm, described on pages 9-17, or find a ready sw somewhere. The detailed timing diagrams are not important for you when working with arduino, except the write process - either you have to wait long enough, or you have to poll certain data bits until the flash is written (reading a flash takes 50-70ns, writing takes several msecs usually).
HTH



« Last Edit: October 22, 2013, 04:33:03 pm by pito » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I appreciated your help pito,

In the attachement is the screenshot from command definition table of this Flash memory.

Regarding the read operation, I think it's very clear but can you be more specific about this :

Quote
0. CS, WE, OE are high - the default (these 3 signals must be normally high, except the read/write sequence)

CS, WE, OE must be high except "Read/Write Sequence", So since we are in a read operation they can be LOW at the beginning no ?

Second thing, and this is what I can't understand. The writing require a command at special address and send a special data. So, If I understand what do you said and  what the screenshot mean:

To write data I must do as following, correct me if I'm wrong:
0- OE goes HIGH.
1- set the address and data
2- CS to low
3- WE to low
4- Small delay or not.
5-  Write "0x555" so it will be "0000000010101010101 in binary" and it will goes from A18 to A0.
6- Delay 70ns or not.
7- Send Special craft of data  "0xAA" which is "10101010 in binary" and it will goes from D7 to D0.
8- Delay 10ms.
9- Write "0x2AA" which will be "0000000001010101010" and it will goes from A18 to A0.
10- Delay 70ns or not.
11- Send "0x55" data which will be "0010 10101" and it will goes from D7 to D0.
12- Delay 10ms.
13- Write "0x555" so it will be "0000000010101010101 in binary" and it will goes from A18 to A0.
14- Delay 70ns or not.
15- Send "0xA0" data which will be "10100000" and it will goes from D7 to D0.
16- Delay 10ms.
17- CS to Low.
18- WE to LOW.

I have some questions:

1- Is this a kind of algorithm or we can say instructions flow which I should write in arduino sketch to write data to the flash ?

2- How can I find out if I should send command (CS, OE, WE) at first  after the set of the address, or after a sent of data. Can you show me that in the datasheet please ?

3- in the instructions above especially "Special command/sequence" are that what we called "operations unlock" ?

4- Are the delays important in Flash memory programming ?

5- the "command defintion" in the screenshot shows that must drive at first the 6 cycles at first to write (Special command/sequences) and there are no delays between them. Where you found that ?

I hope that those questions don't mind you, I have many others (about what should be first and the last ...)  but I stop here until I understand those things or leave them for later. This is my first time which I use a Flash memory, so I'm a noob.

Regards.


* Command definition.png (36.04 KB, 769x423 - viewed 77 times.)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I did what you have said and I studied the timing diagram of reading and writing operations (Special command / Sequence).
I also tested my code below but without any result.

Below  is my code:

Writing:
Code:
#define SERIALDATA 10
#define SERIALCLK 12
#define STORECLK 11

#define WE A3
#define OE A4
#define CE A5

#define OUT 0
#define IN  1

unsigned int addr = 0;
int count = 0;
unsigned int unlock = 0;

void ChangeMode(byte io)
{
  if (io) {
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    pinMode(4, INPUT);
    pinMode(5, INPUT);
    pinMode(6, INPUT);
    pinMode(7, INPUT);
    pinMode(8, INPUT);
    pinMode(9, INPUT);
  }
  else
  {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
  }
}

void setup()
{
  Serial.begin(19200);
  //Data read or write D0 - D7 - Pin9 - Pin2
  ChangeMode(OUT);
 
  //Shiftregister pins
  pinMode(STORECLK, OUTPUT);
  pinMode(SERIALCLK, OUTPUT);
  pinMode(SERIALDATA, OUTPUT);
 
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
 
  digitalWrite(WE, HIGH);
  digitalWrite(CE, HIGH);
  digitalWrite(OE, HIGH);
 
}

void loop()
{
  Serial.println("START WRITING ...");
 
  for (addr = 0; addr <= 0xFFF; addr++)
  {
    //Send address to the memory  ...
 
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (addr>>8));
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (addr&0xFF));
    digitalWrite(STORECLK, HIGH);
   
    //write the same data ...
    delay(1);
   
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
   
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
   
    digitalWrite(WE, LOW); //Write disabled
    digitalWrite(CE, LOW); //Chip disable
   
    //Write 0x555
    unlock = 0x555;
   
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (unlock>>8));
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (unlock&0xFF));
    digitalWrite(STORECLK, HIGH);
    delay(1);
    //Write 0xAA
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(9, HIGH);
     
    delayMicroseconds(10);
   
    //Write 2AA
    unlock = 0x2AA;
   
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (unlock>>8));
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (unlock&0xFF));
    digitalWrite(STORECLK, HIGH);
    delay(1);
    //send 0x55 data
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
   
    delayMicroseconds(10);
   
    //Write again 0x555 §Sequence
   
    unlock = 0x555;
   
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (unlock>>8));
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (unlock&0xFF));
    digitalWrite(STORECLK, HIGH);
   
    //Write 0xA0 command
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(9, HIGH);
   
    delayMicroseconds(10);
   
    digitalWrite(WE, HIGH);
    digitalWrite(CE, HIGH);
  }
 
  Serial.print("FINAL STEP, PLEASE WAIT ");
  for (int c = 0; c < 3; c++) {
    Serial.print(".");
    delay(1000);
  }
  delay(1000);
  Serial.println("");
  Serial.println("WRITING COMPLETE.");
 
  while(1)
  delay(50);
}

Reading:
Code:
#define SERIALDATA 10
#define SERIALCLK 12
#define STORECLK 11

#define WE A3
#define OE A4
#define CE A5

#define OUT 0
#define IN  1

unsigned int addr = 0;
byte data = 0;
int counter = 0;
boolean val = LOW;

void ChangeMode(byte io)
{
  if (io) {
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    pinMode(4, INPUT);
    pinMode(5, INPUT);
    pinMode(6, INPUT);
    pinMode(7, INPUT);
    pinMode(8, INPUT);
    pinMode(9, INPUT);
  }
  else
  {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(9, OUTPUT);
  }
}

void setup()
{
  Serial.begin(19200);
  //Data read or write D0 - D7 - Pin9 - Pin2
  ChangeMode(IN);
 
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
 
  //Shiftregister pins
  pinMode(STORECLK, OUTPUT);
  pinMode(SERIALCLK, OUTPUT);
  pinMode(SERIALDATA, OUTPUT);
 
  //Command register - default
  digitalWrite(WE, HIGH);
  digitalWrite(CE, HIGH);
  digitalWrite(OE, HIGH);
}

void loop()
{
  Serial.println("START READING");
 
  for (addr = 0; addr < 0xFFF; addr++)
  {
    digitalWrite(STORECLK, LOW);
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (addr>>8));
    shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (addr&0xFF));
    digitalWrite(STORECLK, HIGH);
   
    digitalWrite(CE, LOW);
    digitalWrite(OE, LOW);
   
    delayMicroseconds(7);
   
    for (int i = 2, j = 0; i <= 9; i++, j++)
    {
        val = digitalRead(i);
        if (val == HIGH)
            bitWrite(data, j, HIGH);
    }
   
    digitalWrite(CE, HIGH);
    digitalWrite(OE, HIGH);
   
    Serial.print(data, HEX);
    Serial.print(" ");
    if (++counter == 32) {
      Serial.println("");
      counter = 0;
    }
   
  }
 
  Serial.println("");
  Serial.println("READING FINISH");
   
  while(1);
}

The reading always return 0xFF even if I execute the write code. Really, I don't understand why it's so easy when you read the datasheet but in real world is much complicated.

The datasheet is in the attachement file for a person who want to help me.

Thanks in advance.

* AM29F040B.pdf (826.1 KB - downloaded 39 times.)
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try to create the following functions, ie.:

Code:
flash_ctrl_deselect(); // OE=HIGH, WE=HIGH, CS=HIGH, in this sequence
flash_ctrl_rd(); // CS=LOW, OE=LOW, in this sequence
flash_ctrl_wr(); // CS=LOW, WE=LOW, in this sequence

flash_addr_set(uint32 address);  // puts the flash address on the addressbus
flash_data_set(uint8 data); // writes data on the databus
uint8 flash_data_get(); // reads data from the databus

uint8 flash_read(uint32 address}; // reads the flash

boolean flash_get_DQ7(); // get DQ7 value
boolean flash_get_DQ6(); // get DQ6 value
boolean flash_get_DQ5(); // get DQ5 value
boolean flash_get_DQ3(); // get DQ3 value
boolean flash_get_DQ2(); // get DQ2 value
boolean flash_byte_write_poll(); // write polling, TRUE - byte write under process, FALSE - done
..
other pollings if required

flash_write_command(uint32 address, uint8 data); // writes a command to the flash command buffer
flash_write(uint32 address, uint8 data); // writes the data to the flash

flash_erase(); // erase the entire flash

« Last Edit: October 24, 2013, 12:24:32 pm by pito » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Pito,

As requested, this is code that I have wrote. Erase function still remain for later when write and read are functionnal:
Code:
#define SERIALDATA 10
#define SERIALCLK 12
#define LATCH 11

#define WE A3
#define OE A4
#define CE A5

#define A18 A0
#define A17 A1
#define A16 A2

#define OUT 0
#define IN  1

//Change pinMode of D0- D7
void flash_change_pins_mode(boolean io)
{
  if (io) {
    for (int i = 2; i < 10; i++)
    pinMode(i, INPUT);
  }
  else
  {
    for (int i = 2; i < 10; i++)
    pinMode(i, OUTPUT);
  }
}

void flash_ctrl_deselect()
{
  digitalWrite(OE, HIGH);
  digitalWrite(WE, HIGH);
  digitalWrite(CE, HIGH);
}

void flash_ctrl_rd_enable()
{
  digitalWrite(CE, LOW);
  digitalWrite(OE, LOW);
}

void flash_ctrl_rd_disable()
{
  digitalWrite(CE, HIGH);
  digitalWrite(OE, HIGH);
}

void flash_ctrl_wr_enable()
{
  digitalWrite(CE, LOW);
  digitalWrite(WE, LOW);
}

void flash_ctrl_wr_disable()
{
  digitalWrite(CE, HIGH);
  digitalWrite(WE, HIGH);
}

void flash_addr_set(unsigned int address)
{
  digitalWrite(LATCH, LOW);
  shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (address>>8));
  shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (address&0xFF));
  digitalWrite(LATCH, HIGH);
}

void flash_data_set(byte data)
{
  flash_change_pins_mode(OUT);
  for (int i = 0; i < 8; i++)
  {
    if (data&bit(i))
    digitalWrite(i+2, HIGH);
    else
    digitalWrite(i+2, LOW);
  }
}

byte flash_data_get()
{
  byte data = 0;
  boolean state = LOW;
 
  flash_change_pins_mode(IN);
  for (int i = 2, j = 0; i <= 9; i++, j++)
  {
        state = digitalRead(i);
        if (state == HIGH)
            bitWrite(data, j, HIGH);
  }
  return data;
}

byte flash_read(unsigned int address)
{
  byte data = 0;
 
  flash_ctrl_deselect();
  flash_change_pins_mode(IN);
 
  flash_addr_set(address);
  flash_ctrl_rd_enable();
 
  delayMicroseconds(7);
 
  data = flash_data_get();
  flash_ctrl_rd_disable();
  return data;
}

boolean flash_get_DQ7()
{
  boolean state = LOW;
 
  pinMode(9, INPUT);
  state = digitalRead(9);
  if (state == HIGH)
  return true;
  else return false;
}

boolean flash_get_DQ6()
{
  unsigned long duration = 0;
 
  pinMode(8, INPUT);
  duration = pulseIn(8, HIGH);
  if (duration > 0)
  return true;
  else return false;
}

boolean flash_get_DQ5()
{
  boolean state = LOW;
 
  pinMode(7, INPUT);
  state = digitalRead(7);
  if (state == HIGH)
  return true;
  else return false;
}

boolean flash_get_DQ3()
{
  boolean state = LOW;
 
  pinMode(5, INPUT);
  state = digitalRead(5);
  if (state == HIGH)
  return true;
  else return false;
}

boolean flash_get_DQ2()
{
  boolean state = LOW;
 
  pinMode(4, INPUT);
  state = digitalRead(4);
  if (state == HIGH)
  return true;
  else return false;
}

//Check data
boolean flash_byte_write_poll()
{
  boolean state = LOW;
  state = flash_get_DQ7();
  if (state)
  return true; //Under process
  else return false; //Done
}

//Sequence/Command
void flash_write_command(unsigned int address, byte data)
{
    flash_change_pins_mode(OUT);
    flash_addr_set(address);
    flash_data_set(data);
}

void flash_write(unsigned int address, byte data)
{
 
  flash_ctrl_deselect();
  flash_change_pins_mode(OUT);
 
  //Set address and data
  flash_addr_set(address);
  flash_data_set(data);
  flash_ctrl_wr_enable();
 
  //Send command sequence
  flash_write_command(0x555, 0xAA);
  flash_write_command(0x2AA, 0x55);
  flash_write_command(0x555, 0xA0);
 
  flash_ctrl_wr_disable();
}

void flash_erase()
{
}

void setup()
{
  Serial.begin(9600);
 
  //Init A16 - A18 flash pins
  pinMode(A17, OUTPUT);
  pinMode(A16, OUTPUT);
  pinMode(A18, OUTPUT);
 
  //Init pin's shoft register
  pinMode(LATCH, OUTPUT);
  pinMode(SERIALCLK, OUTPUT);
  pinMode(SERIALDATA, OUTPUT);
 
  //Init flash command pins
  pinMode(WE, OUTPUT);
  pinMode(CE, OUTPUT);
  pinMode(OE, OUTPUT);
}

void loop()
{
  if (Serial.available() > 0)
  {
    if (Serial.read() == 'r') {
      int count = 0;
      Serial.println("");
      for (unsigned int addr = 0; addr < 0xFF; addr++) {
        Serial.print(flash_read(addr), HEX);
        Serial.print(" ");
        if (++count == 15) {
        Serial.println("");
        count = 0;
        }
      }
    }
    Serial.flush();
  }
 
  if (Serial.available() > 0)
  {
    if (Serial.read() == 'w')
    {
      for (unsigned int addr = 0; addr < 100; addr++)
      {
        byte value = 0xAB;
        Serial.println("");
        flash_write(addr, value);
        while (flash_byte_write_poll()) {
          Serial.print("*");
          delay(5);
        } 
        Serial.print("Byte ");
        Serial.print(addr);
        Serial.println(" Written");
      } 
      Serial.println("Operation complete");
    }
    Serial.flush();
  }
}

I tested it out but still no result.
There is one thing which I can't understand why I should execute device command at last ? shouldn't be at first ?

What I'm supposed to do now ?

Thanks.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First glance:
use only these 3 functions:
Code:
void flash_ctrl_deselect()
{
  digitalWrite(OE, HIGH);
  digitalWrite(WE, HIGH);
  digitalWrite(CE, HIGH);
}

void flash_ctrl_rd()
{
  digitalWrite(CE, LOW);
  digitalWrite(OE, LOW);
}

void flash_ctrl_wr()
{
  digitalWrite(CE, LOW);
  digitalWrite(WE, LOW);
}

Mind - for the addresses: the "unsigned int" is 16bit, you need "unsigned  long" (or simply uint32).. !! 16+8bit!!
Code:
// read a single byte from flash
byte flash_read(unsigned long address)
{
  byte data = 0;  
  flash_ctrl_deselect();
  flash_change_pins_mode(IN);  
  flash_addr_set(address);
  flash_ctrl_rd();  // rd/oe goes LOW
  delayMicroseconds(1);  // 1usec is ok when reading the flash (70ns is min)  
  data = flash_data_get();
  flash_ctrl_deselect();  // rd/oe goes HIGH, cs goes HIGH
  return data;
}

BTW: Polling a bit on the data bus require "while()":
Code:
boolean flash_get_DQ7()
{...
while (...) ... ;
..
}

Mind - for the address: the "unsigned int" is 16bit, you need "unsigned  long" (or simply uint32).. !! 16+8bit!!

Code:
void flash_addr_set(unsigned long address)
{
  digitalWrite(LATCH, LOW);

  // YOU HAVE TO SET THE HIGHEST 8BITS SOMEWHERE !!
  // for example a function:
  set_highest_flash_address(address>>16);

  shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (address>>8));
  shiftOut(SERIALDATA, SERIALCLK, MSBFIRST, (address&0xFF));
  digitalWrite(LATCH, HIGH);
}

Code:
// write flash Command - using min 70ns long write
void flash_write_command(unsigned long address, byte data)
{
    flash_ctrl_deselect();  
    flash_change_pins_mode(OUT);
    flash_addr_set(address);
    flash_data_set(data);
    flash_ctrl_wr();  //wr goes LOW
    delayMicroseconds(1);  // for example 1us delay
    flash_ctrl_deselect();    //wr goes HIGH, cs goes HIGH
}

YOU NEED:
Code:
// write flash memory Data byte - with 10ms delay or POLLING the data bit - see the datasheet
void flash_write_data(unsigned long address, byte data)
{
    flash_ctrl_deselect();  
    flash_change_pins_mode(OUT);
    flash_addr_set(address);
    flash_data_set(data);
    flash_ctrl_wr();   //wr goes LOW
    delay(10);  // for example 10ms delay OR POLLING THE DQ7
    flash_ctrl_deselect();    //wr goes HIGH, cs goes HIGH
}

Code:
// write single byte into the flash (Commands + Data)
void flash_write(unsigned long address, byte data)
{  
  //Send the command sequence
  flash_write_command(0x555, 0xAA);  //this is with 1usec delay (70ns is enough)
  flash_write_command(0x2AA, 0x55);  //this is with 1usec delay (70ns is enough)
  flash_write_command(0x555, 0xA0);  //this is with 1usec delay (70ns is enough)

//HERE YOU HAVE TO WRITE THE BYTE INTO THE FLASH:
  flash_write_data(address, data);  //this is a write with 10ms delay or with POLLING THE DQ7  
}

The last function in setup() shall be  "flash_ctrl_deselect();" that is the default state !

Usually the next step is to check each function, whether it works properly or not (call the single function and check the pins with voltmeter or oscilloscope or logic analyzer). All above functions must work properly.

Be aware of pin direction setting. Double check.

Mind your address is more than 16bit! Try to write a single byte, and read it back. Do it for few addresses, step by step.
Do not expect it will work on the first attempt. It takes time.. There is a lot of signals and wirings you have to clean up.. It takes time..

Do not try to optimize/simplify the code unless it works - it means you flashed/erased your memory successfully at least 20x smiley

Do not use polling yet - use the 10-20ms delay as described above - 10ms is usually enough flash write time. Do not decrease the time yet. Rather wait few minutes to write the entire flash. When it works rock stable then you may start with code optimization and/or polling the DQx instead of using the fixed delay..
HTH
« Last Edit: October 26, 2013, 05:45:37 pm by pito » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi pito and everyone,

Sorry for the late response.

I'm agree with you that programming flash will take time, this is why I decided to study and read over and over the datasheet  to understand how the chip really works. However, I'm struggling to understand some sentences in the datasheet, if someone please can help me to find out what these phrases mean:

Quote
Byte Program Command Sequence

Programming is a four bus cycle operation. The program command sequence is initiated by writing two unlock write cycles, followed by the program set-up command. The program address and data are written next, which in turn initiate the Embedded Program algorithm. The system is not required to provide further controls or timings. The device automatically provides internally generated program pulses and verify the programmed cell margin. The command definitions take shows the address and data requirements for the byte program command sequence.

What's set-up command ? is the (CE#, OE#, WE#) command register ?
Is unlock write cycles contain address and data ?

Another one:

Quote
Programming is allowed in any sequence and across sector boundaries. A bit cannot be programmed from a "0" back to a "1". Attempting to do so may halt the operation and set DQ5 to "1".

Is that means that only erase operation can do this ?
How can I know if command registers (CS, WE, OE) are sent after a set of address and data or before ?

Please those questions are important for me to understand.

Regards.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What's set-up command ? is the (CE#, OE#, WE#) command register ?
Is unlock write cycles contain address and data ?
Read carefully the table 4.
Programming Set-up command is writing the 0Ah at the address 555h ("cycle" n.3).
(CE#, OE#, WE#) - those are just signals you have to bitbang during each cycle as required.
Unlock write cycles does contain address and data:
             adr   data
1. cycle: 555 aa   //unlock
2. cycle: 2aa 55   //unlock
3. cycle: 555 0a   // setup command
4. cycle: PA   PD  // actual address and data to be written into flash

Quote
Is that means that only erase operation can do this ?
How can I know if command registers (CS, WE, OE) are sent after a set of address and data or before ?
Yes.
(CS, WE, OE) - those are not command registers but signals. Those signals are set by calling
void flash_ctrl_deselect()
void flash_ctrl_rd()
void flash_ctrl_wr()..
You know where to sent them because you know how a typical rd/wr into a memory works.

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for you quick reply,

Can you please be more specific about this:

Quote
You know where to sent them because you know how a typical rd/wr into a memory works.

My question was when can I send them ? Because reading the datasheet especially in Table 1 (Device bus operations), they just mention the requirements to read or write data, there is any order how to send them. To be more clear this is an example of what I mean

Should do like this:

1- flash_addr_set()
2-flash_data_set()
3-flash_ctrl_rd() //send address and data then enable read operation

or like this:

1- flash_ctrl_rd() //Enable read operation and send address and data
2-flash_addr_set()
3-Flash_data_set()

I would like to know the same thing about write and erase operation.

Thanks.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Set the address and data first, then do flash_ctrl_rd(). The same with write. Mind the delays. Erase is a sequence of commands (see table 4).
Logged

Offline Offline
Sr. Member
****
Karma: 11
Posts: 358
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I made an sst39sf040 programmer you can base your programmer off my code see
This will run on your arduino uno note that I used avr-gcc to compile it instead of the arduino ide https://github.com/ComputerNerd/sst39sf040-avr
This will run on your computer https://github.com/ComputerNerd/sst39sf040-computerside
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everyone,

Regarding the flash memory programming, I can say now that I can read the eeprom. I cleaned up the circuit (Pulldown resistors & shift registers ...).  I'm sure now because when I take WE off it returns 0 rather than FF. (may be wrong please advise)

I used this logic to get data, any other way won't work I'll get just 0s:
flash_ctrl_deselect();
flash_ctrl_rd();
flash_addr_set();
flash_get_data();
flash_ctrl_deselect();

Howewer, the remaining challenge now is Writing program I can't actually figure out how to do this. I tried several algorithm from the writing timing Diagram without success.

Please in the attachement the timing diagram of Write operation, and below the flow of what I have understood from it. If there is any recommandation or correction please don't hesistate to do it to help me out:

Scenario 1:
  • CE high to low
  • OE HIGH
  • WE HIGH
  • Command 555
  • WE to LOW
  • Data command
  • WE to HIGH
  • CE High to low
  • PA
  • WE to LOW
  • PD
  • WE to HIGH
  • delay 10 us

Scenario 2:

  • CE high & WE HIGH & OE HIGH/li]
    • Address command 555h
    • CE to LOW
    • WE to LOW
    • data command A0h
    • WE to HIGH
    • PA
    • CE High to low
    • WE to LOW
    • PD
    • WE to HIGH
    • CE to HIGH
    • delay 10 us

    What do you think about them ? what's the one that you think  it may work for me.

    Any other clue or idea will be appreciated.

    Thanks.


* Timing diagram.png (33.79 KB, 758x428 - viewed 60 times.)
Logged

Pages: [1] 2 3   Go Up
Jump to: