2014-05-14 146 views
1

我正在嘗試編寫一些處理寄存器接口的代碼。寄存器接口是通用的,並在我正在使用的所有芯片上使用。有幾種不同類型的實例使用寄存器接口的子集。C如何基於結構的結構

我想知道,是否有一些方法在C創建一個結構主寄存器接口,然後有不同的子集結構只能訪問其使用的寄存器?

因此,舉例來說,我們不妨將不同的可能子集A,B和C

寄存器接口可以是這個樣子:

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 

因此,使用相同的格式that ARM uses for their SCS register interface,我可以爲master創建以下結構:

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

該部分相對簡單。但是我很難想出一種實現a_t,b_t和c_t類型的方法,讓它們的內容仍然指向正確的偏移量,而不是用與上面完全相同的方法創建單獨的結構體(這將使得它非常傳播改變/錯誤修正的痛苦;實際的用例更像master_t的總共50個寄存器)。基本上,我的最終目標是,如果你指向正確的內存地址的a_t,然後試圖編寫代碼(例如)試圖訪問a_t.size,編譯器會拋出一個錯誤。在C中有這種可能嗎?

+0

有沒有辦法ŧ o說「結構'a_t'就像結構'master_t',除非它沒有成員'size'」 – Barmar

+0

@Barmar如果我要手動創建struct a_t,而不是「uint32 size」,我會把像「uint32填充」,這將有相同的最終結果。如果沒有辦法做到這一點,我可能最終不得不寫一個圖書館和一些獲得適當保護的getter/setter。 –

+0

你可以用宏來做。 '#define a_t_size(s)...' – Barmar

回答

1

也許是這樣的:

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; 

要訪問:

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. 

或者......

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. 

或者......

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. 
+0

我最後用類似的東西去了。基本上,在完整版本中,A和B具有非常相似的接口,C具有相同的寄存器,但有許多附加寄存器。我建立了一個工會,所以你可以通過master.whatever訪問A/B/C-common寄存器,而C特定的東西就是c.whatever。不是100%理想,但對我來說足夠好。 –