Searching \ for '[PIC] C18 Fun! :(' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'C18 Fun! :('.

Exact match. Not showing close matches.
PICList Thread
'[PIC] C18 Fun! :('
2005\12\31@144837 by Herbert Graf

picon face
Hello all, get ready for me having done something pretty daft...

I'm trying to get something going with C18:

       unsigned char [BUFFER_LEN] buffer;
       unsigned long checksum = 0;
       unsigned int ip_header_len;
       unsigned int i = 0;
       
       
       //some code that assigns buffer values and other stuff
       ...
       ...

       for (; i+1 < ip_header_len + IP_OFFSET; i = i+2)
       {
               checksum = checksum + buffer[i]*256 + buffer[i+1];
       }

       //now invert
       checksum = ~checksum;

This is a snippit of some code I'm putting together.

Basically what it's supposed to do is group two bytes in "buffer" at a
time, convert them to a 16bit number, and add them to checksum.

Sounds simple? Well, the 16bit stuff works fine, for example, the first
two bytes collected from "buffer" are 0x45 and 0x00, after running the
for loop once the ICD correctly reports that checksum = 0x00004500.

This continues on, until I get to a point where the number is bigger
then 16 bits. At that point "checksum" acts like it's a 16bit number,
going from say 0x0000fe00 to 0x00001045.

Does anyone see something wrong with how I've done things here? Is there
something about C or C18 that will "demote" the unsigned long
"checksum" (which, according to the C18 manual, unsigned long = 32bits,
plus the MPLAB watch window reports it's 32 bits long) from a 32bit
value to a 16bit value for this calc?

I've confirmed the "wrong" result isn't something the ICD2 does since
the outside work also sees the result of the "wrong" value.

All optimizations in C18 have been disabled.

I've also tried other "lines" like:
checksum += buffer[i]*256 + buffer[i+1];
checksum += buffer[i]<<8 + buffer[i+1];
checksum += (unsigned long)(buffer[i]*256 + buffer[i+1]);

The interesting thing is after running the checksum = ~checksum line,
checksum comes back with it's upper bits flipped (as you'd expect!).

i.e.
checksum = 0x0000aa55
checksum = ~checksum;
-> checksum = 0xffff55aa is what the ICD2 reports

Thanks for any clues.

TTYL


-----------------------------
Herbert's PIC Stuff:
http://repatch.dyndns.org:8383/pic_stuff/

2005\12\31@152006 by WH Tan

picon face
On 1/1/06, Herbert Graf <spam_OUThgrafTakeThisOuTspamemail.com> wrote:
> checksum = checksum + buffer[i]*256 + buffer[i+1];

> I've also tried other "lines" like:
> checksum += buffer[i]*256 + buffer[i+1];
> checksum += buffer[i]<<8 + buffer[i+1];
> checksum += (unsigned long)(buffer[i]*256 + buffer[i+1]);

I'm not sure but try this:

checksum = checksum + (unsigned long) buffer[i]*256 + buffer[i+1];

or

checksum += (unsigned long) buffer[i]<<8 + buffer[i+1];

--
WH Tan

2005\12\31@164847 by Jose Da Silva

flavicon
face
On December 31, 2005 12:20 pm, WH Tan wrote:
> On 1/1/06, Herbert Graf <.....hgrafKILLspamspam@spam@email.com> wrote:
> > checksum = checksum + buffer[i]*256 + buffer[i+1];
> >
> > I've also tried other "lines" like:
> > checksum += buffer[i]*256 + buffer[i+1];
> > checksum += buffer[i]<<8 + buffer[i+1];
> > checksum += (unsigned long)(buffer[i]*256 + buffer[i+1]);
>
> I'm not sure but try this:
>
> checksum = checksum + (unsigned long) buffer[i]*256 + buffer[i+1];
>
> or
>
> checksum += (unsigned long) buffer[i]<<8 + buffer[i+1];

I haven't used C18, but some compilers are really twisted!
For example, my DOS 8088 compiler has trouble with values beyond 16bit
since the compiler doesn't really know how to work with 32bit values,
so you end up having to mask bits just to get a result.
If you still have trouble, try something like this:

(unsigned long)(checksum += (((buffer[i]<<8) & 0xff00) | buffer[i+1]));

