Go Down

Topic: EEPROM **Hardware Level** programming ( 2560 Mega) (Read 5211 times) previous topic - next topic

Capt_Rhizz

Hello all!

Brief history: been using the arduino for college. Been only using hard ware level programming. AKA accessing everything from scratch. Such as creating my own functions for serial capabilities.

Here's the question. And  I have read through the manual on this, but my code for the write function, just is not working. I am really sure I got the sequence correct. However, the darn thing just will not write.

Any ideas?

void EepromWrite(unsigned short address, unsigned char data)
{
  while( *myEECR & 0x02){}//wait for completion of previous write//

  // defining which addres to be written to
  *myEEARhigh= 0x00;
  *myEEARlow = 0x01;
 
*myEEDR = data;// putting data in temp reg

*myEECR |= 0x04;// writing 1 to EEMPE bit

*myEECR |= 0x02;// now writing to EEPE bit which starts write

 
}

Here are the declarations of registers:
/////////////////////////////////////////////////////////////////
//EEPROM REG
////////////////////////////////////////////////////////////////
//Where the adresses live to store data
volatile unsigned char *myEEARlow = (unsigned char*) 0x41;
volatile unsigned char *myEEARhigh = (unsigned char*) 0x42;
//EEPROM control register
volatile unsigned char *myEECR = (unsigned char*) 0x3F;
//where the value is stored before it goes into the EEPROM storage address
volatile unsigned char *myEEDR = (unsigned char*) 0x40;


Anyone who can help will help my understanding I thank in advance. BTW the assignment is over. So take your time... :smiley-mr-green:

Coding Badly


Writing to EEPROM involves a timed sequence.  Does your code execute within the time limit?

Budvar10

It looks like an examle from datasheet. Try EEARH 0x22; EEARL 0x21; EEDR 0x20; EECR 0x1F instead.
Arduino clone with ATmega1284P   http://forum.arduino.cc/index.php?topic=277260.0

Capt_Rhizz

Yes the sequence should be within 4 cycles. I imagine these executions happen within a mater of a fraction of micro seconds.

As for those Hex values Budvar10; are you suggestion I try the other addresses given in the data sheet, instead of where I declared their homes already? Because there are generally two addressees given for each register within the manual.

Coding Badly

Quote
I imagine these executions happen within a mater of a fraction of micro seconds.


The time the processor takes to execute those instructions is irrelevant.  For example, if the processor is running from a 1 Hz clock it will take more than four seconds to write to the EEPROM.

The number of cycles is what is important.

Yes the sequence should be within 4 cycles.


In other words, you took no action, exerted no effort, to verify your assumption is correct.  If you had, you would know the answer to the question is "no".

Quote
...are you suggestion I try the other addresses given in the data sheet, instead of where I declared their homes already?


The compiler has enough intelligence to use the lower addresses when appropriate.

Capt_Rhizz

#5
Sep 26, 2014, 05:49 am Last Edit: Sep 26, 2014, 05:51 am by Capt_Rhizz Reason: 1


• Bit 2 - EEMPE: EEPROM Master Programming Enable
The EEMPE bit determines whether setting EEPE to one causes the EEPROM to be written.
When EEMPE is set, setting EEPE within four clock cycles will write data to the EEPROM at the
selected address If EEMPE is zero, setting EEPE will have no effect. When EEMPE has been
written to one by software, hardware clears the bit to zero after four clock cycles. See the
description of the EEPE bit for an EEPROM write procedure.

Ok, so what "point" are you trying to drive? I don't think I am following.... :~

Coding Badly


This is the code that has to execute within four clock cycles...

Code: [Select]
 *myEECR |= 0x04;// writing 1 to EEMPE bit
 *myEECR |= 0x02;// now writing to EEPE bit which starts write


This is the resulting assembly...

Code: [Select]
 ec: e0 91 04 01 lds r30, 0x0104
 f0: f0 91 05 01 lds r31, 0x0105
 f4: 80 81       ld r24, Z
 f6: 84 60       ori r24, 0x04 ; 4
 f8: 80 83       st Z, r24

 fa: e0 91 04 01 lds r30, 0x0104
 fe: f0 91 05 01 lds r31, 0x0105
102: 80 81       ld r24, Z
104: 82 60       ori r24, 0x02 ; 2
106: 80 83       st Z, r24


Between the two st(ore) instructions and including one st(ore) is the important part.  The first st(ore) sets the EEMPE bit.  The second st(ore) sets the EEPE bit.  Instruction timing, in cycles, is available in the datasheet.  What are the total cycles?

Capt_Rhizz

