Eeprom programmer: Arduino DUE + SD card + Tsop48

Hi,

I would like to assemble a 29LV640 memory programmer, tsop48, I found the tsop48 adapter for DIP, but they are 64Mbits, it is a parallel bus. So I think it will be more appropriate to use the data bus via SPI to store the file, that is, an SD card.

(I thought about making a graphical interface for the computer and using the serial port, but I believe it would be slower. According to calculations, using 8MB and 115200bps would give about 9.26 min, In addition, the SD card interface is now ready for use)

https://www.calctool.org/CALC/prof/computing/transfer_time

I modified a sample SD card reading and writing example, to write and read an 8MB (64Mbits) file, the times are as follows:

  • Write: 296s (4,93 min)
  • Read: 78s (1,3 min)

It seems acceptable to me this time for data storage, not counting the access time of the 29LV640 memory.

I thought about the DUE arduino, for its performance, also for having 3V3 input and output pins.

Any tips to improve performance, in addition to directly manipulating the input and output pins?

/*
  SD card read/write

  This example shows how to read and write data to and from an SD card file
  The circuit:
   SD card attached to SPI bus as follows:
 ** UNO:  MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
  and pin #10 (SS) must be an output
 ** Mega:  MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
  and pin #52 (SS) must be an output
 ** Leonardo: Connect to hardware SPI via the ICSP header


  created   Nov 2010  by David A. Mellis
  modified 9 Apr 2012  by Tom Igoe

  This example code is in the public domain.

*/

#include <SPI.h>
#include <SD.h>

File myFile;

// change this to match your SD shield or module;
//     Arduino Ethernet shield: pin 4
//     Adafruit SD shields and modules: pin 10
//     Sparkfun SD shield: pin 8
const int chipSelect = 6;

uint32_t millis1 = 0;
uint32_t millis2 = 0;
uint32_t millis3 = 0;

uint32_t byte_cnt = 0;

void setup()
{
  pinMode(13, OUTPUT);

  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(SS, OUTPUT);

  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  Serial.println("FILE_WRITE");

  // bytes: 8388608

  // if the file opened okay, write to it:
  if (myFile) {
    millis1 = millis();

    //Serial.print("Writing to test.txt...");
    //myFile.println("testing 1, 2, 3.");
    for (uint32_t i = 0; i < 8388608; i++) {
      myFile.write(255);

      byte_cnt++;

      if ((millis3 + 500) < millis()) {
        millis3 = millis();

        digitalWrite(13, !digitalRead(13));

        Serial.print("byte cnt: ");
        Serial.println(byte_cnt, DEC);
      }
    }

    millis2 = millis();

    Serial.print("write time (sec.): ");
    Serial.println((millis2 - millis1) / 1000, DEC);

    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  Serial.println("FILE_READ");

  byte_cnt = 0;

  // re-open the file for reading:
  myFile = SD.open("file.bin");
  if (myFile) {
    Serial.println("file.bin:");

    millis1 = millis();

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      //Serial.write(myFile.read());

      myFile.read();

      byte_cnt++;

      if ((millis3 + 500) < millis()) {
        millis3 = millis();

        digitalWrite(13, !digitalRead(13));

        Serial.print("byte cnt: ");
        Serial.println(byte_cnt, DEC);
      }
    }

    millis2 = millis();

    Serial.print("read time (sec.): ");
    Serial.println((millis2 - millis1) / 1000, DEC);

    // close the file:
    myFile.close();

  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file.bin");
  }
}

void loop()
{
  // nothing happens after setup
}

Good news!

I managed to improve the performance, using buffer!

  • Write: 36s
  • Read: 30s

(P.S.: buffer size >=512 Bytes to get that time (multiples, 512, 1024, 2048...))

