overflow in supposed to be unsigned long

Hi, I have to transmit an unsigned long as four bytes, so I split them up and join them again, but with the folowing example code, I get overflow at long_counter>32767 - can any of you give me a clue how to do it right?

unsigned

char i; unsigned long long_counter; unsigned char char_counter[4];

void main(void) { unsigned char len; unsigned char lcd_buf[16];

OSCCONbits.SCS = 0x0; // System Clock Select bits = External oscillator OSCCONbits.IRCF = 0x7; // Internal Oscillator Frequency Select bits 8 MHz (INTOSC drives clock directly)

lcd_init(); while (1) { for (long_counter = 0; long_counter < 0xffff0000; long_counter += 50) { // split long_counter to four unsigned char's for (i = 0; i < 4; i++) { char_counter[i] = (long_counter & (0xff

(i * 8);
}

// convert them to unsigned int again long_counter = char_counter[0] | (char_counter[1]

Reply to
stoffer
Loading thread data ...

Long constants, such as 0xffff0000 need an 'L' or 'l' at the end: try

0xffff0000L.

Your calculations, such as 'char_counter[0] | (char_counter[1]

Reply to
Arlet Ottens

Compilers will figure that one out themselves - you only need the "L" if you have a constant that would fit within a smaller size but should be treated as long. But many people like to use the L anyway in such cases

- it's better to be explicit than implicit.

Reply to
David Brown

Reply to
Arlet Ottens

I don't know how good or bad a compiler he has, but some compilers might see that as a shift-left-32-by-32 library call instead of a byte move operation.

Mind you, considering the target is a brain-dead PIC, the code at the moment is probably at least 100 times slower than using a union. Even just the simple act of making the variables local to the function would probably double the speed. And the union solution is shorter (both source code and target code) and clearer.

The test code also has a bug, in that long_counter is used for a loop variable and is changed by the byte-swap routine.

static uint32_t byteSwap32(uint32_t x) { union { uint32_t l; uint8_t b[4]; } u1, u2;

u1.l = x; u2.b[0] = u1.b[3]; u2.b[1] = u1.b[2]; u2.b[2] = u1.b[1]; u2.b[3] = u1.b[0]; return u2.l; }

Of course, the implementation above assumes you have a decent compiler that will inline this code and eliminate unnecessary registers. Otherwise it's only /much/ better than the original code.

Reply to
David Brown

For a

Reply to
nospam

Nope, that doesn't work

For a

Reply to
nospam

There is no byte swap routine. The code doesn't change the order of the bytes. The bug you refer to is only a bug because there's another bug...

Reply to
nospam

Maybe, but then they may see ((uint32_t) char_counter[1]

Reply to
Arlet Ottens

Ah, you're right. I assumed the rules for

Reply to
Arlet Ottens

Depending on the circumstances of your transmission, you may also consider doing it like this:

transmit( &long_counter, sizeof(long_counter) );

The order of the bytes will be implementation independent, but if you control both ends of the transmission, and you know the endianness of both sides is the same, it should work.

Or, you could have a situation where you need to send data from a big-endian embedded target to a little-endian PC, and just define the communication to be big-endian, to make life easier on the embedded target.

Reply to
Arlet Ottens

Good point! I wonder if he is trying to swap the bytes and got the code wrong, or if the code is actually trying to do nothing and is still wrong...

Reply to
David Brown

As has been pointed out by someone else, the int promotion rules are not exactly like that for the asymmetrical > operations.

Sometimes compiler's optimisations are dependent on the code pattern used, so that operations that are logically identical can result in different code.

Reply to
David Brown

This seems to be an ideal situation for using a union---particulary of the processor doesn't have a 32-bit barrel shifter:

union bytelong { unsigned long lval; unsigned char bvals[4]; } mylong;

You can store or fetch from the bytes with a simple character pointer or normal array indexing. Getting or storing the long word is a single assignment.

You can also reverse the endianness of the long value by indexing in the opposite direction. It was this need to reverse the endianness that brought me to this solution in the first place.

Mark Borgerson

Reply to
Mark Borgerson

You mean "... and pray that the compiler does what it is supposed to do". I'd get all explicit, both to spare myself from almost-compliant compilers, and to spare future programmers from trying to unweave the meaning from the code.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

I am using sdcc and gputils, but appearantly it does not support 'L' after constants, I got bus error when I try actually...

--
- stoffer
Reply to
stoffer

((uint32_t) char_counter[0]) | (((uint32_t) char_counter[1])

Reply to
Kristoffer

(sdcc)

Then your compiler (or the header that defines uint32_t) is crap, and you need to exercise extreme cleverness to get around it's crappiness.

_Either_ do something like:

long int dest_counter;

dest_counter = char_counter[3]; dest_counter

Reply to
Tim Wescott

(sdcc)

Please note that Google Groups, in their continuing efforts to abuse USENET out of existence, has introduced a bug in their new interface. When you reply to one of these threads, Google helpfully hacks the headers up so that many popular newsreaders think that you're starting a separate thread.

The 'old' Google interface, while exceedingly clunky, does not do this.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

If it didn't support 'l', I would expect a compile time error, not a bus error. I would expect something else is causing the bus error.

Reply to
Arlet Ottens

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.