Write manually to the E2PROM on AT TINY

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello All,

 

I am building a simple counter. The general idea is to do the counting in the loop(), while in the setup() the number of counting is checked, if above do that, if below do that...

 

OK, so far I can easily write the value into the e2prom via the eg. setup(), but every time the uC is turned on... it does that, so the question is: how to manually write the value in e2prom without the need to have that in the setup() ?

 

Any ideas? Thank you in advance and I am looking forward to your replies.

 

BEST.

This topic has a solution.

Bravo!!!

Last Edited: Mon. Nov 16, 2020 - 12:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are talking about setup()/loop() you are presumably talking about Arduino? If so then the only two places you can do stuff are in setup() (once, at the start) or in loop() (repeatedly as the program runs). The core AVR-LibC function for EEPROM access are:

 

https://www.nongnu.org/avr-libc/...

 

So you could just do:

int EEMEM myVar;

setup() {
    eeprom_update_word(&myVar, 12345);
}

loop() {
    
}

and that would just write 12345 to the EEPROM once at start up or you might have:

int EEMEM myVar;
int counter;

setup() {
    counter = 0;
}

loop() {
    counter++;
    eeprom_update_word(&myVar, counter);
}

But this would be a VERY BAD IDEA because this would be doing EEPROM writes 100's of times a second and, because an AVR EEPROM wears out after 100,000 writes it would not be long before you damaged the chip. So you'd probably do something more like
 

int EEMEM myVar;
int counter;

setup() {
    counter = 0;
}

loop() {
    if (infrequent_event_occurred) {
        counter++;
        eeprom_update_word(&myVar, counter);
    }
    // get o nwith other stuff that just sets
    // infrequent event ever once in a while
}

The key thing is to limit your EEPROM writing to only when you really must.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for all that, not sure, if I understand you rightly, but I would like to manually put the values into the e2prom... you have rightly point out that ep2om may burn out... so... my question is that eprom is programmed 1st when the program is downloaded on the uC, 2nd evertime the counter has found a count put the value into the e2prom, so thats it.

 

I guess the option would be to hard encode the value into the e2prom?

 

To my experience assembly code , etc can be used without the Arduino sketch... done that with the WDT... but never worked with the e2prom...

 

Thanks anyway...

 

BEST.

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rats, the system just lost the reply I typed but basically I was saying that you'd use something like:

char EEMEM myChar = 'A';
int EEMEM myInt = 12345;
long EEMEM myLong = 0xACEB1ADE;

then when you build this not only will a projectname.hex be created as normal and that is what you program into the flash of the AVR but (depending on build system) you should also get a file called projectname.eep and you use your ISP programmer to program that into the EEPROM of the AVR.

 

However if you are using Arduino then I'm not sure how this works - I don't know if it builds .eep files and, if it does, I have a feeling that not all Arduino bootloaders have the capability to receive and program .eep data.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I understand you correctly what you could do is, in setup(), check the EEPROM to see if it is blank (or contains the correct data). If it is blank, or contains incorrect data, you write your startup values to it. If the data is already there then you skip that step.

 

This is what I do in several commercial units. On first run I store the default settings. After that the unit uses any setting that have been changed...

eeprom uint8_t gSomeVariable;
eeprom uint16_t gAnotherVariable;

...

if (gSomeVariable = 0xFF) {
    gSomeVariable = 0x01;
    gAnotherVariable = 0x02;
    ...
}

(Note: CVAVR syntax)

 

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Last Edited: Wed. Nov 4, 2020 - 10:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is more like it :) So what I am doing is this:

 

outside the setup() or loop()

 

byte EEMEM myByte = 5;  

 

although this is all good, I am not sure how to fund this number, for example, when I read the EEPROM usually EEPROM.read(0) is used, read the value on location 0, therefore, not sure how is the location of value specified with the above example?

 

Not sure pow to program the .eep?

 

I am working simple with downloading the .hex on tiny via usbasp.

 

 

Bravo!!!

Last Edited: Wed. Nov 4, 2020 - 10:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

 

It's common to use the Arduino array operator overload and refer to eeprom locations as e.g. EEPROM[27];

 