/*
  SD card read/write

  This example shows how to read and write data to and from an SD card file
  The circuit:
   SD card attached to SPI bus as follows:
 ** UNO:  MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
  and pin #10 (SS) must be an output
 ** Mega:  MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
  and pin #52 (SS) must be an output
 ** Leonardo: Connect to hardware SPI via the ICSP header


  created   Nov 2010  by David A. Mellis
  modified 9 Apr 2012  by Tom Igoe

  This example code is in the public domain.

*/

#include <SPI.h>
#include <SD.h>

File myFile;

// change this to match your SD shield or module;
//     Arduino Ethernet shield: pin 4
//     Adafruit SD shields and modules: pin 10
//     Sparkfun SD shield: pin 8
const int chipSelect = 6;

uint32_t millis1 = 0;
uint32_t millis2 = 0;
uint32_t millis3 = 0;

uint32_t byte_cnt = 0;


#define data_buff_size 32768
byte data_buff[data_buff_size];

void setup()
{
  pinMode(13, OUTPUT);

  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(SS, OUTPUT);

  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  Serial.println("FILE_WRITE");

  // bytes: 8388608

  // if the file opened okay, write to it:
  if (myFile) {
    millis1 = millis();

    //Serial.print("Writing to test.txt...");
    //myFile.println("testing 1, 2, 3.");
    for (int i = 0; i < data_buff_size; i++) {
      data_buff[i] = 0;
    }

    for (uint32_t i = 0; i < (8388608/data_buff_size); i++) { // 8388608/256=32768
      myFile.write(data_buff, data_buff_size);

      byte_cnt += data_buff_size;

      if ((millis3 + 500) < millis()) {
        millis3 = millis();

        digitalWrite(13, !digitalRead(13));

        Serial.print("byte cnt: ");
        Serial.println(byte_cnt, DEC);
      }
    }

    millis2 = millis();

    Serial.print("write time (sec.): ");
    Serial.println((millis2 - millis1) / 1000, DEC);

    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  Serial.println("FILE_READ");

  byte_cnt = 0;

  // re-open the file for reading:
  myFile = SD.open("file.bin");
  if (myFile) {
    Serial.println("file.bin:");

    millis1 = millis();

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      //Serial.write(myFile.read());

      myFile.read(data_buff, data_buff_size);

      byte_cnt += data_buff_size;

      if ((millis3 + 500) < millis()) {
        millis3 = millis();

        digitalWrite(13, !digitalRead(13));

        Serial.print("byte cnt: ");
        Serial.println(byte_cnt, DEC);
      }
    }

    millis2 = millis();

    Serial.print("read time (sec.): ");
    Serial.println((millis2 - millis1) / 1000, DEC);

    // close the file:
    myFile.close();

  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file.bin");
  }
}

void loop()
{
  // nothing happens after setup
}
1 Like

I am experiencing some random instabilities with the reading / writing of memory.

After adding an external power supply, the instability improved when using standard digitalWrite / digitalRead access. But for direct access from the port, there are still instabilities.

The response speed has increased a lot with direct access, I believe that it will be necessary to insert intervals between commands, in order to comply with the time chart described in the memory datasheet.

It seems that the memory goes into protection mode, and it is only possible to read 0x00 at all addresses.

The complete project is attached, in case anyone has a way to test it.

I'm using a Tsop48 MX29LV640EBTI-70G memory.

This is the direct access code (further down, the standard code):

#ifdef Mode_Fast_IO
#warning "Using direct port manipulation"

void EEPROM_set_address(uint16_t addr);
uint16_t EEPROM_get_data();
void EEPROM_set_data(uint16_t dat);
void EEPROM_set_data_input();
void EEPROM_set_data_output();
void EEPROM_reset_cmd();
uint16_t EEPROM_read_cmd();
void EEPROM_write_cmd();

