We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I have a somewhat complex structure in my C code, and driver functions to read or write data with it.
The simpler parts of the struct (such as ioflags2 below) and their driver functions work just fine. However, the more complex parts of the struct (such as ioflags3) do not.
The symptom is that only the drivers for the first part of the more complex parts of the structure work right, and the rest don't appear to change the "word" part of the structure.
However, if I step through the code with the simulator, all of the individual parts of the more complex parts of the struct work just fine with the driver functions, but the "word" part doesn't change (well, except for the 1st part of the more complex parts, i.e., module1 works, but module2 - module5 don't).
Finally, I cut/paste the whole struct and drivers to a Visual C++ program and stepped through the code with their debugger. *ALL* of the driver functions had the expected effect on *ALL* of the parts of the whole struct.
Can anyone tell me what, if anything, is wrong with this code, and how to make it work with KEIL's ARM tools?
union{ u16 word; struct{ unsigned sensor1:1; unsigned sensor2:1; unsigned sensor3:1; unsigned sensor4:1; unsigned sensor5:1; unsigned sensor6:1; unsigned sensor7:1; unsigned sensor8:1; unsigned sensor9:1; unsigned sensor10:1; unsigned reserved_bit_10:1; unsigned reserved_bit_11:1; unsigned reserved_bit_12:1; unsigned reserved_bit_13:1; unsigned reserved_bit_14:1; unsigned reserved_bit_15:1; }bit; }ioflags2; union{ u16 word; struct{ struct{ struct{ unsigned run:1; unsigned direction:1; }stepper_motor; }module1; union{ struct{ unsigned extend:1; unsigned retract:1; }ioctl; struct{ unsigned run:1; unsigned direction:1; }dc_motor; }module2; union{ struct{ unsigned open:1; unsigned close:1; }ioctl; struct{ unsigned run:1; unsigned direction:1; }dc_motor; }module3; union{ struct{ unsigned open:1; unsigned close:1; }ioctl; struct{ unsigned run:1; unsigned direction:1; }dc_motor; }module4; union{ struct{ unsigned reserved_bit_0:1; unsigned fan:1; }ioctl; struct{ unsigned direction:1; unsigned run:1; }dc_motor; }module5; unsigned reserved_bit_10:1; unsigned reserved_bit_11:1; unsigned reserved_bit_12:1; unsigned reserved_bit_13:1; unsigned reserved_bit_14:1; unsigned reserved_bit_15:1; }bit; }ioflags3;
And here's how my drivers manipulate the structure.
int set_module2_retract(int state){ int previous_state; ASSERT(module2_type() == TYPE_IOCTL); if(module2_type() != TYPE_IOCTL){ return(-1); } if(state){ set_module1_extend(0); // protect the hardware! } previous_state = variable.ioflags3.bit.module2.ioctl.retract; variable.ioflags3.bit.module2.ioctl.retract = state ? 1u : 0u; return(previous_state); }
All very interesting and illuminating responses. I did abandon the bit field concept for my struct, and no longer have the problem.
I've always used the manual masking of bit fields in the past, but was looking for a cleaner (i.e., more readable) method; combined with a way to have a single variable that could be written to or read from non-volatile memory as a single block of bytes; that also enforced that *all* of the configuration/setup/operational settings would have to be in that single block of bytes. Accessing them via the "dot" operator from the single struct seemed like a logical way to do all of that.
Thanks for all your help.
Dave.