However, if you use the update functions (see link in #2):

  • In addition to the write functions there is a set of update ones. This functions read each byte first and skip the burning if the old value is the same with new. The scaning (sic) direction is from high address to low, to obtain quick return in common cases.

In this case, the EEPROM won't be worn out if the values haven't changed and you only waste some compute cycles. Of course, you should really do it properly, as per #5.

 

The Arduino bootloaders don't have the functionality to program the EEPROM when the sketch is uploaded. The developers preferred size and simplicity, which seems a wise decision given the target audience.

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian Fairchild wrote:
If I understand you correctly what you could do is, in setup(), check the EEPROM to see if it is blank (or contains the correct data).
Oh I see, I completely missed that in OP. In which case a common approach is a "cookie". Such as:

typedef struct {
    char c;
    int n;
    long l
    uint32_t cookie;
} eeVars_t;

eeVars_t myEEVars;

setup() {
    if (eeprom_read_dword(&myEEVars.cookie != 0xDEADBEEF)) {
        eevars_t inRam;
        inRam.c = 'A';
        inRam.n = 12345;
        inram.l = 0xBABEFACE;
        inRam.cookie = 0xDEADBEEF;
        eeprom_update_block(&inRam, &myEEVvars, sizeof(eeVars_t));
    }
}

loop () {
    
}

When you first program and switch on an AVR the chances are that if the EEPROM has not been used yet all locations will contain 0xFF. So when this code first reads the myEEcars.cookie location at first setup() it will read 0xFFFFFFFF. Because this is not the "cookie" value 0xDEADBEEF it knows the EEPROM has not been touched yet so it will create a copy of the EEPROM layout in RAM (called "inRAM") and set all the initial values into it. Then it will write the whole block from RAM to EEPROM. Because the fields that are written include the .cookie field and it has now been set to 0xDEADBEEF then, at next power on, the code will read myEEVars.cookie as 0xDEADBEEF and skip the initialisation.

 

If you ever want to reset everything just corrupt the .cookie field by writing something other than 0xDEADBEEF to it.

 

Be warned that if you program a code update into the AVR that usually starts with a Chip Erase and part of a chip erase is "wipe EEPROM" (which will return .cookie (and everythning) to 0xFF bytes) so you settings will be lost. There is a fuse called EESAVE which you can set to prevent EEPROM being cleared during a code update - you might want to explore how to set that if you want to retain settings while still developing the code and programming updates.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

The datasheet for the chip should have some examples of writing to the EEPROM...it's just a few lines of code & away you go.  

Avoid location zero---easily corrupted

It was nice when they used to include some samples to try out.  They determined that was too easy and straightforward to be of much use to anyone looking for a complex and difficult procedure.

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. Nov 4, 2020 - 10:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mu234 wrote:

This is more like it :) So what I am doing is this:

 

outside the setup() or loop()

 

byte EEMEM myByte = 5;  

 

although this is all good, I am not sure how to fund this number, for example, when I read the EEPROM usually EEPROM.read(0) is used, read the value on location 0, therefore, not sure how is the location of value specified with the above example?

 

Not sure pow to program the .eep?

 

I am working simple with downloading the .hex on tiny via usbasp.

As I say that 5 would only be there if (a) a .eep is created during the build and (b) the programming system for the AVR allows .eep contents to be delivered to the EEPROM. If there is a problem with either (a) or (b), and I think there may be if this is Arduino, then do as Brian suggested and I then showed an example of in posts #5 and #8

 

BTW if you want to be sure that EEPROM things are always laid out in an exact order then group everything into a struct as I did. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cheers for all the inputs, this is what I have so far, it works, but as you can see I have a fuse, namely the if() in the setup to actually set the eeprom to the arithmetic number which is actually counted, indeed, after this is set then the if is put to false to avoid this every time ...

 

Please comment, if I am using the eeprom correctly, I do not want to burn it out :)

// install dependencies
#include <Bounce2.h>      // debouncer
#include <EEPROM.h>       // e2prom

//byte EEMEM myByte = 0;  

// constant variables for pins
const byte LED = 4;  // pin 2 , at tiny 4 / arduino testing on pin 13
const byte SWITCH = 3; // pin 3

int switchState = HIGH;
int a;                  // eeprom location
byte counting = 0;      //counter

// THE AMOUNT OF PROGRAMMING ALOWED
byte maxProgNumber = 5;    //maximum number of programming ?!?!?!??!?!?!

