CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Reusing write_eeprom code

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rbarbali



Joined: 17 Dec 2015
Posts: 8

View user's profile Send private message

Reusing write_eeprom code
PostPosted: Tue Jun 29, 2021 5:32 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jun 29, 2021 6:00 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jun 29, 2021 7:22 am     Reply with quote

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.... Sad

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

View user's profile Send private message

PostPosted: Tue Jun 29, 2021 8:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jun 29, 2021 12:06 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jun 30, 2021 6:36 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jun 30, 2021 11:56 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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