Go Down

Topic: Open project Arduino general eeprom R/W (Read 2133 times) previous topic - next topic

Cvik_Dasa

May 22, 2019, 08:25 am Last Edit: May 22, 2019, 08:27 am by Cvik_Dasa
Hello there  :) Im working on a project based on arduino and I would like to get you involved in it.

What I'm trying to do is an arduino reader and writer for spi, i2c and parallel eeproms. When I finish this project I will make it fully open source and I will share it with all of you so because of that I want to hear your opinion what should be done, what to consider as option in software, code look up to see if I missed something and so on.

So far I came up with this:



I already started writing code for SPI and I figure out it will be hard to make it as simple as possible but still easy to adopt to any eeprom. So here I have a question about ready bit in status register. Many of manufacturers calls them RDY but winbond calls it BUSY instead so how give a clue to user when searching the datasheet what to look for?


In the attachment is visual basic code for windows side app and here is an arduino part:

Code: [Select]
#include <SPI.h>
int CS;
int CSPinAL = 0;
int SO;
int SOPinAL = 0;
int WP;
int WPPinAL = 0;
int SI;
int SIPinAL = 0;
int SCLK;
int SCKPinAL = 0;
int HOLD;
int HOLDPinAL = 0;
int Addressbitlength = 0;
int HighestAddressBit = 0;
int DataBit = 0;
int WRDIint = 0;
int RDRSint = 0;
int WRSRint = 0;
int READint = 0;
int WRITEint = 0;
int WRENint = 0;
int WEN = 0;
int RDY = 0;
int WENAL = 0;
int RDYAL = 0;

String Serial_Data;
int Protocol;
 