Bounce debouncer = Bounce(); // Instantiate a Bounce object

void setup ()
{
//  Serial.begin(9600);
//  while (!Serial) {
//    Serial.println("Waiting for servial to begine?!"); // wait for serial port to connect. Needed for native USB port only
//  }

  pinMode (LED, OUTPUT);
  digitalWrite(LED, switchState);

  pinMode (SWITCH, INPUT);
  digitalWrite (SWITCH, HIGH);  // internal pull-up

  debouncer.attach(SWITCH, INPUT_PULLUP);
  debouncer.interval(50); //higher "debounce" time due to measuring only the actuall programming, which takes more than 500ms... so use 50 when testing on short intervals ...

//****************************************************************************************************************

  // THE FUSE

  // If (true), you will delete the e2prom and reset the programmator

  //  If (false) you will just use the programmator
  
//**************************************************************************************************************** 
  
  if (false) {
    // delete the number of programming and write to eeprom !
    EEPROM.update(0, 0);

    // reset the number of programmiong to 1 ! Do not forget to FALSE this when done!!!
    //    // delete complete eeprom
    //    for (int i = 0 ; i < EEPROM.length() ; i++) {
    //      EEPROM.write(i, 0);
    //    }
  } else {
  
    //FUSE, disable the programmer, if the maximum number of programming is reached
    //read the address 0 in the e2prom and store its value to the counting variable...

    counting = EEPROM.read(0); // the last number of programming
    //counting = 1;

    // check, if the counting is above or equall to "the allowed number of programming"
    if (counting > maxProgNumber) {
      // we are using the analogWrite, because PINs are not declared as digital?
      //if so, freeze the program and disable programming ->>>>> RED LED
      analogWrite(LED, 0);
      //while (true);
    }
    //otherway around, alow further programming ->>>>>> GREEN LED
    else {
      //Serial.println("we are not over");
      analogWrite(LED, 255);
      //while (true);
    }
  }
}  // end of setup, continue with the loop :)

void loop () {
//  Serial.print("Counting ");
//  Serial.print( counting  );
//  Serial.print(" maxProgNumber ");
//  Serial.println( maxProgNumber );

  debouncer.update();  // watch for the lenght of the time the pin was high...

  //count the number of programming
  if ( debouncer.fell() ) {  // Call code if button transitions from HIGH to LOW
    switchState = !switchState; // Toggle LED state
    //digitalWrite(LED, ledState); // Apply new LED state
    counting++; //increase the timer
    //write the last number of programinh to the e2prom
    EEPROM.write(0, counting);
  }

  //if the max number of programming is reached disable the programmer
  if (counting >= maxProgNumber) {
    analogWrite(LED, 0);
    //analogWrite(13, 255);
  }


}  // end of loop

 

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're mixing EEPROM.update() and EEPROM.write(). Are compute cycles at such a premium that you can't use .update() everywhere ?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

obdevel wrote:
You're mixing EEPROM.update() and EEPROM.write(). Are compute cycles at such a premium that you can't use .update() everywhere ?
Those map to the AVR-LibC functions eeprom_write_type() and eeprom_update_type(). You should never use the write functions, always use the update ones. True there is a miniscule additional overhead in update that it does a read check before write but it's worth it because it ensure the write (which will reduce the 100,000 life of the EEPROM) will not go ahead if the check read finds that the value that is about to be written is the value already there. So:

for (long l = 0; l < 200000; l++) {
    EEPROM.write(&foo, 0x55);
}

would destory your EEPROM while:

for (long l = 0; l < 200000; l++) {
    EEPROM.update(&foo, 0x55);
}

would write just once and skip the next 199,999 potential writes. At the end that location in the EEPROM would still have 99,999 writes of its 100,000 cycle life left.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, thanks for this input, did you ever try e.g. the C example ? How would you hard encode this eg. in Arduino?

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used those steps for many years....it's basically the bottom line of what must be done to use the  EEPROM (not much, really).  Can't say what Arduino does.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all,

 

the easiest solution was to use the AVRDude terminal and program the EEPROM directly :)

 

Thanks for all your inputs anyway!

 

Best.

Bravo!!!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please mark your solution

 

jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user