Skip to content

Commit 455d8d1

Browse files
committed
generic-p1
1 parent fde8568 commit 455d8d1

File tree

4 files changed

+258
-82
lines changed

4 files changed

+258
-82
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod device;
2+
pub mod generic;
23
pub mod interrupt;
34
pub mod peripheral;
45
pub mod register;

src/generate/device.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::errors::*;
66
use crate::util::{self, ToSanitizedUpperCase};
77
use crate::Target;
88

9-
use crate::generate::{interrupt, peripheral};
9+
use crate::generate::{interrupt, peripheral, generic};
1010

1111
/// Whole device generation
1212
pub fn render(
@@ -136,6 +136,8 @@ pub fn render(
136136
}
137137
}
138138

139+
out.extend(generic::render()?);
140+
139141
for p in &d.peripherals {
140142
if target == Target::CortexM && core_peripherals.contains(&&*p.name.to_uppercase()) {
141143
// Core peripherals are handled above

src/generate/generic.rs

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
use quote::Tokens;
2+
3+
use crate::errors::*;
4+
5+
/// Generates generic bit munging code
6+
pub fn render() -> Result<Vec<Tokens>> {
7+
let mut code = vec![];
8+
let mut generic_items = vec![];
9+
10+
generic_items.push(quote! {
11+
use core::marker;
12+
use core::ops::Deref;
13+
use vcell::VolatileCell;
14+
15+
///Marker trait for readable register/field
16+
pub trait Readable {}
17+
18+
///Marker trait for writable register/field
19+
pub trait Writable {}
20+
21+
/// Marker struct for register/field with safe write
22+
pub struct Safe;
23+
24+
/// Marker struct for register/field with unsafe write
25+
pub struct Unsafe;
26+
27+
///Reset value of the register
28+
pub trait ResetValue<U> {
29+
///Reset value of the register
30+
fn reset_value() -> U;
31+
}
32+
});
33+
34+
generic_items.push(quote! {
35+
///Wrapper for registers
36+
pub struct Reg<REG>(pub(crate) REG);
37+
38+
impl<U, REG> Reg<REG>
39+
where
40+
REG: Readable + Deref<Target=VolatileCell<U>>,
41+
U: Copy
42+
{
43+
///Reads the contents of the register
44+
#[inline(always)]
45+
pub fn read(&self) -> R<U, REG> {
46+
R::new((*self.0).get())
47+
}
48+
}
49+
50+
impl<U, REG> Reg<REG>
51+
where
52+
Self: ResetValue<U>,
53+
REG: Writable + Deref<Target=VolatileCell<U>>,
54+
U: Copy,
55+
{
56+
///Writes the reset value to the register
57+
#[inline(always)]
58+
pub fn reset(&self) {
59+
(*self.0).set(Self::reset_value())
60+
}
61+
}
62+
});
63+
64+
generic_items.push(quote! {
65+
impl<U, REG> Reg<REG>
66+
where
67+
Self: ResetValue<U>,
68+
REG: Writable + Deref<Target=VolatileCell<U>>,
69+
U: Copy
70+
{
71+
///Writes to the register
72+
#[inline(always)]
73+
pub fn write<F, S>(&self, f: F)
74+
where
75+
F: FnOnce(&mut W<U, REG, S>) -> &mut W<U, REG, S>
76+
{
77+
78+
(*self.0).set(f(&mut W::new(Self::reset_value())).bits);
79+
}
80+
}
81+
});
82+
83+
generic_items.push(quote! {
84+
impl<U, REG> Reg<REG>
85+
where
86+
REG: Writable + Deref<Target=VolatileCell<U>>,
87+
U: Copy + Default
88+
{
89+
///Writes Zero to the register
90+
#[inline(always)]
91+
pub fn write_with_zero<F, S>(&self, f: F)
92+
where
93+
F: FnOnce(&mut W<U, REG, S>) -> &mut W<U, REG, S>
94+
{
95+
96+
(*self.0).set(f(&mut W::new(U::default())).bits);
97+
}
98+
}
99+
});
100+
101+
generic_items.push(quote! {
102+
impl<U, REG> Reg<REG>
103+
where
104+
REG: Readable + Writable + Deref<Target = VolatileCell<U>>,
105+
U: Copy,
106+
{
107+
///Modifies the contents of the register
108+
#[inline(always)]
109+
pub fn modify<F, S>(&self, f: F)
110+
where
111+
for<'w> F: FnOnce(&R<U, REG>, &'w mut W<U, REG, S>) -> &'w mut W<U, REG, S>
112+
{
113+
let bits = (*self.0).get();
114+
(*self.0).set(f(&R::new(bits), &mut W::new(bits)).bits);
115+
}
116+
}
117+
});
118+
119+
generic_items.push(quote! {
120+
///Register reader
121+
pub struct R<U, T> where T: Readable {
122+
bits: U,
123+
_reg: marker::PhantomData<T>,
124+
}
125+
126+
impl<U, T> R<U, T>
127+
where
128+
T: Readable,
129+
U: Copy
130+
{
131+
///Create new instance of reader
132+
#[inline(always)]
133+
pub fn new(bits: U) -> Self {
134+
Self {
135+
bits,
136+
_reg: marker::PhantomData,
137+
}
138+
}
139+
///Read raw bits from register
140+
#[inline(always)]
141+
pub fn bits(&self) -> U {
142+
self.bits
143+
}
144+
}
145+
});
146+
147+
generic_items.push(quote! {
148+
///Register writer
149+
pub struct W<U, REG, S> where REG: Writable {
150+
///Writable bits
151+
pub bits: U,
152+
_reg: marker::PhantomData<(REG, S)>,
153+
}
154+
155+
impl<U, REG, S> W<U, REG, S> where REG: Writable {
156+
///Create new instance of reader
157+
#[inline(always)]
158+
pub(crate) fn new(bits: U) -> Self {
159+
Self {
160+
bits,
161+
_reg: marker::PhantomData,
162+
}
163+
}
164+
}
165+
});
166+
167+
generic_items.push(quote! {
168+
impl<U, REG> W<U, REG, Safe> where REG: Writable {
169+
///Writes raw bits to the register
170+
#[inline(always)]
171+
pub fn bits(&mut self, bits: U) -> &mut Self {
172+
self.bits = bits;
173+
self
174+
}
175+
}
176+
177+
impl<U, REG> W<U, REG, Unsafe> where REG: Writable {
178+
///Writes raw bits to the register
179+
#[inline(always)]
180+
pub unsafe fn bits(&mut self, bits: U) -> &mut Self {
181+
self.bits = bits;
182+
self
183+
}
184+
}
185+
});
186+
187+
code.push(quote! {
188+
#[allow(unused_imports)]
189+
use generic::*;
190+
///Common register and bit access and modify traits
191+
pub mod generic {
192+
#(#generic_items)*
193+
}
194+
});
195+
196+
Ok(code)
197+
}

0 commit comments

Comments
 (0)