void EEPROM_set_address(uint16_t addr) {
  PIOA->PIO_ODSR = (PIOA->PIO_ODSR & ~(
                      (1 << FPIN_A19) |
                      (1 << FPIN_A9) |
                      (1 << FPIN_A11) |
                      (1 << FPIN_A18)
                    )
                   ) | (
                     (((addr >> 19) & 1) << FPIN_A19) |
                     (((addr >> 9) & 1) << FPIN_A9) |
                     (((addr >> 11) & 1) << FPIN_A11) |
                     (((addr >> 18) & 1) << FPIN_A18)
                   );

  PIOB->PIO_ODSR = (PIOB->PIO_ODSR & ~(
                      (1 << FPIN_A0) |
                      (1 << FPIN_A21) |
                      (1 << FPIN_A2) |
                      (1 << FPIN_A4) |
                      (1 << FPIN_A6) |
                      (1 << FPIN_A17)
                    )
                   ) | (
                     ((addr & 1) << FPIN_A0) |
                     (((addr >> 21) & 1) << FPIN_A21) |
                     (((addr >> 2) & 1) << FPIN_A2) |
                     (((addr >> 4) & 1) << FPIN_A4) |
                     (((addr >> 6) & 1) << FPIN_A6) |
                     (((addr >> 17) & 1) << FPIN_A17)
                   );

  PIOC->PIO_ODSR = (PIOC->PIO_ODSR & ~(
                      (1 << FPIN_A8) |
                      (1 << FPIN_A20) |
                      (1 << FPIN_A1) |
                      (1 << FPIN_A3) |
                      (1 << FPIN_A7) |
                      (1 << FPIN_A5)
                    )
                   ) | (
                     (((addr >> 8) & 1) << FPIN_A8) |
                     (((addr >> 20) & 1) << FPIN_A20) |
                     (((addr >> 1) & 1) << FPIN_A1) |
                     (((addr >> 3) & 1) << FPIN_A3) |
                     (((addr >> 7) & 1) << FPIN_A7) |
                     (((addr >> 5) & 1) << FPIN_A5)
                   );

  PIOD->PIO_ODSR = (PIOD->PIO_ODSR & ~(
                      (1 << FPIN_A14) |
                      (1 << FPIN_A15) |
                      (1 << FPIN_A13) |
                      (1 << FPIN_A16) |
                      (1 << FPIN_A12) |
                      (1 << FPIN_A10)
                    )
                   ) | (
                     (((addr >> 14) & 1) << FPIN_A14) |
                     (((addr >> 15) & 1) << FPIN_A15) |
                     (((addr >> 13) & 1) << FPIN_A13) |
                     (((addr >> 16) & 1) << FPIN_A16) |
                     (((addr >> 12) & 1) << FPIN_A12) |
                     (((addr >> 10) & 1) << FPIN_A10)
                   );
                   
//  digitalWrite(PIN_A0, addr & 1);
//  digitalWrite(PIN_A1, (addr >> 1) & 1);
//  digitalWrite(PIN_A2, (addr >> 2) & 1);
//  digitalWrite(PIN_A3, (addr >> 3) & 1);
//  digitalWrite(PIN_A4, (addr >> 4) & 1);
//  digitalWrite(PIN_A5, (addr >> 5) & 1);
//  digitalWrite(PIN_A6, (addr >> 6) & 1);
//  digitalWrite(PIN_A7, (addr >> 7) & 1);
//  digitalWrite(PIN_A8, (addr >> 8) & 1);
//  digitalWrite(PIN_A9, (addr >> 9) & 1);
//  digitalWrite(PIN_A10, (addr >> 10) & 1);
//  digitalWrite(PIN_A11, (addr >> 11) & 1);
//  digitalWrite(PIN_A12, (addr >> 12) & 1);
//  digitalWrite(PIN_A13, (addr >> 13) & 1);
//  digitalWrite(PIN_A14, (addr >> 14) & 1);
//  digitalWrite(PIN_A15, (addr >> 15) & 1);
//  digitalWrite(PIN_A16, (addr >> 16) & 1);
//  digitalWrite(PIN_A17, (addr >> 17) & 1);
//  digitalWrite(PIN_A18, (addr >> 18) & 1);
//  digitalWrite(PIN_A19, (addr >> 19) & 1);
//  digitalWrite(PIN_A20, (addr >> 20) & 1);
//  digitalWrite(PIN_A21, (addr >> 21) & 1);
}

