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...
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.
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.
Capt_Rhizz:
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".
...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.
• 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.... :~
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?
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. :%
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..
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.
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..
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...
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.
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
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..
Thanks for the help AWOL. If I was understanding the datasheet correctly it seems we are taking 7 clock cycles to complete the instructions in between the two "st(ore)" instructions, which is over the required limit of within 4 clock cycles. But then how can we correct for this? What do we need to do to get it to within the specified limit of 4 clock cycles. Any help would be appreciated, thank you all. By the way my background is not in CS or computer engineering, i'm just trying to learn. Thank you all for helping.
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.
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
Yes, the code compiles for me as well (using Arduino Compiler) but EEPROM_write function does not write to an EEPROM address like it is suppose to. And I believe it is because of the reason AWOL and CodingBadly are pointing out: that the logic 1 flipping of the EEMPE bit and EEPE bit are not occuring within the specified time limit (4 clock cycles). If i read the datasheet correctly, it is taking 7 clock cycles. By the way, my custom EEPROM_read function works, tested it using the built-in EEPROM.write() function from the EEPROM.h, it is just that my custom EEPORM_write() function is not working properly.
TheArchitect22:
If I was understanding the datasheet correctly it seems we are taking 7 clock cycles to complete the instructions in between the two "st(ore)" instructions...
lds --> 2
lds --> 2
ld --> 2
ori --> 1
You did not include one of the st(ore) instructions in the total. I did mention twice that is necessary.
...which is over the required limit of within 4 clock cycles.
In any case that is correct. The code takes too long to set the second bit.