![]() |
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;}; |
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) |
Re: Shadow Register Problem
Quote:
Quote:
Code:
#define writeShadow(S,R) ECanaShadow.(S).bit.(R) |
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:
|
Re: Shadow Register Problem
Quote:
Quote:
|
Re: Shadow Register Problem
Quote:
Code:
#define writeShadow(STRCT, BITN) ECanaShadow.STRCT.bit.BITNCode:
ECanaShadow.STRCT.bit.BITNCode:
ECanaShadow.STRCT.bit.BITN = |
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... 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 { |
Re: Shadow Register Problem
Quote:
Quote:
Quote:
|
| All times are GMT -5. The time now is 04:45. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi