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 support@ccsinfo.com

3.204 & 3.205 Bug (part 1)
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Futureatwork
Guest







PostPosted: Tue Jul 13, 2004 11:28 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 13, 2004 4:13 pm     Reply with quote

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

View user's profile Send private message

Here is a 1 byte version: time for structs/unions again!
PostPosted: Tue Jul 13, 2004 6:15 pm     Reply with quote

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







PostPosted: Tue Jul 13, 2004 8:54 pm     Reply with quote

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

Cheers !

BTW, Hans, using union is the fastest, but it still need 2 bytes for PIC18, or 1 word, not 1 byte. Wink
C-H Wu
Guest







PostPosted: Tue Jul 13, 2004 9:06 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jul 14, 2004 2:01 am     Reply with quote

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. Smile
Guest








however...
PostPosted: Wed Jul 14, 2004 7:53 am     Reply with quote

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


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
PostPosted: Wed Jul 21, 2004 9:22 am     Reply with quote

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

 
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