|
|
View previous topic :: View next topic |
Author |
Message |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
four lines of code - 152++ instruct cycles of ouch ? |
Posted: Mon Aug 03, 2009 7:47 pm |
|
|
oh - would anybody care to thrash me ?
i have these four lines of code ( for an f887 v4.085 )
that generate 152 instructions and sucks up even more clock cycles to execute
fadd is an unsigned int8 used as an offset into EEPROM space,
and myid and myidck are both unsigned int16's
IS THERE A BETTER WAY TO DO THIS - instruction count wise ?
i do several similar uses of EEPROM and the code space burden is the worst thing in the program
Code: |
write_eeprom( fadd++, make8( MyId, 0));
write_eeprom( fadd++, make8( MyId, 1));
write_eeprom( fadd++, make8( MyIdCk, 0));
write_eeprom( fadd, make8( MyIdCk, 1));
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
which cuts it down some .... |
Posted: Mon Aug 03, 2009 9:25 pm |
|
|
after profiling the change that gets down to 115 instrux total
and is very worthwhile since the program is crafted to never have an issue with exec time , when EEPROM is being written to -
that gets it down 25% - which is better than before
i keep wondering if there is a more efficient way to access the bytes of the long ints as well - better than make8 - but looking at the ASM code for THAT does not give me much hope |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Tue Aug 04, 2009 1:03 am |
|
|
asmboy,
Since CCS C duplicates code freely, it is sometimes better to create a one-line function and call it repeatedly.
Code: |
void store_to_eeprom(int8 fadd, int8 dat)
{
write_eeprom(fadd, dat);
}
void main()
{
int8 fadd;
int16 dat, dat2;
fadd = 2;
store_to_eeprom(fadd++, make8(dat, 0));
store_to_eeprom(fadd++, make8(dat, 1));
store_to_eeprom(fadd++, make8(dat2, 0));
store_to_eeprom(fadd, make8(dat2, 1));
}
|
I counted 57 instructions in the four lines plus function for the F887.
Regards
Noam _________________ Every solution has a problem. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
what number base is that ??? |
Posted: Tue Aug 04, 2009 8:35 am |
|
|
So here is a link to what compiled for me - the LST file.
After making assignment changes and merging it with a live bit of code
see for yourself at
http://64.128.110.53/eep.txt
Am I and n-sq using different number bases when we count ?
I get way over a hundred instructs in the LST - but especially
the block of 28 instrux - the "wrapper" - that is executed 4 times
in runtime.
How am I misreading to LST file to get such a large number of
1- code space instructs
2- wicked big number of executed instructs ?
WAY more that N-sq counted or saw. |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Tue Aug 04, 2009 9:09 am |
|
|
Asmboy,
I included the complete listing below, for your review.
It seems to me that in your program the variables are located in different banks, which causes the compiler to switch back and forth between them.
Best regards
Noam
Code: |
CCS PCM C Compiler, Version 4.091, 43746 04-àåâåñè-09 22:45
Filename: C:\DEVELOP\test\main.lst
ROM used: 108 words (1%)
Largest free fragment is 2048
RAM used: 13 (4%) at main() level
15 (4%) worst case
Stack: 1 locations
*
0000: NOP
0001: MOVLW 00
0002: MOVWF 0A
0003: GOTO 022
.................... #include <16F887.h>
.................... //////// Standard Header file for the PIC16F887 device ////////////////
.................... #device PIC16F887
.................... #list
....................
.................... #device ICD=TRUE
.................... #device adc=8
....................
.................... #FUSES NOWDT //No Watch Dog Timer
.................... #FUSES INTRC_IO //Internal RC Osc, no CLKOUT
.................... #FUSES NOPROTECT //Code not protected from reading
.................... #FUSES NOBROWNOUT //No brownout reset
.................... #FUSES NOPUT //No Power Up Timer
.................... #FUSES NOCPD //No EE protection
.................... #FUSES NODEBUG //No Debug mode for ICD
.................... #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
.................... #FUSES NOWRT //Program memory not write protected
.................... #FUSES IESO //Internal External Switch Over mode enabled
.................... #FUSES FCMEN //Fail-safe clock monitor enabled
.................... #FUSES MCLR //Master Clear pin enabled
.................... #use delay(clock=8000000,RESTART_WDT)
.................... #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
....................
.................... void store_to_eeprom(int8 fadd, int8 dat)
.................... {
.................... write_eeprom(fadd, dat);
0004: MOVF 28,W
0005: BSF 03.6
0006: MOVWF 0D
0007: BCF 03.6
0008: MOVF 29,W
0009: BSF 03.6
000A: MOVWF 0C
000B: BSF 03.5
000C: BCF 0C.7
000D: BSF 0C.2
000E: BCF 03.5
000F: BCF 03.6
0010: MOVF 0B,W
0011: MOVWF 77
0012: BCF 0B.7
0013: BSF 03.5
0014: BSF 03.6
0015: MOVLW 55
0016: MOVWF 0D
0017: MOVLW AA
0018: MOVWF 0D
0019: BSF 0C.1
001A: BTFSC 0C.1
001B: GOTO 01A
001C: BCF 0C.2
001D: MOVF 77,W
001E: BCF 03.5
001F: BCF 03.6
0020: IORWF 0B,F
.................... }
0021: RETLW 00
....................
.................... void main()
.................... {
0022: CLRF 04
0023: BCF 03.7
0024: MOVLW 1F
0025: ANDWF 03,F
0026: MOVLW 71
0027: BSF 03.5
0028: MOVWF 0F
0029: MOVF 0F,W
002A: BSF 03.6
002B: BCF 07.3
002C: MOVLW 0C
002D: BCF 03.6
002E: MOVWF 19
002F: MOVLW A2
0030: MOVWF 18
0031: MOVLW 90
0032: BCF 03.5
0033: MOVWF 18
0034: BSF 03.5
0035: BSF 03.6
0036: MOVF 09,W
0037: ANDLW C0
0038: MOVWF 09
0039: BCF 03.6
003A: BCF 1F.4
003B: BCF 1F.5
003C: MOVLW 00
003D: BSF 03.6
003E: MOVWF 08
003F: BCF 03.5
0040: CLRF 07
0041: CLRF 08
0042: CLRF 09
....................
.................... int8 fadd;
.................... int16 dat, dat2;
....................
.................... fadd = 2;
0043: MOVLW 02
0044: BCF 03.6
0045: MOVWF 21
.................... store_to_eeprom(fadd++, make8(dat, 0));
0046: MOVF 21,W
0047: INCF 21,F
0048: MOVWF 26
0049: MOVF 22,W
004A: MOVWF 27
004B: MOVF 26,W
004C: MOVWF 28
004D: MOVF 22,W
004E: MOVWF 29
004F: CALL 004
.................... store_to_eeprom(fadd++, make8(dat, 1));
0050: MOVF 21,W
0051: INCF 21,F
0052: MOVWF 26
0053: MOVF 23,W
0054: MOVWF 27
0055: MOVF 26,W
0056: MOVWF 28
0057: MOVF 23,W
0058: MOVWF 29
0059: CALL 004
.................... store_to_eeprom(fadd++, make8(dat2, 0));
005A: MOVF 21,W
005B: INCF 21,F
005C: MOVWF 26
005D: MOVF 24,W
005E: MOVWF 27
005F: MOVF 26,W
0060: MOVWF 28
0061: MOVF 24,W
0062: MOVWF 29
0063: CALL 004
.................... store_to_eeprom(fadd, make8(dat2, 1));
0064: MOVF 25,W
0065: MOVWF 26
0066: MOVF 21,W
0067: MOVWF 28
0068: MOVF 25,W
0069: MOVWF 29
006A: CALL 004
.................... }
006B: GOTO 06B
Configuration Fuses:
Word 1: 0CF4 INTRC_IO NOWDT NOPUT MCLR NOPROTECT NOCPD NOBROWNOUT IESO FCMEN NOLVP DEBUG
Word 2: 3FFF NOWRT BORV40
|
_________________ Every solution has a problem. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Aug 04, 2009 12:43 pm |
|
|
Bank switching happens when you have non trivial programs
that use a lot of variables and buffers.
I need enough large char buffers in the code this was appended to ( 87% Ram used - 91% code space F887) - that many small vars get stuck in whatever space the compiler can stash them.
I should have noticed the bank switch overhead. |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Tue Aug 04, 2009 5:36 pm |
|
|
asmb,
You're welcome.
Sometimes we make TWO misteaks at a thyme.
N-sq _________________ Every solution has a problem. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Aug 04, 2009 6:53 pm |
|
|
As a general optimization trick in the PIC16, try to keep the memory hungry variables out of the first bank. This will create the most effective use of the access bank feature in the instruction set.
The CCS compiler assigns memory locations to the variables in the order they appear in the source code. Check the symbol file (*.sym) to see which large buffers are located in low memory and try to move these to other memory banks.
Furthermore the compiler is doing a poor job: Code: | .................... store_to_eeprom(fadd++, make8(dat1, 1));
0050: MOVF fadd,W
0051: INCF fadd,F
0052: MOVWF @@27
0053: MOVF dat1+1,W
0054: MOVWF @@28
0055: MOVF @@27,W
0056: MOVWF fadd_l
0057: MOVF dat1+1,W
0058: MOVWF dat_l
0059: CALL store_to_eeprom | This is not the most efficient generated code. The make8 is treated like a function and the return value is stored in a temporary location. Replacing the make8 function by a union saves three instructions: Code: | union
{
int16 dat;
char c[2];
} foo;
.................... store_to_eeprom(fadd++, foo.c[1]);
005A: MOVF fadd,W
005B: INCF fadd,F
005C: MOVWF @@27
005D: MOVWF fadd_l
005E: MOVF foo+1,W
005F: MOVWF dat_l
0060: CALL store_to_eeprom | This can be coded more nicely by creating a typedef for the union.
Another instruction can be saved by moving the increment out of the function call: Code: | union
{
int16 dat;
char c[2];
} foo;
.................... store_to_eeprom(fadd, foo.c[1]);
0061: MOVF fadd,W
0062: MOVWF fadd_l
0063: MOVF foo+1,W
0064: MOVWF dat_l
0065: CALL store_to_eeprom
.................... fadd++;
0066: INCF fadd,F
|
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Aug 04, 2009 7:54 pm |
|
|
DUH I shoulda thought of that.
THANK you ckielstra - that is a BIG help for more than just this one instance.
Brilliant and I can use the same sort of thing in several other places where I am messing with make8() and make16 from a int32
for no better reason than it was EZ and the compiler manual pages && doc kinda pointed in that direction.
I OWE U 1 |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Tue Aug 04, 2009 9:40 pm |
|
|
ckielstra,
Thanks for the tips.
I didn't get this far in optimizing the code.
Best regards
Noam _________________ Every solution has a problem. |
|
|
n-squared
Joined: 03 Oct 2006 Posts: 99
|
|
Posted: Tue Aug 04, 2009 9:59 pm |
|
|
As a further exercise, if we make the fadd variable a global and let the store_to_eeprom() increment it after each write, we save further.
For each sequence of writes, we set fadd to the first address and then start calling the function:
Code: |
#include <16F887.h>
#device ICD=TRUE
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES MCLR //Master Clear pin enabled
#use delay(clock=8000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
typedef union {
int16 dat;
int8 byt[2];
} WBX;
int8 fadd;
void store_to_eeprom(int8 dat)
{
write_eeprom(fadd, dat);
fadd++;
}
void main()
{
WBX d1,d2;
fadd = 2; // initialize eeprom address
store_to_eeprom(d1.byt[0]);
store_to_eeprom(d1.byt[1]);
store_to_eeprom(d2.byt[0]);
store_to_eeprom(d2.byt[1]);
}
|
This gets it down to 42 instructions. _________________ Every solution has a problem. |
|
|
|
|
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
|