我想有效地映射帶有寄存器的結構到內存。 其實我已經工作這樣的代碼:通過引用指向結構作爲模板參數
結構寄存器的外圍:
struct Periph {
volatile uint32_t REG1;
volatile uint32_t REG2;
};
在設備是位於內存中的兩個不同的地址這個周2次,所以確定這些地址:
static constexpr size_t PERIPH1_BASE = 0x40000000;
static constexpr size_t PERIPH2_BASE = 0x40001000;
然後我具有可以使用任何這些寄存器的駕駛員:
template<size_t Base> struct Driver {
inline Periph &r() {
return *reinterpret_cast<Periph *>(base);
}
void setFoo(uint32_t x) {
r().REG1 = x;
}
uint32_t getBar() {
return r().REG2;
}
};
要使用這個驅動程序很簡單,只需要一些外圍的設置地址模板:
Driver<PERIPH1_BASE> drv;
uint32_t x = drv.getBar();
drv.setFoo(x);
...
如果編譯器優化合並後的所有內聯函數,則此方法寄存器和沒有任何開銷工作非常有效。
但是這不是很安全,因爲我可以設置Driver
來自不同外設的任何地址。
我的想法是改善這一點是把參考結構作爲模板參數,但沒有成功。
首先,我定義爲寄存器引用:
static Periph &PERIPH1 = *reinterpret_cast<Periph *>(PERIPH1_BASE);
static Periph &PERIPH2 = *reinterpret_cast<Periph *>(PERIPH2_BASE);
這是工作,我可以直接訪問這些寄存器,如:
PERIPH2.REG1 = 123;
但我不知道怎麼打發這些引用模板參數,我的嘗試如下:
template<Periph &r> struct Driver {
void setFoo(uint32_t x) {
r.REG1 = x;
}
uint32_t getBar() {
return r.REG2;
}
};
Driver<PERIPH2> drv;
drv.setFoo(x);
由此我得到以下錯誤:
`error: the value of 'PERIPH2' is not usable in a constant expression`
如果我定義爲PERIPH2然後constexpr我得到另一個錯誤:
`error: reinterpret_cast from integer to pointer`
...所以如何把引用一個對象作爲模板參數? 或者一個想法或建議,使其更好。
此外,這裏還存在很多其他解決方案(比如將引用放到Driver構造函數中......),但是這會降低對寄存器的訪問速度。
感謝您的幫助。
你嘗試過'boost :: ref'或'std :: ref'嗎? –
沒有提升,沒有標準,它嵌入在缺乏內存的小型MCU中 – vlk
坦率地說,我認爲你的第一種方法很好 – Les