uint16_t EEPROM_get_data() {
  uint16_t val = 0;
  uint32_t tmpA = 0;
  uint32_t tmpB = 0;
  uint32_t tmpC = 0;
  uint32_t tmpD = 0;

  tmpA = PIOA->PIO_PDSR;
  tmpB = PIOB->PIO_PDSR;
  tmpC = PIOC->PIO_PDSR;
  tmpD = PIOD->PIO_PDSR;

  val = ((((tmpA >> FPIN_Q2) & 1) << 2) |
         (((tmpA >> FPIN_Q1) & 1) << 1) |
         (((tmpA >> FPIN_Q3) & 1) << 3) |
         (((tmpA >> FPIN_Q15_A_1) & 1) << 15) |
         (((tmpA >> FPIN_Q10) & 1) << 10) |
         ((tmpB >> FPIN_Q0) & 1) |
         (((tmpC >> FPIN_Q7) & 1) << 7) |
         (((tmpC >> FPIN_Q6) & 1) << 6) |
         (((tmpC >> FPIN_Q5) & 1) << 5) |
         (((tmpC >> FPIN_Q4) & 1) << 4) |
         (((tmpC >> FPIN_Q11) & 1) << 11) |
         (((tmpC >> FPIN_Q8) & 1) << 8) |
         (((tmpC >> FPIN_Q9) & 1) << 9) |
         (((tmpD >> FPIN_Q14) & 1) << 14) |
         (((tmpD >> FPIN_Q13) & 1) << 13) |
         (((tmpD >> FPIN_Q12) & 1) << 12));

  //  val |= digitalRead(PIN_Q0);
  //  val |= digitalRead(PIN_Q1) << 1;
  //  val |= digitalRead(PIN_Q2) << 2;
  //  val |= digitalRead(PIN_Q3) << 3;
  //  val |= digitalRead(PIN_Q4) << 4;
  //  val |= digitalRead(PIN_Q5) << 5;
  //  val |= digitalRead(PIN_Q6) << 6;
  //  val |= digitalRead(PIN_Q7) << 7;
  //  val |= digitalRead(PIN_Q8) << 8;
  //  val |= digitalRead(PIN_Q9) << 9;
  //  val |= digitalRead(PIN_Q10) << 10;
  //  val |= digitalRead(PIN_Q11) << 11;
  //  val |= digitalRead(PIN_Q12) << 12;
  //  val |= digitalRead(PIN_Q13) << 13;
  //  val |= digitalRead(PIN_Q14) << 14;
  //  val |= digitalRead(PIN_Q15_A_1) << 15;

  return val;
}

void EEPROM_set_data(uint16_t dat) {
  digitalWrite(PIN_Q0, dat & 1);
  digitalWrite(PIN_Q1, (dat >> 1) & 1);
  digitalWrite(PIN_Q2, (dat >> 2) & 1);
  digitalWrite(PIN_Q3, (dat >> 3) & 1);
  digitalWrite(PIN_Q4, (dat >> 4) & 1);
  digitalWrite(PIN_Q5, (dat >> 5) & 1);
  digitalWrite(PIN_Q6, (dat >> 6) & 1);
  digitalWrite(PIN_Q7, (dat >> 7) & 1);
  digitalWrite(PIN_Q8, (dat >> 8) & 1);
  digitalWrite(PIN_Q9, (dat >> 9) & 1);
  digitalWrite(PIN_Q10, (dat >> 10) & 1);
  digitalWrite(PIN_Q11, (dat >> 11) & 1);
  digitalWrite(PIN_Q12, (dat >> 12) & 1);
  digitalWrite(PIN_Q13, (dat >> 13) & 1);
  digitalWrite(PIN_Q14, (dat >> 14) & 1);
  digitalWrite(PIN_Q15_A_1, (dat >> 15) & 1);
}