#7
Sep 26, 2014, 07:59 am Last Edit: Sep 26, 2014, 08:31 am by Capt_Rhizz Reason: 1
This is me going out on a limb here... 10 cycles? I am just guessing that each line is an instruction and an instruction is a cycle? And if this is so, it took 5 cycles between the bit operations.

My teacher made us produce this assembly, but never went over its significance nor how to read it. So I guess I am lost again on this one. Not very familiar with assembly. More the C language level. You sure are making me work for this one Baldly. Which I do appreciate, yet I am still unfortunately not understanding.  :%

Coding Badly

I am just guessing...


Guessing leads to a crashed Mars rover.

I told you the important instruction: "st".  There are two "st" instructions in the listing.  What instructions are between the two "st" instructions?

Capt_Rhizz

Ahh yes, but guessing also leads to more thought provoking answers in the form of questions.  :smiley-zipper: 

TheArchitect22

It seems to me there are 4 instructions between the two (st)ore instuctions:  ldr, ldr, ld, ori...   I myself do not know how to interpret assembly language.  So if you don't mind me asking?  What is the significance of these in-between instructions?  And how do we know how long these instructions are taking in cycles.  I tried looking for it on the 2560 ATmel manual but no look so far.  I digress and will continue to search though..

TheArchitect22

Also if we are outside the given parameters (in this case 4 clock cycles), how can we correct for this error?  Do we have to do something with the produced assembly language??  Thank you in advance for any help.

AWOL


It seems to me there are 4 instructions between the two (st)ore instuctions:  ldr, ldr, ld, ori...   I myself do not know how to interpret assembly language.  So if you don't mind me asking?  What is the significance of these in-between instructions?  And how do we know how long these instructions are taking in cycles.  I tried looking for it on the 2560 ATmel manual but no look so far.  I digress and will continue to search though..

http://www.atmel.com/Images/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf
Instruction set summary, page 404

Capt_Rhizz

From some searching around on the internets. I saw that each instruction should be added together, then multiplied by 2.5. So if what I am thinking is correct and that is for each St or store instruction; it is taking up 2.5 clock cylcles. So if those are the only instructions then the total would be 5 cycles and we would thus be over the given time.

So how is this corrected. Can I just do this:

FROM:
*myEECR |= 0x04;// writing 1 to EEMPE bit

*myEECR |= 0x02;// now writing to EEPE bit which starts write

TO:
*myEECR |=06;

Then it would be done it one instruction? But not in a sequence...

I feel a bronze star for effort coming.. :smiley-roll-sweat:

Budvar10

Quote
Quote
Quote
It looks like an examle from datasheet. Try EEARH 0x22; EEARL 0x21; EEDR 0x20; EECR 0x1F instead.
...are you suggestion I try the other addresses given in the data sheet, instead of where I declared their homes already?
The compiler has enough intelligence to use the lower addresses when appropriate.

Yes, that is exactly true. It does'n matter which addresses are used.

I 've tried to compile the code from datasheet and Capt_Rhizz code also in AtmelStudio and both worked.
Code: [Select]
while(EECR & (1 << EEPE));
000001AF  SBIC 0x1F,1 Skip if bit in I/O register cleared
000001B0  RJMP PC-0x0001 Relative jump
EEAR = 1;
000001B1  LDI R24,0x01 Load immediate
000001B2  LDI R25,0x00 Load immediate
000001B3  OUT 0x22,R25 Out to I/O location
000001B4  OUT 0x21,R24 Out to I/O location
EEDR = 0x55;
000001B5  LDI R24,0x55 Load immediate
000001B6  OUT 0x20,R24 Out to I/O location
EECR |= (1 << EEMPE);
000001B7  SBI 0x1F,2 Set bit in I/O register
EECR |= (1 << EEPE);
000001B8  SBI 0x1F,1 Set bit in I/O register


while(*myEECR & 0x02) {}
000001B9  SBIC 0x1F,1 Skip if bit in I/O register cleared
000001BA  RJMP PC-0x0001 Relative jump
*myEEARhigh = 0;
000001BB  OUT 0x22,R1 Out to I/O location
*myEEARlow  = 1;
000001BC  LDI R24,0x01 Load immediate
000001BD  OUT 0x21,R24 Out to I/O location
*myEEDR     = 0xAA;
000001BE  LDI R24,0xAA Load immediate
000001BF  OUT 0x20,R24 Out to I/O location
*myEECR    |= 0x04;
000001C0  SBI 0x1F,2 Set bit in I/O register
*myEECR    |= 0x02;
000001C1  SBI 0x1F,1 Set bit in I/O register

Arduino clone with ATmega1284P   http://forum.arduino.cc/index.php?topic=277260.0

Go Up