View Single Post
  #5   Spotlight this post!  
Unread 26-02-2007, 14:07
Dave K.'s Avatar
Dave K. Dave K. is offline
Engineer/Mentor
FRC #0930
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2005
Location: WI
Posts: 91
Dave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to beholdDave K. is a splendid one to behold
Re: Shadow Register Problem

Quote:
Originally Posted by Adam Y. View Post
I have ran into a problem that someone here might be able to answer. The problem is that I am programing a microcontroller using bit fields created in a structure. The problem comes as I am trying to modify a series of registers that only have 32-bit access. I can't read or write to these registers using a conventional bit field because otherwise the registers would be corrupted. The solution I have read makes perfect sense. You create another structure and then load up the entire 32-bit of the same register and then modify and read the bit fields from that shadow register. Unfortunately, this makes the code a lot more convoluted in in that you constantly have to be making sure that both structures are being updated as seen in the following example I have below which is only checking the a flag. Any solutions on how to make this code more readable or is this the best way to program those registers?
Edit: I know I can just write to those registers in one go but that is a step backwards in readability from where I am right now.
Code:
 while(ECanaShadow.CANMC.bit.CCR==0){ECanaShadow.CANMC.all=ECanaRegs.CANMC.all;};
}
How a particular compiler packs bits is something which can vary from compiler to compiler. While many may allocate the bits in order, others may not, or may choose to order them differently.

I realize that some CPU vendor's header files promote this approach, and for CPU specific hardware registers, portablity isn't a big concern. Where I've seen problems like this create a mess is many years later, when you want to impliment a new compiler, from a new vendor.

That said, I'm unclear as to why you are unable to operate directly on the registers with your structures. If the compiler is generating code that utilizes bit set/clear instructions, those should be read/modify/write type of operations and should perform no differently than you manually read/modify/writing the registers as you seem to propose.

The only time I've had to 'shadow' anything is when dealing with 'write only' types of registers, and that just amounts to keeping a local variable which contains the correct data, and then when modified, gets pushed out to the hardware perhipheral... so perhaps this is the scenario you are trying to address.

As long as you are pursuing non-portable solutions, you might also look at defining a union between an unsigned long (I'm assuming your unidentified CPU considers this a 32 bit variable) and your structure. With the union, you could read the hardware register into a u32, operate on the bits within the struct, and then store the u32 back into the register.


My personal preference for working with hardware registers is to create #defines and just use bit and/or operations to modify the registers as desired. Its both portable and readable.

Code:
#define CANMC_CCR   0x1000
#define CANMC_XYZ   0x2000
// etc.

u32 ltmp;

    ltmp = hardware_register
    ltmp |= CANMC_XYZ;        // turn on XYZ
    ltmp &= ~CANMC_CCR;     // turn off CCR
    hardware_register = ltmp;

    // and you can combine bits like this, which will generate only one OR instruction rather than multiples for each bit set (or clear) action.

    ltmp |= CANMC_XYZ + CANMC_CCR
__________________
--Dave