Question

I'm trying to write some code dealing with a register interface. The register interface is generic and used all over the chip I'm working with. There are several different types of instantiations which use a subset of the register interface.

I want to know, is there some way in C to create a struct with the master register interface, then have the various subsets be structs that only can access their used registers?

So, for example, let's call the different possible subsets A, B, and C.

The register interface may look something like this:

OFFSET  NAME    NEEDED BY
0x00 -- CFG     A B C
0x04 -- VERSION A B C
0x08 -- SIZE      B C
0x0C -- TYPE    A   C
0x10 -- USER    A

So, using the same format that ARM uses for their SCS register interface, I can create the following struct for master:

typedef volatile struct {
    uint32 cfg;
    uint32 version;
    uint32 size;
    uint32 type;
    uint32 user;
} master_t;

That part's relatively straightforward. But I'm having trouble thinking of a way to implement the a_t, b_t, and c_t types to have their contents still point to the right offsets, short of just creating separate structs in the exact same method as above (which would make it extremely painful to propagate changes/bugfixes; the actual use case has more like 50 total registers for master_t).

Essentially, my end goal is that if you pointed an a_t to the right memory address, then tried to write code that would (e.g.) try to access a_t.size, the compiler would throw an error. Is there any way this is possible in C?

Était-ce utile?

La solution

Perhaps like this:

typedef struct 
   {
   uint32 cfg;
   uint32 version;
   uint32 filler;
   uint32 type;
   uint32 user;
   } SUB_A_T;

typedef struct 
   {
   uint32 cfg;
   uint32 version;
   uint32 size;
   } SUB_B_T;

typedef struct 
   {
   uint32 cfg;
   uint32 version;
   uint32 size;
   uint32 type;
   } SUB_C_T;

typedef UNION 
   {
   SUB_A_T a;
   SUB_B_T b;
   SUB_C_T c;
   } MASTER_T;

To access:

   MASTER_T master;

   master.a.cfg = 1;
   master.a.version = 2;
   master.a.type = 3;
   master.a.user = 4;
// master.a.size = 11  This line would cause a compiler error. 

Or...

   master.b.cfg = 10;
   master.b.version = 20;
   master.b.size = 30;
// master.b.type = 22  This line would cause a compiler error. 
// master.b.user = 33  This line would cause a compiler error. 

Or...

   master.c.cfg = 100;
   master.c.version = 200;
   master.c.size = 300;
   master.c.type = 400;
// master.c.user = 44  This line would cause a compiler error. 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top