|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
|
|
Thread Tools | Rate Thread | Display Modes |
|
|
|
#1
|
||||
|
||||
|
Shadow Register Problem
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;};
}
Last edited by Adam Y. : 26-02-2007 at 11:13. |
|
#2
|
|||||
|
|||||
|
Re: Shadow Register Problem
Do you consider macros more or less readable than what you have?
A macro for that statement off the top of my heads is Code:
#define writeShadow(S,R) while((S).CANMC.bit.CCR==0){(S).CANMC.all=(R).CANMC.all;};
Code:
writeShadow(ECanaShadow,ECanaRegs) |
|
#3
|
||||
|
||||
|
Re: Shadow Register Problem
Quote:
Quote:
Code:
#define writeShadow(S,R) ECanaShadow.(S).bit.(R) Last edited by Adam Y. : 26-02-2007 at 13:09. |
|
#4
|
|||||
|
|||||
|
Re: Shadow Register Problem
Quote:
Code:
#define writeShadow(STRCT, BITN) ECanaShadow.STRCT.bit.BITN Code:
ECanaShadow.STRCT.bit.BITN Code:
ECanaShadow.STRCT.bit.BITN = ECanaRegs.STRCT.bit.BITN |
|
#5
|
||||
|
||||
|
Re: Shadow Register Problem
Quote:
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
|
|
#6
|
||||
|
||||
|
Re: Shadow Register Problem
Quote:
Quote:
|
|
#7
|
||||
|
||||
|
Re: Shadow Register Problem
Quote:
The example code would work fine for the bit positions denoted, as there is no need to prepend zero's to a number. Certainly if you wanted to denote a bit position greater than 16, then it would be proper to add something like a 'UL' suffix to the constant. Since you haven't mentioned which CPU this is for, and curiosity got the better of me, I used Google and turned up some example code for the TMS320 series. TI's example code is inconsistent, some of it shows direct manipulation, others show using this shadow register workaround. Finally, one example came clean with the following embedded comment: Code:
/* Create a shadow register structure for the CAN control registers. This is needed, since, only 32–bit access is allowed to these registers. 16–bit access to these registers could potentially corrupt the register contents. This is especially true while writing to a bit (or group of bits) among bits 16 – 31 */ struct ECAN_REGS ECanaShadow; ... ok, so this is a workaround for the C compiler which may generate a 16 bit read/modify/write operation. It is an understandable optimization for the compiler, but a bit surprising that TI doesn't offer some native functionality to denote memory locations that are 32bit wide access only. Since optimization appears to be the problem, then my examples of |= and &= would similarly be optimized and create the same problem. In any event, this seems to work ok: Code:
struct foo {
unsigned bit1:1;
unsigned bit2:1;
unsigned bit3:1;
unsigned many:3;
};
struct bar {
struct foo cat;
struct foo dog;
};
struct bar x;
struct bar y;
#define eCANWrite(a,b,c) y=x; y.a.b=c; x=y;
void test(void) {
eCANWrite(cat,many,1);
// produces the same code as
y=x;
y.cat.many = 1;
x=y;
}
|
|
#8
|
||||
|
||||
|
Re: Shadow Register Problem
Quote:
Quote:
Quote:
|
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Shadow of the Colossus - Absolutly Amazing | Zero-Bee | Chit-Chat | 0 | 07-01-2006 13:35 |
| pic: The Shadow Claw | bradleym1559 | Robot Showcase | 8 | 27-02-2005 15:10 |
| pic: 1241 Robot - Shadow | CD47-Bot | Robot Showcase | 2 | 11-04-2004 13:16 |
| Shadow? | Jack | Chit-Chat | 9 | 03-02-2003 20:28 |
| How to register | Jeremy Roberts | General Forum | 0 | 02-10-2002 01:09 |