2005\12\31@172627 by Spehro Pefhany

picon face
At 02:48 PM 12/31/2005 -0500, you wrote:


>All optimizations in C18 have been disabled.
>
>I've also tried other "lines" like:
>checksum += buffer[i]*256 + buffer[i+1];
>checksum += buffer[i]<<8 + buffer[i+1];
>checksum += (unsigned long)(buffer[i]*256 + buffer[i+1]);

how about separating it into two lines?

checksum += buffer[i+1];
checksum += buffer[i];

Have you enabled integer promotions?

If the two lines works, try explicitly casting the intermediate results:

checksum+= ((unsigned long) buffer[i+1]) + (((unsigned long) buffer[i]) << 8);



{Quote hidden}

>

2005\12\31@182137 by James Humes

picon face
Try enabling "Integer Promotions" in the C18 preferences and see if that
helps.


'[PIC] C18 Fun! :('
2006\01\01@132716 by Peter
picon face

It could be a compiler bug. Try this:

#ifndef ulong
#  define ulong unsigned long
#endif

checksum = checksum + (ulong)(buffer[i]<<8) + (ulong)(buffer[i+1]);

Afair C does automatic promotion to int when in doubt. I am not sure if
this is a bug.

Did you try to increment checksum by itself (i.e. checksum += 16 ...) to
see if the '+=' operator is not buggy ?

Peter

2006\01\01@182629 by Herbert Graf

flavicon
face
On Sat, 2005-12-31 at 16:21 -0700, James Humes wrote:
> Try enabling "Integer Promotions" in the C18 preferences and see if that
> helps.

BINGO! Thanks to all for the help, seems "Integer Promotions" was what I
was missing!

Thanks again to all for the help. TTYL


-----------------------------
Herbert's PIC Stuff:
http://repatch.dyndns.org:8383/pic_stuff/

2006\01\02@010043 by William Chops Westfield

face picon face

On Jan 1, 2006, at 3:26 PM, Herbert Graf wrote:

>> Try enabling "Integer Promotions" in the C18
>> preferences and see if that helps.
>
> BINGO!

Good.  If this is an ip checksum routing, you were missing
the code that does the end-around carry folding in between
the loop at the complement...

Also, while this is a sort of standard unix ip checksum
algorithm, it's a REALLY BAD algorithm to use on a CPU
that doesn't natively support 32bit integers.  It dates
back to vaxen and 68000s, and is not good for PICs...
(alas, C is not so good for implementing the IP checksum
algorithm, because it doesn't give you access to the 'extra'
carry bit..)

BillW

2006\01\02@011045 by Herbert Graf

flavicon
face
On Sun, 2006-01-01 at 22:00 -0800, William Chops Westfield wrote:
> On Jan 1, 2006, at 3:26 PM, Herbert Graf wrote:
>
> >> Try enabling "Integer Promotions" in the C18
> >> preferences and see if that helps.
> >
> > BINGO!
>
> Good.  If this is an ip checksum routing, you were missing
> the code that does the end-around carry folding in between
> the loop at the complement...

The code I included was only relavent to the problem I had. It is indeed
an IP checksum routine, and after a little more debugging my packet
sniffers show the correct checksum on the wire!

Of course, then the next step was a UDP checksum routine. Spent some
time trying to figure out why it wasn't working right, and then I
discovered if you set it to 0x0000 machines recognize that as "no
checksum"! :)

> Also, while this is a sort of standard unix ip checksum
> algorithm, it's a REALLY BAD algorithm to use on a CPU
> that doesn't natively support 32bit integers.  It dates
> back to vaxen and 68000s, and is not good for PICs...
> (alas, C is not so good for implementing the IP checksum
> algorithm, because it doesn't give you access to the 'extra'
> carry bit..)

I was trying to think of a better way to do it, but in C alone I don't
really see anything immensely better. I suppose I could inline an
assembly routine, but I'd rather not spend the extra time for something
I don't need.

It's no matter, the app is more of a test bench then anything, and code
size, speed and efficiency don't matter in the least, it just has to
work.

TTYL

-----------------------------
Herbert's PIC Stuff:
http://repatch.dyndns.org:8383/pic_stuff/

More... (looser matching)
- Last day of these posts
- In 2006 , 2007 only
- Today
- New search...