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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# Changelog
## [Unreleased]
**BREAKING** The `reset_reg!` macro is removed. It may be added later.
**BREAKING** The API uses raw pointers to access registers, avoiding
references. To support this goal, the package has new read, write, and modify
macros. The macros expect a different definition for register blocks and
registers.
Here's a small example demonstrating the new definition of register blocks,
registers, and fields. It also demonstrates the macro syntax.
```rust
//
// Peripheral definition.
//
#![allow(non_snake_case)]
pub mod pit {
#[repr(C)]
pub struct RegisterBlock {
pub MCR: u32,
pub LTMR: [u32; 2],
_reserved_0: [u8; 16],
pub CHANNEL: [CHANNEL::RegisterBlock; 4],
}
ral_registers::register!(pub MCR<u32> RW [
FRZ start(0) width(1) RW {}
MDIS start(1) width(1) RW {
DISABLE = 1,
ENABLE = 0,
}
]);
ral_registers::register!(pub LTMR<u32> RO []);
pub mod CHANNEL {
#[repr(C)]
pub struct RegisterBlock {
pub LDVAL: u32,
pub CVAL: u32,
pub TCTRL: u32,
pub TFLG: u32,
}
ral_registers::register!(pub LDVAL RW []);
ral_registers::register!(pub CVAL RO []);
ral_registers::register!(pub TCTRL<u32> RW [
TEN start(0) width(1) RW {
DISABLE = 0,
ENABLE = 1,
}
TIE start(1) width(1) RW {}
CHN start(2) width(1) RW {}
]);
ral_registers::register!(pub TFLG<u32> RW [
TIF start(0) width(1) RW {}
]);
}
}
//
// Peripheral usage.
//
use ral_registers as ral;
// pit1() expanded from ral::instances! shown later
let pit1 = unsafe { instances::pit1() };
ral::modify_reg!(pit, pit1, MCR, MDIS: ENABLE);
ral::modify_reg!(pit, pit1, CHANNEL[2].TCTRL, TEN: ENABLE);
loop {
while ral::read_reg!(pit, pit1, CHANNEL[2].TFLG, TIF == 0) {}
ral::write_reg!(pit, pit1, CHANNEL[2].TFLG, TIF: 1);
}
//
// NEW: instance definitions.
//
mod instances {
ral::instances! {
unsafe {
pit1<pit::RegisterBlock> = 0x4008_4000;
pit2<pit::RegisterBlock> = 0x400C_4000;
// Expansion:
// pub const unsafe fn pit1() -> ral::Instance<pit::RegisterBlock> { /* ... */ }
// pub const unsafe fn pit2() -> ral::Instance<pit::RegisterBlock> { /* ... */ }
}
}
}
```
A `RegisterBlock` only describes a layout using unsigned or signed primitives.
There are no more `RWRegister`, `RORegister`, or `WORegister` types to convey
access. Instead, each register module describes its access. The approach allows
a single register block layout to be shared for different use cases, cases that
may vary the access for a given register.
The `register!` macros provides a convenient way to define fields and field
enums. The macro is optional; the expanded code is specified and stable. Codegen
tools can directly generate compatible modules without using `register!`.
Despite the new register block and register definitions, the read, write, and
modify macros support the same syntax as 0.1. Specifically,
```rust
ral::modify_reg!(pit, pit1, MCR, MDIS: ENABLE);
```
is unchanged from the 0.1 macros. The remaining usages like
```rust
ral::modify_reg!(pit, pit1, CHANNEL[2].TCTRL, TEN: ENABLE);
```
is newly supported. All macros expand through an arbitrary depth of array
offset and block members from the top-level instance.
For compatibility with the macros, the instance type must implement the
unsafe `ral_registers::Inst` trait. The type must implement an
`fn as_ptr() -> *mut RegisterBlock` method. For convenience, the package
provides an opinionated `Instance` type.
Finally, the package exports an `instances!` macro that lets users declare
the base address of register blocks. Each name-address pair expands to a
`const unsafe fn` that produces an `Instance` object. The `const fn` permits
C-style usage when inlined directly into the macro.
## [v0.1.3] - 2023-06-18
* Allow trailing commas inside macros (#7)
## [v0.1.2] - 2023-01-03
* Support register-array access (#5)
## [v0.1.1] - 2021-09-29
* Mark all registers as `#[repr(transparent)]` (#1)
* Update macros to prevent masking of local variables named `mask` or `offset` (#4)
## [v0.1.0] - 2021-08-15
* Initial release. Registers and macros imported from `stm32ral` project.
[Unreleased]: https://github.com/adamgreig/ral-registers/compare/v0.1.3...HEAD
[v0.1.3]: https://github.com/adamgreig/ral-registers/tree/v0.1.3
[v0.1.2]: https://github.com/adamgreig/ral-registers/tree/v0.1.2
[v0.1.1]: https://github.com/adamgreig/ral-registers/tree/v0.1.1
[v0.1.0]: https://github.com/adamgreig/ral-registers/tree/v0.1.0
|