| Details | Message |
|---|
Read-Only Author Soren Hansen Posted 10-Oct-2004 11:24 GMT Toolset C51 |  Struct in union Soren Hansen Hi I have some problems with struct inside a union This is my code.
union{
unsigned char id_byte[2];
struct {
unsigned char DLC:4;
unsigned char RTR:1;
unsigned int identifier:11;
}del_element;
}can_descriptor;
when I write an_descriptor.del_element.identifier=0x0A;
nothing comes in id_byte array why? The values I put in DLC and RTR are placed correct.
If i change the code to
union{
unsigned char id_byte[2];
struct {
unsigned int identifier:11;
unsigned char DLC:4;
unsigned char RTR:1;
}del_element;
}can_descriptor;
And writes 0x0A to identifier: id_byte[0]=0 id_byte[1]=0x0A
but i shoud be id_byte[0]=0x80 id_byte[1]=0x01
why? This program is part of an CAN program for SJA1000, this funktion i made make it easy to write the CAN iddentifiers DLC and RTR bit in the controller.....if it worked.
Best Regrads Soren |
|
Read-Only Author Jon Ward Posted 10-Oct-2004 14:52 GMT Toolset C51 |  RE: Struct in union Jon Ward The bit-fields in your struct are different types:
unsigned char DLC:4;
unsigned char RTR:1;
unsigned int identifier:11;
Try making them all unsigned int rather than mixing types.
Jon |
|
Read-Only Author Soren Hansen Posted 10-Oct-2004 18:38 GMT Toolset C51 |  RE: Struct in union Soren Hansen tryede that. now comes the identifier,DLC and RTR into the array. but wrong:
identifier=0x0A DLC=0x04 RTR=1
gives: array[0]=0xA0 array[1]=0x0A
corect is array[0]=0x64 array[1]=0x01
the identifier is the 11. higist bit, RTR bit and last 4 DLC bits. is something wrong with my order of my struct?
Soren |
|
Read-Only Author Drew Davis Posted 11-Oct-2004 03:26 GMT Toolset C51 |  RE: Struct in union Drew Davis Keil C has a somewhat non-intuitive order for bitfields.
http://www.keil.com/support/docs/1948.htm
Per the C standard, the "correct" storage pattern for bitfields is up the implementation. A program cannot rely on the order of bitfields within an int, nor can it depend on the signed-ness of a bitfield. For that matter, per spec all bitfields must occupy an "int" (whatever that may be), though every compiler I've ever used lets you specify other byte widths for them.
In fact, I avoid using this C feature at all because the results are so different for every compiler and platform. In addition, many compilers generate poor code for bitfields. It's more portable and often more efficient just to use the & and | operators directly. If you're sending messages to another processor, you can use the same declarations without worrying about different implementation orders. |
|
Read-Only Author Soren Hansen Posted 11-Oct-2004 08:14 GMT Toolset C51 |  RE: Struct in union Soren Hansen This means that I never can do what i had in intention?
Soren |
|
Read-Only Author Hans-Bernhard Broeker Posted 11-Oct-2004 12:39 GMT Toolset C51 |  RE: Struct in union Hans-Bernhard Broeker This means that I never can do what i had in intention?
In a nutshell: yes. The language definition for C left so many details of bitfield behaviour for the implementor to specify that there's essentially nothing usable left for application like yours, trying to recreate some hardware bit addressing schemes in C structs.
In short, C data structures will only ever match any pre-determined physical address layout by coincidence, but not by design.
Use #define'd shifting and masking operations instead. |
|
Read-Only Author Andy Neil Posted 11-Oct-2004 13:53 GMT Toolset C51 |  RE: Struct in union Andy Neil Actually, you can do it - but, for the reasons already discussed, it's best avoided.
I don't think there's any reason to believe that bitfields will give you (significantly) better code than shifts and masks and some bitfield implementations are notoriously inefficient - so shifts and masks can actually be better!
Your problem is that you have not fully understood Keil's bitfield implementation. If you really do want to use bitfields, you will have to read-up on Keil's implementation, and adapt your union to match.
There are articles in the Knowledgebase that will help you with this - use the site 'Search' facility.
You can always use the memory viewing facilities in the simulator to help you see what's going on...
But, again, why bother? Just use shifts & masks - you know where you are with shifts & masks! And they're portable! |
|
Read-Only Author Soren Hansen Posted 11-Oct-2004 13:57 GMT Toolset C51 |  RE: Struct in union Soren Hansen I tryed not to use shift and mask too much.
I have now implantet the union struct, with some modifikations.....and i works.
Shifting and masking, is not good if you need to convert 2 ways...
Soren |
|
Read-Only Author Andy Neil Posted 11-Oct-2004 14:25 GMT Toolset C51 |  RE: Struct in union Andy Neil "I tryed not to use shift and mask too much."
Why not? It's probably how the compiler actually implements the bitfields!
"I have now implantet the union struct, with some modifikations.....and i works."
Be sure to test it thoroughly - you don't want any nasty surprises with the sign bit, for example...
"Shifting and masking, is not good if you need to convert 2 ways..."
Why not? |
|
Read-Only Author Soren Hansen Posted 11-Oct-2004 14:30 GMT Toolset C51 |  RE: Struct in union Soren Hansen I uses the union struct to place bit into my SJA1000 controller.
I uses the funktion to make TX id byts. and to decode RX bytes.
if I shifts, I need more code, becourse I need to shift different if i have a RTR bit set. I don't have that problem in union struct.
Soren |
|
Read-Only Author Hans-Bernhard Broeker Posted 11-Oct-2004 14:44 GMT Toolset C51 |  RE: Struct in union Hans-Bernhard Broeker if I shifts, I need more code, becourse I need to shift different if i have a RTR bit set.
I rather strongly suspect the opposite to be true. If the shift is, indeed, different depending on the status of some bits, that's impossible to model using bitfields alone, because the lengths, and thus by implication the positions, of bitfields inside a struct are fixed at compile time. It's much more transparent to have the argument of a shift operator be a variable or expression than having to do something like
if(rtr)
my_union.rtr_set.somebit = 1;
else
my_union.rtr_clr.somebit = 1;
|
|
Read-Only Author Andy Neil Posted 11-Oct-2004 14:47 GMT Toolset C51 |  RE: Struct in union Andy Neil "if I shifts, I need more code ... I don't have that problem in union struct."
It may look like more source code, but have you checked the generated object code?
Does it make any difference to the amount of code that the processor actually has to run? |
|
Read-Only Author Soren Hansen Posted 11-Oct-2004 14:50 GMT Toolset C51 |  RE: Struct in union Soren Hansen year ok.
yes as small as passebel, no time to waste.
You say that i shoud use mask and shift? dose't it give more code?
Soren |
|
Read-Only Author Andy Neil Posted 11-Oct-2004 17:13 GMT Toolset C51 |  RE: Struct in union Andy Neil "You say that i shoud use mask and shift? dose't it give more code?"
Try re-reading the previous posts!
Here's a reminder of what's been said so far:
"many compilers generate poor code for bitfields. It's more portable and often more efficient just to use the & and | operators directly."
"I don't think there's any reason to believe that bitfields will give you (significantly) better code than shifts and masks and some bitfield implementations are notoriously inefficient - so shifts and masks can actually be better!"
"[shift & mask] is probably how the compiler actually implements the bitfields!"
That should answer your question!
And again, shifts & masks are portable; bitfields are not. |
|
Read-Only Author Soren Hansen Posted 11-Oct-2004 17:15 GMT Toolset C51 |  RE: Struct in union Soren Hansen thanks i try that.
soren |
|