void EEPROM_set_data_input() {
  pinMode(PIN_Q0, INPUT);
  pinMode(PIN_Q1, INPUT);
  pinMode(PIN_Q2, INPUT);
  pinMode(PIN_Q3, INPUT);
  pinMode(PIN_Q4, INPUT);
  pinMode(PIN_Q5, INPUT);
  pinMode(PIN_Q6, INPUT);
  pinMode(PIN_Q7, INPUT);
  pinMode(PIN_Q8, INPUT);
  pinMode(PIN_Q9, INPUT);
  pinMode(PIN_Q10, INPUT);
  pinMode(PIN_Q11, INPUT);
  pinMode(PIN_Q12, INPUT);
  pinMode(PIN_Q13, INPUT);
  pinMode(PIN_Q14, INPUT);
  pinMode(PIN_Q15_A_1, INPUT);
}

void EEPROM_set_data_output() {
  pinMode(PIN_Q0, OUTPUT);
  pinMode(PIN_Q1, OUTPUT);
  pinMode(PIN_Q2, OUTPUT);
  pinMode(PIN_Q3, OUTPUT);
  pinMode(PIN_Q4, OUTPUT);
  pinMode(PIN_Q5, OUTPUT);
  pinMode(PIN_Q6, OUTPUT);
  pinMode(PIN_Q7, OUTPUT);
  pinMode(PIN_Q8, OUTPUT);
  pinMode(PIN_Q9, OUTPUT);
  pinMode(PIN_Q10, OUTPUT);
  pinMode(PIN_Q11, OUTPUT);
  pinMode(PIN_Q12, OUTPUT);
  pinMode(PIN_Q13, OUTPUT);
  pinMode(PIN_Q14, OUTPUT);
  pinMode(PIN_Q15_A_1, OUTPUT);
}

void EEPROM_reset_cmd() {
  digitalWrite(PIN_RESET, LOW);

  delayMicroseconds(10);

  digitalWrite(PIN_RESET, HIGH);

  delayMicroseconds(20);
}

uint16_t EEPROM_read_cmd() {
  uint16_t dat = 0;
  // Read array action is to read the data stored in the array. While the memory device is in powered up or has been reset,
  // it will automatically enter the status of read array. If the microprocessor wants to read the data stored in the array, it has
  // to drive CE# (device enable control pin) and OE# (Output control pin) as Vil, and input the address of the data to be
  // read into address pin at the same time. After a period of read cycle (Tce or Taa), the data being read out will be
  // displayed on output pin for microprocessor to access. If CE# or OE# is Vih, the output will be in tri-state, and there will
  // be no data displayed on output pin at all.

  digitalWrite(PIN_WE, HIGH);
  digitalWrite(PIN_CE, LOW);
  digitalWrite(PIN_OE, LOW);

  //delayMicroseconds(1);
  dat = EEPROM_get_data();

  digitalWrite(PIN_OE, HIGH);
  digitalWrite(PIN_CE, HIGH);

  return dat;

}

void EEPROM_write_cmd() {
  // To write a command to the device, system must drive WE# and CE# to Vil, and OE# to Vih. In a command cycle, all
  // address are latched at the later falling edge of CE# and WE#, and all data are latched at the earlier rising edge of CE#
  // and WE#.
  digitalWrite(PIN_OE, HIGH);
  digitalWrite(PIN_CE, LOW);
  digitalWrite(PIN_WE, LOW);

  delayMicroseconds(1);

  digitalWrite(PIN_WE, HIGH);
  digitalWrite(PIN_CE, HIGH);

  delayMicroseconds(1);

}
#endif

EEPROM_Programmer_V1.zip (11.3 KB)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.