void setup() {
    Serial.begin(115200);
 Serial.setTimeout(5);
 Serial.print("Ready");

 do {//Used to send board info
  
 if(Serial.available()){
 Serial_Data = Serial.readStringUntil('\n');      
 }
 if (Serial_Data == "B"){
 Serial.print("Nano");
 Serial_Data = "";
 break;
 }
 } while (1 == 1);

 do {
  
 if(Serial.available()){
 Serial_Data = Serial.readStringUntil('\n');      
 }
 if (Serial_Data == "2"){
 Serial.print("SPI");
 Serial_Data = "";
 Protocol = 3;
 break;
 }
 } while (1 == 1);

 if (Protocol == 3){
 int CSPin = 0;

 do { //CS pin setup
 if(Serial.available()){
 CSPin = Serial.parseInt();      
 }
 if (CSPin != 0){
 CS = CSPin;
 Serial.print(CSPin);
 break;
 }
 } while (1 == 1);

 do { //CS pin active low or high
 if(Serial.available()){
 CSPinAL = Serial.parseInt();      
 }
 if (CSPinAL != 0){//cs pin active low
 Serial.print(CSPinAL);
 break;      
 }
 } while (1 == 1);

 int SOPin = 0;

 do { //SO pin setup
 if(Serial.available()){
 SOPin = Serial.parseInt();      
 }
 if (SOPin != 0){
 SO = SOPin;
 Serial.print(SOPin);
 break;
 }
 } while (1 == 1);

 do { //SO pin active low or high
 if(Serial.available()){
 SOPinAL = Serial.parseInt();      
 }
 if (SOPinAL != 0){//so pin active low
 Serial.print(SOPinAL);
 break;    
 }
 } while (1 == 1);

 int WPPin = 0;

 do { //WP pin setup
 if(Serial.available()){
 WPPin = Serial.parseInt();      
 }
 if (WPPin != 0){
 WP = WPPin;
 Serial.print(WPPin);
 break;
 }
 } while (1 == 1);

 do { //WP pin active low or high
 if(Serial.available()){
 WPPinAL = Serial.parseInt();      
 }
 if (WPPinAL != 0){//WP pin active low
 Serial.print(WPPinAL);
 break;      
 }
 } while (1 == 1);

 int SIPin = 0;

 do { //SI pin setup
 if(Serial.available()){
 SIPin = Serial.parseInt();      
 }
 if (SIPin != 0){
 SI = SIPin;
 Serial.print(SIPin);
 break;
 }
 } while (1 == 1);

 do { //SI pin active low or high
 if(Serial.available()){
 SIPinAL = Serial.parseInt();      
 }
 if (SIPinAL != 0){//SI pin active low
 Serial.print(SIPinAL);
 break;  
 }
 } while (1 == 1);

 int SCKPin = 0;

 do { //SCK pin setup
 if(Serial.available()){
 SCKPin = Serial.parseInt();      
 }
 if (SCKPin != 0){
 SCLK = SCKPin;
 Serial.print(SCKPin);
 break;
 }
 } while (1 == 1);

 do { //SCK pin active low or high
 if(Serial.available()){
 SCKPinAL = Serial.parseInt();      
 }
 if (SCKPinAL != 0){//SCK pin active low
 Serial.print(SCKPinAL);
 break;      
 }
 } while (1 == 1);

 int HOLDPin = 0;

 do { //HOLD pin setup
 if(Serial.available()){
 HOLDPin = Serial.parseInt();      
 }
 if (HOLDPin != 0){
 HOLD = HOLDPin;
 Serial.print(HOLDPin);
 break;
 }
 } while (1 == 1);

 do { //HOLD pin active low or high
 if(Serial.available()){
 HOLDPinAL = Serial.parseInt();      
 }
 if (HOLDPinAL != 0){//HOLD pin active low
 Serial.print(HOLDPinAL);
 break;      
 }
 } while (1 == 1);

 do { //Address bit length
 if(Serial.available()){
 Addressbitlength= Serial.parseInt();      
 }
 if (Addressbitlength != 0){//Address bit length isnot 0
 Serial.print(Addressbitlength);
 break;    
 }
 } while (1 == 1);

 do { //ActualAddressLenth
 if(Serial.available()){
 HighestAddressBit = Serial.parseInt();      
 }
 if (HighestAddressBit != 0){//HighestAddressBit isnot 0
 Serial.print(HighestAddressBit);
 break;      
 }
 } while (1 == 1);

    do { //DataBitLenth
      if(Serial.available()){
        DataBit = Serial.parseInt();      
      }
      if (DataBit != 0){//DataBit lenth isnot 0
        Serial.print(DataBit);
        break;      
      }
    } while (1 == 1);
    
 do { //WRDIint WRDI as integer
 if(Serial.available()){
 WRDIint = Serial.parseInt();      
 }
 if (WRDIint != 0){//WRDIint as integer > 0
 Serial.print(WRDIint);
 break;  
 }
 } while (1 == 1);

 do { //RDRSint RDRS as integer
 if(Serial.available()){
 RDRSint = Serial.parseInt();      
 }
 if (RDRSint != 0){//RDRSint as integer > 0
 Serial.print(RDRSint);
 break;    
 }
 } while (1 == 1);

 do { //WRSRint WRSR as integer
 if(Serial.available()){
 WRSRint = Serial.parseInt();      
 }
 if (WRSRint != 0){//WRSRint as integer > 0
 Serial.print(WRSRint);
 break;      
 }
 } while (1 == 1);

 do { //READint READ as integer
 if(Serial.available()){
 READint = Serial.parseInt();      
 }
 if (READint != 0){//READint as integer > 0
 Serial.print(READint);
 break;      
 }
 } while (1 == 1);

 do { //WRITEint WRITE as integer
 if(Serial.available()){
 WRITEint = Serial.parseInt();      
 }
 if (WRITEint != 0){//WRITEint as integer > 0
 Serial.print(WRITEint);
 break;      
 }
 } while (1 == 1);

 do { //WRENint WREN as integer
 if(Serial.available()){
 WRENint = Serial.parseInt();      
 }
 if (WRENint != 0){//WRENint as integer > 0
 Serial.print(WRENint);
 break;      
 }
 } while (1 == 1);

 do {//Status register setup
  
 Serial_Data = "";
 if(Serial.available()){
 Serial_Data = Serial.readStringUntil('\n');      
 }

 if (Serial_Data == "E"){
 Serial.print(Serial_Data);
 Serial_Data = "";
 int WENr = 0;

 do { //WEN register setup
 if(Serial.available()){
 WENr = Serial.parseInt();      
 }
 if (WENr != 0){
 WEN = WENr;
 Serial.print(WENr);
 break;
 }
 } while (1 == 1);

 do { //WEN bit active low or high
 if(Serial.available()){
 WENAL = Serial.parseInt();      
 }
 if (WENAL != 0){//WEN bit active low
 Serial.print(WENAL);
 break;
 }
 } while (1 == 1);
 }
  
 if (Serial_Data == "W"){
 Serial.print(Serial_Data);
 Serial_Data = "";
 int RDYr = 0;

 do { //RDY register setup
 if(Serial.available()){
 RDYr = Serial.parseInt();      
 }
 if (RDYr != 0){
 RDY = RDYr;
 Serial.print(RDYr);
 break;
 }
 } while (1 == 1);

 do { //RDY bit active low or high
 if(Serial.available()){
 RDYAL = Serial.parseInt();      
 }
 if (RDYAL != 0){//RDY bit active low
 Serial.print(RDYAL);
 break;
 }
 } while (1 == 1);
 }

 } while (Serial_Data != "Z");
  


 Serial.print(Serial_Data);
 Serial_Data = "";


 pinMode(13, OUTPUT);
 digitalWrite(13,HIGH);

 delay(1000);

 }

}
 
 
 
void loop() {

}



 


And that's it for now I work every day on it so Im sorry it is not too well commented and there are some mess in code but that's just for now. When I will have time i will clean it up a bit.

Looking for your suggestions, support or how ever you can help  :smiley-twist:  

Cvik_Dasa

#1
May 25, 2019, 12:23 am Last Edit: May 25, 2019, 12:29 am by Cvik_Dasa
Hello there... seems like Im hitting the wall  :smiley-sad: 

Cant figure out what is the problem so can someone please assist trying to find out solution?

So when I send cs pin number from pc to arduino I get correct replay from arduino. then it goes cs pin active low or high over serial and sure enough arduino replay received data to pc and stores that information i variable.

next data going over serial is write protect pin number and for example I send as string number 3 and arduino replays back number 3 to pc. Then pc sends active low or high for write protect pin and instead receiving number 1 or 2 from arduino Im getting "pin number + active low or high" like 31 or if i define wp pin as 4 as replay I got 41 or 42.

I tried to send integer and string value over serial and Im getting the same results.

