1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
| #include <cstdint>
#include <limits>
#include <iostream>
constexpr uint32_t generate_unshifted_mask(int width)
{
return width ? 1 | generate_unshifted_mask(width - 1) << 1: 0;
}
constexpr uint32_t generate_mask(int width, int offset)
{
//static_assert(0 < width + offset && width + offset <= 32, "");
return generate_unshifted_mask(width) << offset;
}
struct ro_t
{
static uint32_t read(
volatile uint32_t * device,
int offset,
int mask
)
{ return (*device & mask) >> offset; }
};
struct wo_t
{
static void write(
volatile uint32_t * device,
uint32_t offset,
int mask,
int value
)
{ *device = ((value << offset) & mask); }
};
struct rw_t : ro_t
{
static void write(
volatile uint32_t * device,
uint32_t offset,
int mask,
int value
)
{ *device = (*device & ~mask) | ((value << offset) & mask); }
};
// mut_t 地址
// addr 寄存器地址
// offset 偏移量
// width 宽度
template<typename mut_t, uint32_t addr, int offset, int width>
struct reg_t
{
static_assert(width > 0, "nonpositive width");
static_assert(offset >= 0, "negative offset");
static_assert(width + offset <= std::numeric_limits<uint32_t>::digits, "width overflow");
static uint32_t read()
{
constexpr uint32_t mask = generate_mask(offset, width);
return mut_t::read(reinterpret_cast<volatile uint32_t*>(addr), offset, mask);
}
static void write(uint32_t val)
{
constexpr uint32_t mask = generate_mask(offset, width);
mut_t::write(reinterpret_cast<volatile uint32_t*>(addr), offset, mask, val);
}
};
using enabled = reg_t<ro_t, 0xffff0000, 0, 1>;
int main(int argc, char* argv[]) {
if (enabled::read()) {
std::cout << "not enabled" << std::endl;
}
// enabled::write(1); error
return 0;
}
|