|
|
View previous topic :: View next topic |
Author |
Message |
rbarbali
Joined: 17 Dec 2015 Posts: 8
|
Reusing write_eeprom code |
Posted: Tue Jun 29, 2021 5:32 am |
|
|
PIC16F18875, CCS PCM V5.101 DEMO
Hi. I need to write the internal eeprom several times in a program. Using write_eeprom() as follows:
Code: | void main()
{
WHILE(TRUE)
{
write_eeprom(0,0);
write_eeprom(1,0);
write_eeprom(2,0);
write_eeprom (3, 0);
}
} |
the generated code asm code (from .lst file) is:
Code: |
.................... while(TRUE)
.................... {
.................... write_eeprom(0,0);
001A: MOVF 0B,W
001B: MOVWF 77
001C: BCF 0B.7
001D: MOVLB 10
001E: CLRF 1A
001F: MOVLW 70
0020: MOVWF 1B
0021: CLRF 1C
0022: BSF 1E.6
0023: BSF 1E.2
0024: MOVLW 55
0025: MOVWF 1F
0026: MOVLW AA
0027: MOVWF 1F
0028: BSF 1E.1
0029: BTFSC 1E.1
002A: GOTO 029
002B: BCF 1E.2
002C: BCF 1E.6
002D: MOVF 77,W
002E: IORWF 0B,F
.................... write_eeprom(1,0);
002F: MOVF 0B,W
0030: MOVWF 77
0031: BCF 0B.7
0032: MOVLW 01
0033: MOVWF 1A
0034: MOVLW 70
0035: MOVWF 1B
0036: CLRF 1C
0037: BSF 1E.6
0038: BSF 1E.2
0039: MOVLW 55
003A: MOVWF 1F
003B: MOVLW AA
003C: MOVWF 1F
003D: BSF 1E.1
003E: BTFSC 1E.1
003F: GOTO 03E
0040: BCF 1E.2
0041: BCF 1E.6
0042: MOVF 77,W
0043: IORWF 0B,F
.................... write_eeprom(2,0);
0044: MOVF 0B,W
0045: MOVWF 77
0046: BCF 0B.7
0047: MOVLW 02
0048: MOVWF 1A
0049: MOVLW 70
004A: MOVWF 1B
004B: CLRF 1C
004C: BSF 1E.6
004D: BSF 1E.2
004E: MOVLW 55
004F: MOVWF 1F
0050: MOVLW AA
0051: MOVWF 1F
0052: BSF 1E.1
0053: BTFSC 1E.1
0054: GOTO 053
0055: BCF 1E.2
0056: BCF 1E.6
0057: MOVF 77,W
0058: IORWF 0B,F
.................... write_eeprom(3,0); }
0059: MOVF 0B,W
005A: MOVWF 77
005B: BCF 0B.7
005C: MOVLW 03
005D: MOVWF 1A
005E: MOVLW 70
005F: MOVWF 1B
0060: CLRF 1C
0061: BSF 1E.6
0062: BSF 1E.2
0063: MOVLW 55
0064: MOVWF 1F
0065: MOVLW AA
0066: MOVWF 1F
0067: BSF 1E.1
0068: BTFSC 1E.1
0069: GOTO 068
006A: BCF 1E.2
006B: BCF 1E.6
006C: MOVF 77,W
006D: IORWF 0B,F
006E: MOVLB 13
006F: GOTO 01A
....................
.................... }
0070: SLEEP
|
I see it doesn't reuse the write_eeprom() code (a waste of rom, I think), but using the following code:
Code: | void write_eeprom2(INT8 addr, int8 value)
{
write_eeprom (addr, value);
}
void main()
{
WHILE (TRUE)
{
write_2eeprom (0, 0) ;
write_2eeprom (1, 0) ;
write_2eeprom (2, 0) ;
write_2eeprom (3, 0);
}
} |
the generated code looks like:
Code: |
.................... void write_eeprom2(int8 addr, int8 value)
.................... {
.................... write_eeprom(addr, value);
0003: MOVF 0B,W
0004: MOVWF 77
0005: BCF 0B.7
0006: MOVF 21,W
0007: MOVLB 10
0008: MOVWF 1A
0009: MOVLW 70
000A: MOVWF 1B
000B: MOVLB 00
000C: MOVF 22,W
000D: MOVLB 10
000E: MOVWF 1C
000F: BSF 1E.6
0010: BSF 1E.2
0011: MOVLW 55
0012: MOVWF 1F
0013: MOVLW AA
0014: MOVWF 1F
0015: BSF 1E.1
0016: BTFSC 1E.1
0017: GOTO 016
0018: BCF 1E.2
0019: BCF 1E.6
001A: MOVF 77,W
001B: IORWF 0B,F
001C: MOVLB 00
001D: RETURN
.................... while(TRUE)
.................... {
.................... write_eeprom2(0,0);
0035: MOVLB 00
0036: CLRF 21
0037: CLRF 22
0038: CALL 003
.................... write_eeprom2(1,0);
0039: MOVLW 01
003A: MOVWF 21
003B: CLRF 22
003C: CALL 003
.................... write_eeprom2(2,0);
003D: MOVLW 02
003E: MOVWF 21
003F: CLRF 22
0040: CALL 003
.................... write_eeprom2(3,0); }
0041: MOVLW 03
0042: MOVWF 21
0043: CLRF 22
0044: CALL 003
0045: GOTO 036
....................
.................... }
0046: SLEEP
|
What I am missing? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Tue Jun 29, 2021 6:00 am |
|
|
The compiler does that; I think their natural default is to optimize for speed not code size. As you've already figured out, wrap their function inside your own function and the compiler will create one function instead of inline-ing everything. If code space is an issue, you need to have a look at the disassembly to see if things could be grouped better. I know from experience that things like a printf() the compiler will tend to try and inline for some reason. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Jun 29, 2021 7:22 am |
|
|
It is also always going to be far better to loop things:
Code: |
WHILE(TRUE)
{
for (int cnt=0;cnt<4;cnt++)
write_eeprom(cnt,0);
}
|
If you are writing multiple variables to EEPROM, then put these in a single
structure, and loop through the structure using a pointer and a counter.
Also though' beware'. Hopefully this doesn't reflect something even remotely
similar to anything you would do 'for real'. Remember every write to EEPROM
uses a life on a memory cell. What you show could 'kill' an EEPROM in
only a few minutes....
What the compiler is doing here is actually not that inefficient. The setup to
actually 'call' the function is so large compared to the actual write
operation, and calling slows this down a little, and also adds some
more overhead. The compiler normally switches between coding as inline,
and calling a function, when the size grows to perhaps 50% larger.
As already said the default is to code for speed. |
|
|
rbarbali
Joined: 17 Dec 2015 Posts: 8
|
|
Posted: Tue Jun 29, 2021 8:46 am |
|
|
Thanks newguy & Ttelmah.
The code I attached is only to show the problem. My final program is a bigger program that writes the eeprom 1 time a day maximum. I can't use a "for loop".
The amount of ROM is of importance. I use the write_eeprom() 20 times.
The difference between this:
Code: | void main()
{
WHILE (TRUE)
{
write_eeprom (0, 0) ;
write_eeprom (1, 0) ;
write_eeprom (2, 0) ;
write_eeprom (3, 0);
write_eeprom (0, 0) ;
write_eeprom (1, 0) ;
write_eeprom (2, 0) ;
write_eeprom (3, 0);
write_eeprom (0, 0) ;
write_eeprom (1, 0) ;
write_eeprom (2, 0) ;
write_eeprom (3, 0);
write_eeprom (0, 0) ;
write_eeprom (1, 0) ;
write_eeprom (2, 0) ;
write_eeprom (3, 0);
write_eeprom (0, 0) ;
write_eeprom (1, 0) ;
write_eeprom (2, 0) ;
write_eeprom (3, 0);
}
} |
and this:
Code: | void write_eeprom2(INT8 addr, int8 *zones)
{
write_eeprom (addr, zones);
}
void main()
{
WHILE (TRUE)
{
write_eeprom2 (0, 0) ;
write_eeprom2 (1, 0) ;
write_eeprom2 (2, 0) ;
write_eeprom2 (3, 0);
write_eeprom2 (0, 0) ;
write_eeprom2 (1, 0) ;
write_eeprom2 (2, 0) ;
write_eeprom2 (3, 0);
write_eeprom2 (0, 0) ;
write_eeprom2 (1, 0) ;
write_eeprom2 (2, 0) ;
write_eeprom2 (3, 0);
write_eeprom2 (0, 0) ;
write_eeprom2 (1, 0) ;
write_eeprom2 (2, 0) ;
write_eeprom2 (3, 0);
write_eeprom2 (0, 0) ;
write_eeprom2 (1, 0) ;
write_eeprom2 (2, 0) ;
write_eeprom2 (3, 0);
}
} |
is 445 bytes vs 151 bytes (294 bytes).
With read_eeprom() is the same, but the difference is less.
Thank you. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Tue Jun 29, 2021 12:06 pm |
|
|
Why can't you use a loop though?.
Seems easy, even if you have to use an array to give you the index required. |
|
|
rbarbali
Joined: 17 Dec 2015 Posts: 8
|
|
Posted: Wed Jun 30, 2021 6:36 am |
|
|
Oh, because it is a big (6 kB) program and I write one byte of eeprom here, another there, as some unrelated events occur. In some events I write a 4-byte packet:
Code: | void AddEepromCR(int8 * p)
{
int8 i;
for(i = 0; i < 4; i++) WriteEeprom(EE_BASE_CR_ADDR + qty_CR * 4 + i, *(p + i));
qty_CR++;
WriteEeprom(EE_CR_QTY_ADDR, qty_CR);
AddEventQueue(0x5E, 0xAA);
} |
I don't know if there is an advantage in writing the entire eeprom (?).
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Wed Jun 30, 2021 11:56 pm |
|
|
No, you would never 'write the entire EEPROM'.
If however, this was an external EEPROM, the best way to work would be
to write a page, or a section of a page.
On the external EEPROM's, the memory is always? organised as 'pages',
typically something between perhaps 8, and 64 bytes. The chips take as
long to write a single byte as a 'page'. So if the data was organised as a
record, that fitted into a page, you could just write this page (or section
of a page), as a single write operation. Potentially much nicer. The page
write also only uses one erase cycle of the chip.
I put '?' on the 'always', since a very few of the earliest EEPROM's are byte
orientated like the PIC ones. However I can't at the moment think of any
even remotely modern EEPROM that does not use a 'page'. This is simply
because it is a cheaper design to do...
However the internal EEPROM, is instead 'byte' organised, so byte writes
are the way to go.
In your case, since you are changing semi 'random' bytes, then the
approach of simply encapsulating the write is going to be the way to go. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|