|
|
View previous topic :: View next topic |
Author |
Message |
Futureatwork Guest
|
|
Posted: Tue Jul 13, 2004 11:28 am |
|
|
C-H Wu:
Quote: | Comment: in case of frequent RAM bank selection and switching is required, say, heavy RAM usage, using simple code like cmd = (int8)(address>>8); instead of pointer operation cmd = *(&address+1); avoid this kind of tricky bug. |
In my application, I have some data to move from eeprom to a struct and struct to eeprom. The way it is coded is *(&address+offset) like you said that can cause bugs...
Can you explain how (int8)((address+index)>>8); works? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Jul 13, 2004 4:13 pm |
|
|
In order to retrieve the high or low byte of an int16 xpercad started with the following code:
Code: | #define hi(x) (*(&x+1))
#define lo(x) (*(&x))
void write_ext_eeprom(int16 address, byte data)
{
byte low_byte, high_byte;
low_byte = lo(address); // 14 bytes
high_byte = hi(address); // 14 bytes
}
|
Then C-H Wu came with a simpler implementation that is easier to swallow by the compiler: Code: | low_byte = (int8)(address); // 4 bytes
high_byte = (int8)(address>>8); // 6 bytes |
But why is nobody using the CCS supplied command Make8(var, offset) ?
This can extract a single byte from an int8, int16 or int32 and does this with a single byte move.
Code: | low_byte = make8(address, 1); // 4 bytes
high_byte = make8(address, 0); // 4 bytes |
|
|
|
Hans Wedemeyer
Joined: 15 Sep 2003 Posts: 226
|
Here is a 1 byte version: time for structs/unions again! |
Posted: Tue Jul 13, 2004 6:15 pm |
|
|
If your code can tolerate one global variable for the Address then it will only require ONE byte to load the High or Low parts of the Address.
// struct to enable easy access to high and low byte
struct HighLow
{
char l;
char h;
};
typedef union HL_TAG
{
long L;
struct HighLow hl;
}HL16;
HL16 g_Address; // the global address for
void write_ext_eeprom( byte data)
{
byte low_byte, high_byte;
// I have no idea what the orginal user wanted to do with these. Of course the two bytes are not needed. Simply use the g_Address.hl.l and g_Address.hl.h directly, it saves even more space... can I then claim 0 Bytes... :-)
low_byte = g_Address.hl.l; // 1 byte
high_byte = g_Address.hl.h; // 1 byte
}
void main()
{
int data=0;
g_address = 32000;
write_ext_eeprom( data);
}
From the LST
.................... void write_ext_eeprom( byte data)
.................... {
.................... byte low_byte, high_byte;
....................
.................... low_byte = g_Address.hl.l; // 1 byte
0004: MOVFF 05,09
.................... high_byte = g_Address.hl.h; // 1 byte
0008: MOVFF 06,0A
.................... }
000C: GOTO 002C (RETURN)
.................... |
|
|
C-H Wu Guest
|
|
Posted: Tue Jul 13, 2004 8:54 pm |
|
|
It is great to know that there are quite a few different ways to do the job!
Here is CCS's reply to xpercad's e-mail: Quote: | You could also try changing your macros to this:
#define hi(x) (x>>8)
#define lo(x) (x&0xff)
|
CCS knew where could be the problem, they suggest simple, easy to understand, and robust algorithm.
make8(var, offset) is fast, equivalent to (((var >> (offset*8)) & 0xff), however, it is a CCS dialect. make8() is a good choice if portability is not an issue. The disadvantage, make8() can not be placed at the left hand side of an expression like *(int8 *)(&var+offset) = x.
I did learned a lot through this bug hunting experience.
Cheers !
BTW, Hans, using union is the fastest, but it still need 2 bytes for PIC18, or 1 word, not 1 byte. |
|
|
C-H Wu Guest
|
|
Posted: Tue Jul 13, 2004 9:06 pm |
|
|
Hi, Futureatwork:
Futureatwork wrote: | C-H Wu:
Quote: | Comment: in case of frequent RAM bank selection and switching is required, say, heavy RAM usage, using simple code like cmd = (int8)(address>>8); instead of pointer operation cmd = *(&address+1); avoid this kind of tricky bug. |
In my application, I have some data to move from eeprom to a struct and struct to eeprom. The way it is coded is *(&address+offset) like you said that can cause bugs...
Can you explain how (int8)((address+index)>>8); works? |
Sorry, it won't work.
y = (int8)(x>>8) is equivalent to y = *(&x+offset) only if the variable 'offset' equals to one, which is his case but not your case.
If the code *(&address+offset) does run into bugs of PCH 3.205, try 3.187 with #opt 10, or, wait for 3.206. I am always hesitate to use pointer because I am not good at C programming.
By the way, since you ask me to reply, someone else with better options might hold there just for politeness. It is time to ask them and I am looking forward to learn more.
Best wishes
C-H Wu |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jul 14, 2004 2:01 am |
|
|
Hi Hans,
Code: | From the LST
.................... void write_ext_eeprom( byte data)
.................... {
.................... byte low_byte, high_byte;
....................
.................... low_byte = g_Address.hl.l; // 1 byte
0004: MOVFF 05,09
.................... high_byte = g_Address.hl.h; // 1 byte
0008: MOVFF 06,0A
.................... }
000C: GOTO 002C (RETURN) |
These examples are not taking 1 byte!!! It's 1 instruction, but taking 2 instruction cycles and 4 bytes of code space!!! So your example of using a struct is taking the same amount of ROM space as the make8() function. |
|
|
Guest
|
however... |
Posted: Wed Jul 14, 2004 7:53 am |
|
|
ckielstra wrote: | Hi Hans,
Code: | From the LST
.................... void write_ext_eeprom( byte data)
.................... {
.................... byte low_byte, high_byte;
....................
.................... low_byte = g_Address.hl.l; // 1 byte
0004: MOVFF 05,09
.................... high_byte = g_Address.hl.h; // 1 byte
0008: MOVFF 06,0A
.................... }
000C: GOTO 002C (RETURN) |
These examples are not taking 1 byte!!! It's 1 instruction, but taking 2 instruction cycles and 4 bytes of code space!!! So your example of using a struct is taking the same amount of ROM space as the make8() function. |
Yes I mixed instructions with bytes...
Make8() has a very limited use and not is portable, as was pointed out it can't be used on the left side... whereas the struct/union can... |
|
|
C-H Wu Guest
|
Bug fixed ... in 3.207 |
Posted: Wed Jul 21, 2004 9:22 am |
|
|
Quote: | > Sent: Wednesday, July 21, 2004 9:37 PM
> Subject: Re: PCW Support for 3.206 22330{?}
>
> This message is a reply to CCS e-mail id: 4G3738
>
> The problem you reported has been fixed and will be in the
> next compiler release.
|
Let's wait and see if 3.207 really fixed it. |
|
|
|
|
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
|