how to assign a union to an array element

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

how to assign a union to an array element

4,407 Views
irob
Contributor V
Hey everyone.  Does anyone know how I can assign a union to a particular element of array?  For instance, I have the following union defined:

Code:
typedef union{  Byte bits;  struct  {    Byte VIDEO0   :1;   // video mode bits    Byte VIDEO1   :1;    Byte ORIENT0  :1;   // orientation bits    Byte ORIENT1  :1;    Byte FREQ0    :1;   // frequency bits    Byte FREQ1    :1;    Byte LED      :1;   // LED enable bit    Byte          :1;   // unused  } bit;  struct  {    Byte mrgVIDEO   :2;    Byte mrgORIENT  :2;    Byte mrgFREQ    :2;    Byte            :1;    Byte            :1;  } mergedbits;} vconfig_union;extern volatile vconfig_union vconfig;#define VCONFIG         vconfig.bits#define VCONFIG_VIDEO0  vconfig.bit.VIDEO0#define VCONFIG_VIDEO1  vconfig.bit.VIDEO1#define VCONFIG_ORIENT0 vconfig.bit.ORIENT0#define VCONFIG_ORIENT1 vconfig.bit.ORIENT1#define VCONFIG_FREQ0   vconfig.bit.FREQ0#define VCONFIG_FREQ1   vconfig.bit.FREQ1#define VCONFIG_LED     vconfig.bit.LED#define VCONFIG_VIDEO   vconfig.mergedbits.mrgVIDEO#define VCONFIG_ORIENT  vconfig.mergedbits.mrgORIENT#define VCONFIG_FREQ    vconfig.mergedbits.mrgFREQ

 
And I also have an array of bytes defined:

Code:
Byte memory[8];

I want to assign the above union to the 8th element in the memory[] array.  I've tried the address operator in various ways but can't seem to make this work.

The reason is so that the last byte of that array can be easier to work with and test other control loops against.
Labels (1)
Tags (1)
0 Kudos
14 Replies

1,013 Views
CompilerGuru
NXP Employee
NXP Employee
Without having it tried out, but does
memory[7]= VCONFIG;

not work?

Also I'm not completely understand why
you want to do this assignment,
not sure how memory[7] could be simpler than using the VCONFIG,
but there are certainly good reasons for copying a byte :smileyhappy:.

Daniel


0 Kudos

1,013 Views
irob
Contributor V
Thanks for your help, Mr. Guru.  :manhappy:

I should have been more clear.  It's not simply byte copying that I wanted to do.  The memory array is stored to and retrieved from EEPROM.  It's easy to work with inside an array.  Each element of my array happens to be 8 bits in length, except for the last byte.  That one is broken into three pairs of bits, and one final bit (7 total bits).  The arrangement matches the breakdown listed in my union.

The union is obviously the easiest to work with in my code for its bit fields.  But how to then pack that back into the 8th element of the memory array when it's time to write or read from EEPROM?

You are correct, simply copying the full union to memory[7] during the EEPROM storage/retrieval will work just fine.  I was merely hoping for a clever way to maybe have the two entities mirror each other, avoiding the need to read and write each time.  Maybe I'm just making this too difficult.

Does that make any sense?
0 Kudos

1,013 Views
bigmac
Specialist III
Hello irob,
 
Not sure whether the following is what you require -
 
typedef struct {
   Byte data[7];
   vconfig_union vconfig;
} mem_array;
 
extern vconfig_union vconfig;
extern mem_array memory;
 
 
VCONFIG = memory.VCONFIG;
dataval = memory.data[x];
 
Regards,
Mac
 
0 Kudos

1,013 Views
irob
Contributor V
Bigmac, thanks for your suggestion.  Though I couldn't quite follow it completely, or make it compile without error in my source.  For instance, I wasn't sure what dataval was doing.

It occurred to me that maybe I could just add memory[7] inside my existing union, like this:

Code:
extern Byte memory[];  // Flash EEPROM memory
typedef union
{
  Byte bits;
  struct
  {
    Byte LEDS       :1;   // LED enable bit, 0
    Byte SSVR       :1;   // screensaver bit, 1
    Byte FREQ0      :1;   // frequency bits, 2-3
    Byte FREQ1      :1;
    Byte ORIENT0    :1;   // orientation bits, 4-5
    Byte ORIENT1    :1;
    Byte VIDEO0     :1;   // video mode bits, 6-7
    Byte VIDEO1     :1;
  } bit;
  struct
  {
    Byte            :1;
    Byte            :1;
    Byte mrgFREQ    :2;
    Byte mrgORIENT  :2;
    Byte mrgVIDEO   :2;
  } mergedbits;
 struct
  {
    Byte memory[7]  :8;
  } eeprombits;
} config_union;
extern volatile config_union config;

My hope was that the 8th byte of the memory[] array will also reside in the same memory as config.bits

This compiles, but alas, it treats the two "memory"s as unique names .  One is part of the memory[] array, the other is simply all 8 bits (config.bits).

0 Kudos

1,013 Views
allawtterb
Contributor IV
I think bigmac's suggestion should work, I made the following file:
Code:
typedef union{  Byte bits;  struct  {    Byte VIDEO0   :1;   // video mode bits    Byte VIDEO1   :1;    Byte ORIENT0  :1;   // orientation bits    Byte ORIENT1  :1;    Byte FREQ0    :1;   // frequency bits    Byte FREQ1    :1;    Byte LED      :1;   // LED enable bit    Byte          :1;   // unused  } bit;  struct  {    Byte mrgVIDEO   :2;    Byte mrgORIENT  :2;    Byte mrgFREQ    :2;    Byte            :1;    Byte            :1;  } mergedbits;} vconfig_union;#define VCONFIG         vconfig.bits#define VCONFIG_VIDEO0  vconfig.bit.VIDEO0#define VCONFIG_VIDEO1  vconfig.bit.VIDEO1#define VCONFIG_ORIENT0 vconfig.bit.ORIENT0#define VCONFIG_ORIENT1 vconfig.bit.ORIENT1#define VCONFIG_FREQ0   vconfig.bit.FREQ0#define VCONFIG_FREQ1   vconfig.bit.FREQ1#define VCONFIG_LED     vconfig.bit.LED#define VCONFIG_VIDEO   vconfig.mergedbits.mrgVIDEO#define VCONFIG_ORIENT  vconfig.mergedbits.mrgORIENT#define VCONFIG_FREQ    vconfig.mergedbits.mrgFREQtypedef struct {   Byte data[7];   vconfig_union vconfig;   } mem_array;mem_array memory;unsigned char test;void main(void) {  /* put your own code here */  memory.VCONFIG_VIDEO0 = 1;  test = memory.data[7];  for(;;) {} /* wait forever */  /* please make sure that you never leave this function */}

 
For which the disassembly is:
Code:
   52:    memory.VCONFIG = 0x12;  0000 c612         [1]     LDAB  #18  0002 7b0000       [3]     STAB  memory:7   53:    test = memory.data[7];  0005 b60000       [3]     LDAA  memory:7  0008 7a0000       [3]     STAA  test

Becareful with the array as it doesn't seem to be checking the bounds.


 
0 Kudos

1,013 Views
irob
Contributor V
Thanks, allawtterb, but yours will not compile for me.  I'm getting C1019, incompatible type, found 'mem_array', expected "unsigned char[8]").

I presume it's because memory for me is already defined in main.c as unsigned character array, 8 bytes wide.  Hmm.
0 Kudos

1,013 Views
bigmac
Specialist III
Hello iRob,
 
I wonder if your compile problem has anything to do with the visibility (or lack thereof) of the typedef Byte within one of the files.  I am not sure in which header file this is defined.  I would usually make use of the alternate typedef byte as I know this is defined within the MCU header file, and is accessible through derivative.h.
 
Regards,
Mac
 
0 Kudos

1,013 Views
irob
Contributor V
Hmm, good thought.  "Byte" is defined in stdtypes.h (<install dir>\lib\hc08c\include\).

On a whim, I change all instances of Byte and Word over to byte and word.  Alas, I get the same error at the "mem_array memory;" line in main.h

To be clear, all the structure definitions are in my main.h file.  In my main.c, I have memory first initialized:

Code:
byte memory[8];      // flash config bytes






Message Edited by irob on 2008-04-25 10:03 AM
0 Kudos

1,013 Views
bigmac
Specialist III
Hello iRob,
 
Now I think that I understand.  If you are attempting to use the code posted by Brett, there is already the global variable definition -
mem_array memory;
 
So you cannot also have the global definition -
byte memory[8];
 
This would appear to give the conflict.  You can only have a single definition for memory.  If you need to access one of the data byte locations within the array, it would need to occur via the structure, as with -
test = memory.data[0];
 
Regards,
Mac
 
0 Kudos

1,013 Views
irob
Contributor V
Ahh, I see now.  I've updated all my instances of memory[x] to memory.data[x].  That does indeed work.

However, it seems that all my instances of VCONFIG will  have to change to something like memory.vconfig.  In the debugger, I'm seeing two entries for vconfig, both with separate segments in RAM.  The second is an element of the memory structure.

Is there a way I should be restructuring my #define's so that my labels -- like VCONFIG -- call out the memory. vconfig structure elements?  The #define obviously makes it more manageable.
0 Kudos

1,013 Views
allawtterb
Contributor IV


irob wrote:
However, it seems that all my instances of VCONFIG will  have to change to something like memory.vconfig.  In the debugger, I'm seeing two entries for vconfig, both with separate segments in RAM.  The second is an element of the memory structure.


Make sure that you don't have another vconfig defined somewhere else, in your original post you had:
Code:
extern volatile vconfig_union vconfig;

 
This declaration and any definition of vconfig outside of the struct should not exist.
 
 

irob wrote:
Is there a way I should be restructuring my #define's so that my labels -- like VCONFIG -- call out the memory. vconfig structure elements?  The #define obviously makes it more manageable.


If you want to access memory.vconfig with one define, change the defines to:
Code:
#define VCONFIG         memory.vconfig.bits#define VCONFIG_VIDEO0  memory.vconfig.bit.VIDEO0#define VCONFIG_VIDEO1  memory.vconfig.bit.VIDEO1#define VCONFIG_ORIENT0 memory.vconfig.bit.ORIENT0#define VCONFIG_ORIENT1 memory.vconfig.bit.ORIENT1#define VCONFIG_FREQ0   memory.vconfig.bit.FREQ0#define VCONFIG_FREQ1   memory.vconfig.bit.FREQ1#define VCONFIG_LED     memory.vconfig.bit.LED#define VCONFIG_VIDEO   memory.vconfig.mergedbits.mrgVIDEO#define VCONFIG_ORIENT  memory.vconfig.mergedbits.mrgORIENT#define VCONFIG_FREQ    memory.vconfig.mergedbits.mrgFREQ

 
That being said, I don't like the implementation very much.  The overlaying of memory.data[7] and memory.vconfig is only because the compiler is letting you access an array out of it's bounds. 

0 Kudos

1,013 Views
bigmac
Specialist III
Hello,


allawtterb wrote:

That being said, I don't like the implementation very much.  The overlaying of memory.data[7] and memory.vconfig is only because the compiler is letting you access an array out of it's bounds. 

When I posted my original suggestion in message 4, I had intended that the vconfig element of the memory structure would be accessed as memory.vconfig.bits and not as memory.data[7].  So there would be no array bounds issue.  My understanding was that this element was to be handled differently than the other elements of the structure because of its union with a bit field.
 
For demonstration purposes, I had also assumed the creation of a separate variable of type vconfig_union outside of the memory structure.
extern vconfig_union vconfig;
 
It would then be possible to have the following statement to read the contents of the whole structure element -
vconfig.bits = memory.vconfig.bits;
 
Then applying a macro that had previously been defined, the result was -
VCONFIG = memory.VCONFIG;
 
But it seems this may have confused the issue.  This is what I thought the OP required, but I may have been wrong.
 
Regards,
Mac
 
0 Kudos

1,013 Views
allawtterb
Contributor IV
You need to remove this definition for the above code to work properly, you can't define two variables with the same name. 
0 Kudos

1,013 Views
irob
Contributor V
But without the first declaration (memory[8]), I get C1827 errors.  memory is an array of 8 elements.

I'm starting to think this isn't worth the effort.  :smileyhappy:
0 Kudos