vb.net
Code: [Select]
'DEFINE CS PIN

        Com_port_received_text = ""
        SerialPort1.Write(CS_pin_num)
        TimerValue = 0

        ' send pin number to use
        Do
            Magic_Byte = CStr(CS_pin_num)
           
If Com_port_received_text = Magic_Byte Then 'Wait until data is received from arduino

                Exit Do
            End If

            If TimerValue = 20 Then

                MessageBox.Show("Arduino didn't awknoledge sent data packet.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Error_occurred = 1
                GoTo end_sub

            End If

            Application.DoEvents()
        Loop

        'CS PIN ACTIVE LOW OR HIGH
        Com_port_received_text = ""
        TimerValue = 0

        If CheckBox1.Checked = True Then
            Magic_Byte = "1"
            SerialPort1.Write(1)                                'CSPin = active low

        Else
            Magic_Byte = "2"
            SerialPort1.Write(2)                                'CSPin = active high

        End If


        Do
            If Com_port_received_text = Magic_Byte Then

                Exit Do
            End If

            If TimerValue = 20 Then

                MessageBox.Show("Arduino didn't awknoledge sent data packet.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Error_occurred = 1
                GoTo end_sub

            End If

            Application.DoEvents()
        Loop

        'DEFINE WP PIN

        Com_port_received_text = ""
        SerialPort1.Write(WP_pin_num)
        TimerValue = 0

        ' send pin number to use
        Do
            Magic_Byte = CStr(WP_pin_num)
            If Not Com_port_received_text = Magic_Byte Then

                Exit Do
            End If

            If TimerValue = 20 Then

                MessageBox.Show("Arduino didn't awknoledge sent data packet.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Error_occurred = 1
                GoTo end_sub

            End If

            Application.DoEvents()
        Loop

        'WP PIN ACTIVE LOW OR HIGH

        TimerValue = 0

        If CheckBox4.Checked = True Then
            Magic_Byte = "1"
            SerialPort1.Write(1)                                'WPPin = active low

        Else
            Magic_Byte = "2"
            SerialPort1.Write(2)                                'WPPin = active high

        End If
        'SerialPort1.DiscardOutBuffer() does not help
        'SerialPort1.DiscardInBuffer()
        Com_port_received_text = ""
        Do
            'Application.DoEvents()
            If Com_port_received_text = Magic_Byte Then

                Exit Do
            End If

            If TimerValue = 400 Then

                MessageBox.Show("Arduino didn't awknoledge sent data packet.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Error_occurred = 1
                GoTo end_sub

            End If
           ' If Com_port_received_text = "31" Then 'Does not work
           '     Com_port_received_text = "" 'Does not work
           ' End If 'Does not work
            Application.DoEvents()
        Loop



Arduino:
Code: [Select]
int CSPin = 0;
do { //CS pin setup
if(Serial.available()){
CSPin = Serial.parseInt();       
}
if (CSPin != 0){
CS = CSPin;
Serial.print(CSPin);
break;
}
} while (1 == 1);

do { //CS pin active low or high
if(Serial.available()){
CSPinAL = Serial.parseInt();       
}
if (CSPinAL != 0){//cs pin active low
Serial.print(CSPinAL);   
break;     
}
} while (1 == 1);


int WPPin = 0;
do { //WP pin setup
if(Serial.available()){
WPPin = Serial.parseInt();       
}
if (WPPin != 0){
WP = WPPin;
Serial.print(WPPin);
break;
}
} while (1 == 1);
//Serial.print(""); ' does not help
//Serial.flush();


    do { //WP pin active low or high
if(Serial.available()){
WPPinAL = Serial.parseInt();       
}
if (WPPinAL != 0){//WP pin active low
       
Serial.print(WPPinAL);   
break;     
}
    } while (1 == 1);

    if (WPPinAL == 1){// used to see if arduino gets correct information from serial
pinMode(13, OUTPUT);

digitalWrite(13, HIGH);
}

do {
delay(1);
} while (1 == 1);

Cvik_Dasa

 :smiley-confuse:  Ive find out that sometimes fails on cs in too. seems like it have something to do with the serial buffer ? not really sure whats wrong but I think I will send whole bunch of configuration data as one string and on arduino receive it as char array... should work. Im just not shure what is going to happen when I start receiving eeprom data over the serial. I might encounter same problem again :/

Cvik_Dasa

#3
May 28, 2019, 01:04 am Last Edit: May 28, 2019, 01:34 am by Cvik_Dasa
I managed to solve the issue by sending everything as string to the arduino, as backup if that wont work i was planing to send all configuration as one big string and then separate characters on arduino but luckily this worked out :) 

Code: [Select]
Private Sub Send_SPI_Config()


        Dim Analog_pin_Used As Boolean = 0


        'Add cfg to array
        Dim cfgArray As New ArrayList

        'OPEN SPI PROTOCOL

        cfgArray.Add("2") 'defines SPI protocol


        'DEFINE CS PIN

        PinStatus(TextBox10.Text)

        If Analog_pin_Used = True Then

            Error_occurred = 0
            cfgArray.Add(Arduino_Pin_Map(Magic_Byte))

            If Error_occurred = True Then
                GoTo end_sub
            End If
        Else

            cfgArray.Add(Magic_Byte) ' cs pin number
        End If


        'CS PIN ACTIVE LOW OR HIGH

        If CheckBox1.Checked = True Then
            cfgArray.Add("1")                        'CSPin = active low

        Else
            cfgArray.Add("2")
            'CSPin = active high

        End If

        Analog_pin_Used = False

        'DEFINE SO PIN

        PinStatus(TextBox17.Text)

        If Analog_pin_Used = True Then

            Error_occurred = 0
            cfgArray.Add(Arduino_Pin_Map(Magic_Byte))

            If Error_occurred = True Then
                GoTo end_sub
            End If
        Else

            cfgArray.Add(Magic_Byte) ' so pin number
        End If

        Analog_pin_Used = False

        'DEFINE WP PIN

        PinStatus(TextBox18.Text)

        If Analog_pin_Used = True Then

            Error_occurred = 0
            cfgArray.Add(Arduino_Pin_Map(Magic_Byte))

            If Error_occurred = True Then
                GoTo end_sub
            End If
        Else

            cfgArray.Add(Magic_Byte) ' wp pin number
        End If

        'WP PIN ACTIVE LOW OR HIGH

        If CheckBox4.Checked = True Then
            cfgArray.Add("1")                        'WPPin = active low

        Else
            cfgArray.Add("2")
            'WPPin = active high

        End If

        Analog_pin_Used = False

        'DEFINE SI PIN

        PinStatus(TextBox19.Text)

        If Analog_pin_Used = True Then

            Error_occurred = 0
            cfgArray.Add(Arduino_Pin_Map(Magic_Byte))

            If Error_occurred = True Then
                GoTo end_sub
            End If
        Else

            cfgArray.Add(Magic_Byte) ' si pin number
        End If

        Analog_pin_Used = False

        'DEFINE SCK PIN

        PinStatus(TextBox21.Text)

        If Analog_pin_Used = True Then

            Error_occurred = 0
            cfgArray.Add(Arduino_Pin_Map(Magic_Byte))

            If Error_occurred = True Then
                GoTo end_sub
            End If
        Else

            cfgArray.Add(Magic_Byte) ' sck pin number
        End If

        Analog_pin_Used = False

        'DEFINE HOLD PIN

        PinStatus(TextBox22.Text)

        If Analog_pin_Used = True Then

            Error_occurred = 0
            cfgArray.Add(Arduino_Pin_Map(Magic_Byte))

            If Error_occurred = True Then
                GoTo end_sub
            End If
        Else

            cfgArray.Add(Magic_Byte) ' hold pin number
        End If

        'HOLD PIN ACTIVE LOW OR HIGH

        If CheckBox7.Checked = True Then
            cfgArray.Add("1")                        'hold Pin = active low

        Else
            cfgArray.Add("2")
            'hold Pin = active high

        End If

        'Expected address length

        If Not IsNumeric(TextBox26.Text) Or String.IsNullOrWhiteSpace(TextBox26.Text) Then

            MessageBox.Show("Address length is incorrect.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End If


        Try

            If Convert.ToInt32(TextBox26.Text) < Convert.ToInt32(TextBox27.Text) Then
                MessageBox.Show("Address length is incorrect.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Error_occurred = 1
                GoTo end_sub

            End If
        Catch ex As Exception

            MessageBox.Show("Address length is incorrect.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End Try


        Magic_Byte = TextBox26.Text
        Dim Magic_integer = Convert.ToInt32(Magic_Byte)
        Magic_integer = Magic_integer / 8


        If Magic_integer < 1 Or Magic_integer > 4 Then
            MessageBox.Show("Address length is incorrect.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub

        ElseIf Magic_integer > 0.99 And Magic_integer < 2 Then
            cfgArray.Add("8")

        ElseIf Magic_integer > 1.99 And Magic_integer < 3 Then
            cfgArray.Add("16")

        ElseIf Magic_integer > 2.99 And Magic_integer < 4 Then
            cfgArray.Add("24")

        End If


        'HighestAddressBit

        If Not IsNumeric(TextBox27.Text) Or String.IsNullOrWhiteSpace(TextBox27.Text) Then

            MessageBox.Show("Highest Address seems incorrect incorrect.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End If

        cfgArray.Add(TextBox27.Text)

        'Send WRDI instruction

        If Regex.IsMatch(TextBox14.Text, "^[0-1 ]+$") Then

            cfgArray.Add(Bin_To_Dec(TextBox14.Text))

        Else
            MessageBox.Show("WRDI op code must be binary number.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End If


        'Send READ instruction

        If Regex.IsMatch(TextBox11.Text, "^[0-1 ]+$") Then

            cfgArray.Add(Bin_To_Dec(TextBox11.Text))

        Else
            MessageBox.Show("Read op code must be binary number.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End If


        'Send WRITE instruction

        If Regex.IsMatch(TextBox12.Text, "^[0-1 ]+$") Then

            cfgArray.Add(Bin_To_Dec(TextBox12.Text))

        Else
            MessageBox.Show("Write op code must be binary number.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End If

        'Send WREN instruction

        If Regex.IsMatch(TextBox13.Text, "^[0-1 ]+$") Then

            cfgArray.Add(Bin_To_Dec(TextBox13.Text))

        Else
            MessageBox.Show("Read op code must be binary number.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Error_occurred = 1
            GoTo end_sub
        End If

        'transfer from array arduino
        Magic_Byte = ""

        For Each Data As String In cfgArray

            Com_port_received_text = ""
            TimerValue = 0
            SerialPort1.Write(Data)

            Do
                If Com_port_received_text = Data Then

                    Exit Do
                End If

                If TimerValue = 20 Then

                    MessageBox.Show("Arduino didn't awknoledge sent data packet.", "Invald request", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    Error_occurred = 1
                    GoTo end_sub

                End If

                Application.DoEvents()
            Loop
            Error_occurred = 0

        Next

        cfgArray.Clear()



end_sub:
        Return

    End Sub


With this modification and with only one function added I managed to shrink code length by almost 500 lines, so it looks nicer and more organized now

For application to be as versatile as possible I will communicate with eeprom by shiftout and shiftin functions so that you can use any pin you want.

At the moment I implemented nano, mega and due in code, any suggestions for any other board?

Ive figure out that I will need to change GUI a bit because there is no need for SCK active low or high same as data in and out and I will remove opcode for read and write status register same as read status bits. I designed it with only basic knowledge about spi communication so as I learn I will edit GUI accordingly

Cant wait tomorrow to see what next issue will be

Cvik_Dasa

#4
May 29, 2019, 02:04 am Last Edit: May 29, 2019, 02:13 am by Cvik_Dasa
Some update... Well I made it, it seems like Im on the right track but there is still whole bunch of things to do.

Anyway after wasting 3+ hours on debugging why I cant't get any replay from eeprom Ive figure out that I declared miso and mosi on arduino as output pins. Imagine my face after figuring out what mistake I did  ::) 

anyway so far so good






Ive read BIOS eeprom (4MB) W25X40 and data don't have scene by looking at it with hex editor... Have no idea what decoding I should use to get something useful out of it.

I saved just part of code... maybe that part was post screen image, have no idea but I might consider to implement ability to save code as binary it should be easier to decode it that way.

Ammm yea reading whole eeprom took 2 minutes for arduino not that bad if you ask me but application have some issues when writing to the grid view and reading from grid view to save data file.

So complete read from eeprom took 2min eeprom>arduino>app then app took about 30s to convert raw data to hex and then storing it to grid view took 10 minutes. There must be better way to do it but for now it is ok it works I will do fine tuning at the end ;)


in the attachmet is visual studio code and here is arduino part:
Code: [Select]
int protocol = -1;
int cs_pin= -1;
int cs_al= -1;
int so_pin= -1;
int wp_pin= -1;
int wp_al= -1;
int si_pin= -1;
int sck= -1;
int hold= -1;
int hold_al= -1;
long address_length= -1;
long actual_length= -1;
int wrdiR= -1;
int readR= -1;
int writeR= -1;
int wrenR= -1;
byte Lowest = 0;
byte Middle = 0;
byte Highest = 0;
long i = 0;










String readString;

void setup() {
  Serial.begin(115200);
  Serial.print("Ready");
  char incomingByte;
  do{
 
    delay(5);
 
    while (Serial.available()>0) {

    incomingByte = Serial.read();

    readString +=incomingByte;

    }
    if(readString == "B"){
      Serial.print("Nano");

    }
    else if(readString != ""){



      if (protocol == -1){
        protocol = readString.toInt();
        Serial.print(protocol);
        readString = "";

      }

      if ((protocol == 2) && (readString != ""))
      {
        if (cs_pin == -1){
          cs_pin = readString.toInt();
          Serial.print(cs_pin);
          readString = "";

        }

        else if ((cs_pin != -1) && (cs_al == -1)&& (readString != "")){
            cs_al = readString.toInt();
            Serial.print(cs_al);
            readString = "";

        }
        else if ((cs_al != -1) && (so_pin == -1)&& (readString != "")){
          so_pin = readString.toInt();
          Serial.print(so_pin);
          readString = "";

        }
        else if ((so_pin != -1) && (wp_pin == -1)&& (readString != "")){
          wp_pin = readString.toInt();
          Serial.print(wp_pin);
          readString = "";

        }
        else if ((wp_pin != -1) && (wp_al == -1)&& (readString != "")){
          wp_al = readString.toInt();
          Serial.print(wp_al);
          readString = "";

        }
        else if ((wp_al != -1) && (si_pin == -1)&& (readString != "")){
          si_pin = readString.toInt();
          Serial.print(si_pin);
          readString = "";

        }
        else if ((si_pin != -1) && (sck == -1)&& (readString != "")){
          sck = readString.toInt();
          Serial.print(sck);
          readString = "";

        }
        else if ((sck != -1) && (hold == -1)&& (readString != "")){
          hold = readString.toInt();
          Serial.print(hold);
          readString = "";

        }
        else if ((hold != -1) && (hold_al == -1)&& (readString != "")){
          hold_al = readString.toInt();
          Serial.print(hold_al);
          readString = "";

        }
        else if ((hold_al != -1) && (address_length == -1)&& (readString != "")){
          address_length = readString.toInt();
          Serial.print(address_length);
          readString = "";

        }
        else if ((address_length != -1) && (actual_length == -1)&& (readString != "")){
          actual_length = readString.toInt();
          Serial.print(actual_length);
          readString = "";

        }
        else if ((actual_length != -1) && (wrdiR == -1)&& (readString != "")){
          wrdiR = readString.toInt();
          Serial.print(wrdiR);
          readString = "";

        }
        else if ((wrdiR != -1) && (readR == -1)&& (readString != "")){
          readR = readString.toInt();
          Serial.print(readR);
          readString = "";

        }
        else if ((readR != -1) && (writeR == -1)&& (readString != "")){
          writeR = readString.toInt();
          Serial.print(writeR);
          readString = "";

        }
        else if ((writeR != -1) && (wrenR == -1)&& (readString != "")){
          wrenR = readString.toInt();
          Serial.print(wrenR);
          readString = "";


        }

      }

    }
    readString = "";

  }while (wrenR == -1);




  if (protocol == 2){
  //si_pin = 11;
    pinMode(cs_pin,OUTPUT);
    pinMode(so_pin,INPUT);
    pinMode(wp_pin,OUTPUT);
    pinMode(si_pin,OUTPUT);
    pinMode(sck,OUTPUT);
    pinMode(hold,OUTPUT);

    if (cs_al == 1){digitalWrite(cs_pin,HIGH);}
    else{digitalWrite(cs_pin,LOW);}
    if (wp_al == 1){digitalWrite(wp_pin,HIGH);}
    else{digitalWrite(wp_pin,LOW);}
    if (hold_al == 1){digitalWrite(hold,HIGH);}
    else{digitalWrite(hold,LOW);}

    do{
      delay(5);
      while (Serial.available()>0) {

        incomingByte = Serial.read();
        readString +=incomingByte;

      }
    if(readString == "1")
    {
      Serial.print("1");

      if (cs_al == 1){digitalWrite(cs_pin,LOW);}
      else{digitalWrite(cs_pin,HIGH);}
      if (wp_al == 1){digitalWrite(wp_pin,LOW);}
      else{digitalWrite(wp_pin,HIGH);}
      delay(5);
      //actual_length = 1024;//Length(actual_length);

       

      shiftOut(si_pin, sck, MSBFIRST, 3);
      shiftOut(si_pin, sck, MSBFIRST, 0);
      shiftOut(si_pin, sck, MSBFIRST, 0);
      Serial.print(shiftIn(so_pin, sck, MSBFIRST));
      do{

        String var = "h";
        byte ii = shiftIn(so_pin, sck, MSBFIRST);
        Serial.print(var + ii);
        // Serial.println();   
        i++;
 
   
           
      } while(i != address_length);
         
      readString ="";

    }
    } while(readString != "");
  }


 //pinmode setup
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
}

  void loop() {
  delay(100);
  Serial.print("X");
  }
 

Cvik_Dasa

#5
Jun 01, 2019, 02:02 am Last Edit: Jun 01, 2019, 02:08 am by Cvik_Dasa
Update ... I decided to save file as binary instead of plain hex text I also added prompt window which asks when memory is greater than 512kb if you would like to show data in grid view because I was unable to speed up populating process and it takes to much time to show data in grid view if eeprom memory is greater than 512kb.

I got it slightly faster but it still takes to much time so now you have an option ;)

Im facing now another problem, somehow im getting to much of bytes from eeprom, I cant get it how. Im trying to debug it but cant find cause. I think that serial communication is to blame..


Write and read from file returns exact value of bytes so it is not issue in reading and writing the file



I was looking what arduino and eeprom talks about and didn't find problems there so it seems that windows application makes all this trouble.


Here is arduino and visual studio part of code used to communicate to each other



From image above it is clear that arduino understood how many bytes should read otherwise it would trigger an error message "Arduino didn't acknowledge sent data packet" and indeed arduino reads epprom exact number of times, verified by analyzer.

Now I see that I misspelled "acknowledge" in code :/

Here is an image of reading the same memory with the same settings



I would understand if they lose some packets while communicating but adding "some" random number of reads extra. I don't get it


Here is visual basic code fully commented "this part is used to receive bytes from arduino"

Code: [Select]
  Dim Magic_Byte As String = ""           'not part of this code
        Com_port_received_text = ""           'if anithing has been sent over serial get rid of it

        Dim DataArray As New ArrayList   'everything sent from arduino goes to this array
        Dim i As String = ""   'not part of this code
        Do

            If Not Com_port_received_text = "" Then           'if something was received

                SaveArray.Add(Com_port_received_text)                   'Add received text to array -> it will look like this
  'SaveArray(0) = "7h90h17h49h73h96h84h136h86h153h9"
  'I can get only one byte over serial but I need to add
  'delay(2); to slow down arduino transmission, vb app
                                                                          'can handle this string without slowing arduino down
         
         Com_port_received_text = ""           'clear variable
            End If
            Application.DoEvents()   'cant monitor serial protocol while
                                                                          'executing do loop without this
        Loop Until Com_port_received_text = "X"           'When arduino sends X it means that transmission
                                                                          'is done

        Dim newarray As New ArrayList   'here I will save actual data received from serial

        For Each Data As String In SaveArray           'Loop trough SaveArray until end, first pass will
                                                                          'hold '"7h90h17h49h73h96h84h136h86h153h9"

            Dim parts1() As String = Split(Data, "h")                   'Data will hold "7h90h17h49h73h96h84h136h86h153h9" and
  'parts1()is an array and it will be same string but
                                                                          'without h character like part1(0)= 7, part1(1) = 90
                                                                          'and so on
 
For Each Part As String In parts1           'goes trough part1 array and gets string out of it
                newarray.Add(Part)   'stores that string to new array, it will look same
                                                                          'as in parts1() array but this array can handle
  'strings, integers, longs and is easier to handle
                                                                          'data in it
            Next
        Next
        SaveArray.Clear()   'Empty SaveArray " for later use"



        For Each Part As String In newarray                               'read newarray which already holds wrong number of
                                                                          'bytes
           If Not Part = "" Then                                          'used to avoid exception throw

                SaveArray.Add((Convert.ToInt16(Part)))                    'this array is used to write binary file
                DataArray.Add(Hex(Convert.ToInt32(Part)))                 'and this one is used to populate grid view

           End If
        Next






Here is arduino part

Code: [Select]
      shiftOut(si_pin, sck, MSBFIRST, readR);                 //Start comminucation from eeprom (readR) = read opcode
      shiftOut(si_pin, sck, MSBFIRST, 0); //send first 8 bytes of address
      shiftOut(si_pin, sck, MSBFIRST, 0); //send second 8 bytes of address
      Serial.print(shiftIn(so_pin, sck, MSBFIRST));         //Read 0x000000 addres of eeprom and send it over serial

      Serial.print("h");                         //Send h over serial to know where to split the string
//in visual basic

      do{

        String var = "h";
        byte ii = shiftIn(so_pin, sck, MSBFIRST);                 //receive second address from eeprom
       
        Serial.print(ii); //send it over serial

      Serial.print("h"); //Send h over serial to know where to split the string
     
  ii = '\0'; // I was thinking that maybe ii buffer hold some data
//and I get extra data sent over serial so I tried to
//flush ii buffer with '\0' .. . but no help at all
 
        i++; //holds number of addresses readed
   
   

      } while(i != address_length);         //loop until end of eeprom in this case 0x5ffff



Hope that someone can find out what I'm missing here.

I tried also slowing down communication between arduino and computer but didn't get any improvement, also if i read only until 0x1ff or 0xfff everything works fine. it smells like I declared some variable as wrong type but I triple checked that and didn't find any problems there.

Cvik_Dasa

#6
Jun 02, 2019, 09:04 pm Last Edit: Jun 02, 2019, 09:07 pm by Cvik_Dasa
Ok so far so god... well not exactly I managed to get this thing to work but It is not clear exactly what's happening.

By the way I tried everything  adding delays in various parts of code, increase/ reduce baud rate, no success...

I decided to monitor serial communication between arduino and pc and saw many weird thing happening so to keep it simple I decided to synchronize transmission between arduino and pc.

synchronization is done this way. Arduino reads eeprom 10 times and then replays 10 bytes to pc. Pc responds with ack and arduino continues reading next 10 bytes form eeprom and so on.

Here is the result



For some reason windows side app cant keep up receiving information and processing them.

without any logical explanation for this issue I decided to increase sync rate



and it worked, Im getting what I expect but if you look at the timing at the beginning of reading process application freezes for some reason.

This time arudino reads 9 bytes from eeprom and then sends them over serial. Not sure what is the difference 10 bytes shouldn't be enough to overflow arduino or vb.net serial.

Any way Im happy to see that encoding is ok. In this part of dump I can see motherboard type... gigabyte GA-M56S-S3 ... at least something works as it should  :smiley-roll-sweat:



With sync I lost speed so it is something I will deal with... cant really figure out what Im doing wrong and I dont get any support from here and this is the best I can do. maybe later I will try to solve speed issue.

At the moment im still fighting with to many bytes received even with sync but only if i read eeprom over 0x1fff so this first needs to be fixed.

Cvik_Dasa

Took me a while to solve this one  :smiley-confuse:

After some time I decided to write complete receive part of code from the beginning and it solved my problem with double sync but this time instead of sending one byte as sync I'm sending complete last received string to arduino for comparison.
 If transmitted and received data are not the same it will replay last transmitted data. It keeps data integrity if something goes wrong.

I did try to increase the speed of reading data from eeprom by reading more than 8-9 bites before sending them over serial but it failed almost immediately so I thought it cant be computer side problem because I did define SerialPort1.ReadBufferSize = 2000000... Should be enough right?

So I used Due instead of nano and tried to read eeprom again, it failed again as before so what next?
I started to suspect that maybe arduino serial library causes the problem and decided to rewrite complete code for STM32F446 with atollic studio and HAL drivers and still I got the same result.

After quite a bit of time spent on vb net looking for patterns in the data when it fails I find out that serial receives everything from arduino but it only saves around 30 characters in variable and it triggers  serial receive event twice so I should read it twice and keep the data like so.

Code: [Select]
'serial handler
    Public Sub ReceivedText(ByVal [text] As String)


        If Me.TextBox1.InvokeRequired Then
            Dim x As New SetTextCallBack(AddressOf ReceivedText)

            Me.BeginInvoke(x, New Object() {(text)})                                                       

        ElseIf Not text = "" Then

            If Com_port_received_text = "" Then
                Com_port_received_text = text        'Read first part
            Else
                Com_port_received_text1 = text      'Read the rest of data
            End If

        End If
            text = ""

    End Sub




And it work as it should so now I can read more than 8 bytes from eeprom and send them over serial.
As sweet spot I decide to read 16 bytes in total it seems like I'm getting the best results when comparing how long it takes to read complete eeprom.

Also I was careful to write code without delays while receiving the data and I'm receiveing data on another thread so basically I did everything I could to get this thing to go as fast as possible. And results are not so great. max transmission rate is 1kB/s.

any way here is edited transmit/receive code

Code: [Select]
      do {

        for (int vv = 0; vv < 16; vv++) {

          ii = shiftIn(so_pin, sck, MSBFIRST);
          readString += ii;
          readString = readString + "h";

          ii = '\0';

          if (i >= address_length - 1) {
            vv = 16;
          }
          i++;
        }

Resend:
        Serial.print(readString);

        char buff[readString.length() + 1];
        String readString1 = "";
        while (!Serial.available());

        if (Serial.available()) {

          int length = Serial.readBytes(buff, sizeof(buff) - 1);
          buff[length] = 0;
          String str(buff);
          readString1 = str;
        }


        if (readString1 != readString) {
          delay(500);
          Serial.print("NOK");
          Serial.flush();
          delay(500);
          readString1 = "";
          goto Resend;
        }
        readString = "";

        if (i == address_length) {

          Serial.print("X");
        }

        if (i >= address_length) {
          break;
        }

      } while (i != address_length);

  delay(100);
      Serial.print("X");


I didn't bother commenting arduino code, I'm sorry


Code: [Select]
'read data from eeprom

        Dim DataArray As New ArrayList
        Dim ReceivedBits As Integer = 0

Retry:
        SerialPort1.DiscardOutBuffer()      'Empty output and input buffer of serial
        SerialPort1.DiscardInBuffer()
        Com_port_received_text = ""
        Com_port_received_text1 = ""        'Empty vars where serial receive will store data

        Do

            If Not Com_port_received_text = "" Then                     'if something was received
                If Not Com_port_received_text.Contains("NOK") Then      'and it does not contain "NOK"


                    Dim iCnt As Integer = 0
                    For Each character As Char In Com_port_received_text
                        If character = "h" Then iCnt += 1                   'Get number of h characters received from serial
                    Next                                                    'used to count number of bits received from serial

                    TimerValue = 0
                    If Not iCnt = 16 And ReceivedBits + 16 <= ReadAddress_Count Then 'if there is less than 16bits received

                        Do                                                          'wait the rest of the data to be received from serial
                            If TimerValue = 10 Then
                                GoTo NoResponse                                     'if nothing was received in 1second then exit loop
                            End If
                            Application.DoEvents()
                        Loop While Com_port_received_text1 = ""

                        Com_port_received_text = Com_port_received_text + Com_port_received_text1   'combine received bits
                    End If

                    SerialPort1.Write(Com_port_received_text)               'replay received bits to arduino for verification
                    DataArray.Add(Com_port_received_text)                   ' save them in array
                    ReceivedBits = ReceivedBits + 16                        ' count how many bits was received
                    Com_port_received_text = ""
                    Com_port_received_text1 = ""

                Else

                    DataArray.RemoveAt(DataArray.Count - 1)                 'if arduino says we got wrong data remove it from array
                    Threading.Thread.Sleep(5)                               'wait some time for arduino to prepare and send again last bits
                    GoTo Retry                                              'go to the begining to get last bits again
                End If

          Else
NoResponse:
                TimerValue = 0
                Com_port_received_text = ""
                    Com_port_received_text1 = ""
                Do
                    If Com_port_received_text1.Contains("NOK") Then         'if arduino replays with NOK
                        Com_port_received_text1 = ""
                    End If
                    If TimerValue > 100 Then                                'if arduino stucks after 10 seconds
                        SerialPort1.Write("1")                              'write something to get arduino going
                        GoTo Retry
                    End If
                    Application.DoEvents()                                  'Be there until arduino responds
                Loop While Com_port_received_text1 = "" And Com_port_received_text = ""
            End If

            Application.DoEvents()
        Loop Until Com_port_received_text = "X"                              'indicates the end of transmission



Here you can see how arduino and pc handles errors



Arduino serial = RXD, pc serial = TXD

it is not visible on the image but computer didn't respond received data and arduino waits for respond. After 10s computer realizes that arduino waits for respond and it sends random bite.
Then arduino send NOK because random bite is not what was sent last time and arduino replays last bytes, then communication keeps going. on the image you can see that error occurred twice.

At the moment sometimes I'm getting one byte more than I should over serial. By looking at number of positive clock cycles it is clear that arduino sometimes clocks out 8 clocks extra but it happens only if I read more than 100k addresses. Im still fighting with this issue..

It is close to impossible to track with logic analyzer what causes this problem I made simple progress bar to show number of addresses readed. So if it is a glitch in software or hardware I should be able to see on what address it stuck therefore knowing address I can easily compare data between bin file and logic analyzer.

this is how it looks





Cvik_Dasa

Hello there, Im back. This time I have some great news, receiving data from eeprom seems to be fail proof.

At least it seems to be. I did some minor code changes and managed to solve all the problems. In fact im done with part of code used to read from eeprom.

I've tried to mess around with arduino's tx and rx lines while they communicate and I wasn't able to get them to fail. In fact you can disconnect tx and rx lines from pc and when you connect them back arduino will synchronize with pc and continue with transmission.

Ive tried to read more than 30 times 4Mb eeprom and it never failed but as last line of defense if it does it is smart enough to pop up error message letting you know that something went wrong.


I'm gonna take some time to clean vb code a bit because it looks like a mess and after that I will continue with coding

Go Up