ral/lib.rs
1//! Library providing basis for low level registers access
2//! This crate re-exports macros refined in [ral-macro](https://docs.rs/ral-macro),
3//! so this is the only library needed to be defined in dependencies
4//!
5//! # Code generator
6//!
7//! Refer to [ral-gen](https://docs.rs/ral-gen) crate documentation for code generation guidelines
8//!
9//! # DSL and produced result
10//!
11//! Internally generates register description backed by [ral](https://docs.rs/ral)
12//! ```
13//! use ral::register;
14//!
15//! register! {
16//! use crate_name::types::CustomType; // Use expressions for custom types used in field declarations
17//!
18//! #[access = "read-write"] // Optional register wide access specifier
19//! #[doc = "Register description"] // Optional register description
20//! reg0 { // Register name
21//! offset: 0x8, // Register offset in enclosing peripheral
22//! value_size: 32, // Register size, expected values are 8, 16, 32 or 64
23//! reset_mask: 0xFFFFFFFF, // Reset mask
24//! reset_value: 0x0, // Reset value
25//! fields: { // Optional fields
26//! #[doc = "Bits 16:31 - Read-only u16 field"] // Each field can have a description
27//! #[access = "read-only"] // Access specifier
28//! field5[16:16] as u16, // Field specification `<name>[<offset>:<width>] as <type>`
29//!
30//! #[doc = "Bits 14:15 - Write-only field"]
31//! #[access = "write-only"] // Only setters will be generated
32//! field4[14:2] as u8, // Default supported types are `u8`, `u16`, `u32` and `u64`
33//!
34//! #[doc = "Bits 11:13 - Read-only field"]
35//! #[access = "read-only"] // Only getters will be generated
36//! field3[11:3] as u8,
37//!
38//! #[doc = "Bit 10 - Boolean field"]
39//! #[access = "read-write"] // `read-write` is a default access specifier
40//! field2[10:1] as bool, // `bool` fields are also supported by default
41//!
42//! #[doc = "Bits 8:9 - Enum field"]
43//! #[access = "read-write"] // Both getters and setters will be generated
44//! field1[8:2] as CustomType, // Custom types are supported with limitations
45//!
46//! #[doc = "Bits 0:7 - Read-write by default long field"]
47//! field0[0:8] as u8
48//! }
49//! }
50//! }
51//! ```
52//!
53//! Above register definition will be transformed into following code
54//! ```
55//! // Required uses section
56//! use core::sync::atomic::AtomicPtr;
57//! use core::convert::TryFrom;
58//! use ral::{borrow_register, init_register, return_register, value_read, value_write, R, ReadableRegister, Register, VolatileCell, WritableRegister};
59//! use crate_name::types::CustomType;
60//! const REGISTER: AtomicPtr<VolatileCell<<Reg0 as Register>::ValueType>> = AtomicPtr::new(
61//! (super::BASE_ADDRESS /* Enclosing peripheral/cluster base address */ + 0x00 /* offset */) as *mut VolatileCell<<Reg0 as Register>::ValueType>,
62//! );
63//! ///Register description
64//! pub fn reg0() -> Option<Reg0> {
65//! borrow_register(®ISTER).map(Reg0)
66//! }
67//! pub struct Reg0(R<u32, Reg0>);
68//! impl Drop for Reg0 {
69//! fn drop(&mut self) {
70//! let Reg0(register) = self;
71//! return_register(®ISTER, register);
72//! }
73//! }
74//! impl Register for Reg0 {
75//! type RegisterType = Self;
76//! type ValueType = u32;
77//! const RESET_MASK: Self::ValueType = 0xFFFF_FFFF;
78//! const RESET_VALUE: Self::ValueType = 0x1234_0000;
79//! }
80//! impl ReadableRegister for Reg0 { // Will be added if register wide access allows read
81//! fn get_bits(&self) -> Self::ValueType {
82//! self.0.get_bits()
83//! }
84//!
85//! fn read(&mut self) -> &mut Self::RegisterType {
86//! self.0.read();
87//! self
88//! }
89//! }
90//! impl WritableRegister for Reg0 { // Will be added if register wide access allows write
91//! fn set_bits(&mut self, bits: Self::ValueType) -> &mut Self::RegisterType {
92//! self.0.set_bits(bits);
93//! self
94//! }
95//! fn reset(&mut self) -> &mut Self::RegisterType {
96//! self.set_bits(Self::RESET_VALUE)
97//! }
98//! fn write(&mut self) -> &mut Self::RegisterType {
99//! self.0.write();
100//! self
101//! }
102//! }
103//! impl Reg0 { // Will be added if any fields specified
104//! ///Bits 16:31 - Read-only u16 field
105//! #[inline]
106//! pub fn get_field5(&self) -> u16 {
107//! value_read!(self, 0x0000FFFFu32, 16) as u16
108//! // Will further expand into
109//! // ((self.0.get_bits() >> 16) & 0x0000FFFFu32) as u16
110//! }
111//! ///Bits 14:15 - Write-only field
112//! #[inline]
113//! pub fn set_field4(&mut self, value: u8) -> &mut Self {
114//! value_write!(self, 0x00000003u32, 14, value as <Self as Register>::ValueType);
115//! // Will further expand into
116//! // self.0.set_bits(
117//! // (self.0.get_bits() & !(0x00000003u32 << 14))
118//! // | ((value as <Self as Register>::ValueType & 0x00000003u32) << 14),
119//! // );
120//! self
121//! }
122//! ///Bits 11:13 - Read-only field
123//! #[inline]
124//! pub fn get_field3(&self) -> u8 {
125//! value_read!(self, 0x00000007u32, 11) as u8
126//! // Will further expand into
127//! // ((self.0.get_bits() >> 11) & 0x00000007u32) as u8
128//! }
129//! ///Bit 10 - Boolean field
130//! #[inline]
131//! pub fn is_field2_set(&self) -> bool {
132//! value_read!(self, 0x00000001u32, 10) == 1
133//! // Will further expand into
134//! // ((self.0.get_bits() >> 10) & 0x00000001u32) == 1
135//! }
136//! ///Bit 10 - Boolean field
137//! #[inline]
138//! pub fn set_field2_value(&mut self, value: bool) -> &mut Self {
139//! value_write!(self, 0x00000001u32, 10, value as <Self as Register>::ValueType);
140//! // Will further expand into
141//! // self.0.set_bits(
142//! // (self.0.get_bits() & !(0x00000001u32 << 10))
143//! // | ((value as <Self as Register>::ValueType & 0x00000001u32) << 10),
144//! // );
145//! self
146//! }
147//! ///Bit 10 - Boolean field
148//! #[inline]
149//! pub fn set_field2(&mut self) -> &mut Self {
150//! self.set_field2_value(true)
151//! }
152//! ///Bit 10 - Boolean field
153//! #[inline]
154//! pub fn unset_field2(&mut self) -> &mut Self {
155//! self.set_field2_value(false)
156//! }
157//! ///Bits 8:9 - Enum field
158//! #[inline]
159//! pub fn get_field1(
160//! &self,
161//! ) -> Result<CustomType, <CustomType as TryFrom<<Self as Register>::ValueType>>::Error> {
162//! <CustomType as TryFrom<<Self as Register>::ValueType>>::try_from(value_read!(self, 0x00000003u32, 8))
163//! // Will further expand into
164//! // <CustomType as TryFrom<<Self as Register>::ValueType>>::try_from(
165//! // (self.0.get_bits() >> 8) & 0x00000003u32,
166//! // )
167//! }
168//! ///Bits 8:9 - Enum field
169//! #[inline]
170//! pub fn set_field1(
171//! &mut self,
172//! value: CustomType,
173//! ) -> Result<&mut Self, <<Self as Register>::ValueType as TryFrom<CustomType>>::Error>
174//! {
175//! value_write!(self, 0x00000003u32, 8, <<Self as Register>::ValueType as TryFrom<#ty>>::try_from(value)?);
176//! // Will further expand into
177//! // self.0.set_bits(
178//! // (self.0.get_bits() & !(0x00000003u32 << 8))
179//! // | ((<<Self as Register>::ValueType as TryFrom<CustomType>>::try_from(value)?
180//! // & 0x00000003u32) << 8),
181//! // );
182//! Ok(self)
183//! }
184//! ///Bits 0:7 - Read-write by default long field
185//! #[inline]
186//! pub fn get_field0(&self) -> u8 {
187//! value_read!(self, 0x000000FFu32, 0) as u8
188//! // Will further expand into
189//! // ((self.0.get_bits() >> 0) & 0x000000FFu32) as u8
190//! }
191//! ///Bits 0:7 - Read-write by default long field
192//! #[inline]
193//! pub fn set_field0(&mut self, value: u8) -> &mut Self {
194//! value_write!(self, 0x000000FFu32, 0, value as <Self as Register>::ValueType);
195//! // Will further expand into
196//! // self.0.set_bits(
197//! // (self.0.get_bits() & !(0x000000FFu32 << 0))
198//! // | ((value as <Self as Register>::ValueType & 0x000000FFu32) << 0),
199//! // );
200//! self
201//! }
202//! }
203//! ```
204//!
205//! # Proposed modules structure
206//!
207//! Enclosing peripheral module can look like this
208//! ```ignore
209//! #![doc = "Peripheral description"]
210//!
211//! mod reg0;
212//! pub use reg0::*;
213//!
214//! const BASE_ADDRESS: usize = 0x0000_0000; // Should be actual peripheral base address
215//! ```
216//!
217//! Peripherals module should look like this
218//! ```ignore
219//! pub mod peripheral;
220//! ```
221//!
222//! And finally `lib.rs` should look like this
223//! ```ignore
224//! #![doc = "Device description"]
225//!
226//! pub mod peripherals;
227//! ```
228//!
229//! So the recommended module hierarchy is
230//! ```text,ignore
231//! src/
232//! ├── lib.rs
233//! └── peripherals/
234//! ├── mod.rs
235//! └── peripheral/
236//! ├── mod.rs
237//! ├── reg0.rs
238//! ├── reg1.rs
239//! └── cluster/
240//! ├── mod.rs
241//! ├── reg2.rs
242//! ├── reg3.rs
243//! └── reg4.rs
244//! ```
245//!
246//! The layout also includes optional cluster module, which can look like this
247//! ```ignore
248//! #![doc = "Cluster description"]
249//!
250//! mod reg2;
251//! pub use reg2::*;
252//! mod reg3;
253//! pub use reg3::*;
254//! mod reg4;
255//! pub use reg4::*;
256//!
257//! const BASE_ADDRESS: usize = super::BASE_ADDRESS + 0x40; // Enclosing peripheral/cluster base address plus offset
258//! ```
259//!
260//! # Requirenments to custom types
261//!
262//! For read access you must implement `TryFrom<u32> for CustomType` or `From<u32> for CustomType` if your register is 32-bit
263//! For write access you have to implement `TryFrom<CustomType> for u32` or `From<CustomType> for u32` respectively
264//!
265//! # How to use resulting library
266//!
267//! ```
268//! use device_crate::peripherals::peripheral;
269//!
270//! let mut reg0 = peripheral::reg0()
271//! .unwrap() // Borrow the register
272//! .read(); // Load current data stored in register
273//! let field3 = reg0.get_field3(); // Read `u8` field
274//!
275//! let field2 = reg0.is_field2_set(); // Read `bool` field
276//! let field1: CustomType = reg0.get_field1().unwrap(); // Read field represented by `CustomType`
277//! reg0
278//! .set_field0(if field2 {
279//! reg0.get_field5() as u8
280//! } else {
281//! 0
282//! }) // Set `u8` field
283//! .unset_field2() // Unset `bool` field
284//! .set_field4(field3 + 10) // Set 'u8' field
285//! .set_field1(if field1 == Two { One } else { Three }).unwrap() // Set `CustomType` field
286//! .write(); // Finally write result to hardware register
287//! ```
288#![no_std]
289
290use core::marker::{Copy, PhantomData};
291use core::ops::{BitAnd, BitOr, Not};
292use core::ptr::{null_mut, NonNull};
293use core::sync::atomic::AtomicPtr;
294use core::sync::atomic::Ordering::SeqCst;
295
296pub use vcell::VolatileCell;
297
298pub use ral_macro::*;
299
300/// Register data holder, abstracts interaction with actual hardware
301pub struct R<ValueType, RegisterType>
302where
303 ValueType:
304 Copy + Not<Output = ValueType> + BitAnd<Output = ValueType> + BitOr<Output = ValueType>,
305 RegisterType: Register<RegisterType = RegisterType, ValueType = ValueType>,
306{
307 register_type: PhantomData<RegisterType>,
308 register: NonNull<VolatileCell<ValueType>>,
309 bits: ValueType,
310}
311
312impl<ValueType, RegisterType> R<ValueType, RegisterType>
313where
314 ValueType:
315 Copy + Not<Output = ValueType> + BitAnd<Output = ValueType> + BitOr<Output = ValueType>,
316 RegisterType: Register<RegisterType = RegisterType, ValueType = ValueType>,
317{
318 /// Creates new instance bound to specific register
319 #[inline]
320 pub fn new(register: *mut VolatileCell<ValueType>) -> Option<Self> {
321 NonNull::new(register).map(|ptr| Self {
322 register_type: PhantomData,
323 register: ptr,
324 bits: RegisterType::RESET_VALUE,
325 })
326 }
327
328 /// Gets cached bits
329 #[inline]
330 pub fn get_bits(&self) -> ValueType {
331 self.bits
332 }
333
334 /// Stores bits into cache
335 #[inline]
336 pub fn set_bits(&mut self, bits: ValueType) {
337 self.bits = bits;
338 }
339
340 /// Loads data from register to cache
341 #[inline]
342 pub fn read(&mut self) {
343 unsafe {
344 self.bits = self.register.as_ref().get();
345 }
346 }
347
348 /// Stores data from cache to register
349 #[inline]
350 pub fn write(&mut self) {
351 unsafe {
352 self.register.as_ref().set(
353 (!RegisterType::RESET_MASK & RegisterType::RESET_VALUE)
354 | (RegisterType::RESET_MASK & self.bits),
355 );
356 }
357 }
358}
359
360impl<ValueType, RegisterType> Into<*mut VolatileCell<ValueType>> for &mut R<ValueType, RegisterType>
361where
362 ValueType:
363 Copy + Not<Output = ValueType> + BitAnd<Output = ValueType> + BitOr<Output = ValueType>,
364 RegisterType: Register<RegisterType = RegisterType, ValueType = ValueType>,
365{
366 fn into(self) -> *mut VolatileCell<ValueType> {
367 self.register.as_ptr()
368 }
369}
370
371/// Trait representing register, actual registers are to implement this
372pub trait Register {
373 /// Actual register type for operations chaining
374 type RegisterType: Register;
375
376 /// Value type, expected to be one of `u8`, `u16`, `u32` or `u64`
377 type ValueType: Copy
378 + Not<Output = Self::ValueType>
379 + BitAnd<Output = Self::ValueType>
380 + BitOr<Output = Self::ValueType>;
381
382 /// Reset mask
383 const RESET_MASK: Self::ValueType;
384
385 /// Reset value
386 const RESET_VALUE: Self::ValueType;
387}
388
389/// Trait representing readable part of register, actual registers are to implement this
390pub trait ReadableRegister: Register {
391 /// Get value of the register as raw bits
392 fn get_bits(&self) -> Self::ValueType;
393
394 /// Loads value from the register
395 fn read(&mut self) -> &mut Self::RegisterType;
396}
397
398/// Trait representing writable part of register, actual registers are to implement this
399pub trait WritableRegister: Register {
400 /// Set value of the register as raw bits
401 fn set_bits(&mut self, bits: Self::ValueType) -> &mut Self::RegisterType;
402
403 /// Reset value of the register to default
404 fn reset(&mut self) -> &mut Self::RegisterType;
405
406 /// Writes value to the register
407 fn write(&mut self) -> &mut Self::RegisterType;
408}
409
410/// Extract specific bits from register value
411#[macro_export]
412macro_rules! value_read {
413 ($r: expr, $m: expr, $o: expr) => {
414 (($r.0.get_bits() >> $o) & $m)
415 };
416}
417
418/// Set specific bits to register value
419#[macro_export]
420macro_rules! value_write {
421 ($r: expr, $m: expr, $o: expr, $v: expr) => {
422 $r.0.set_bits(($r.0.get_bits() & !($m << $o)) | ((($v) & $m) << $o));
423 };
424}
425
426/// Init register
427#[macro_export]
428macro_rules! init_register {
429 ($a: expr, $t: tt) => {
430 AtomicPtr::new($a as *mut VolatileCell<<$t as Register>::ValueType>)
431 };
432}
433
434/// Exclusively borrows register
435pub fn borrow_register<ValueType, RegisterType>(
436 holder: &AtomicPtr<VolatileCell<ValueType>>,
437) -> Option<R<ValueType, RegisterType>>
438where
439 ValueType:
440 Copy + Not<Output = ValueType> + BitAnd<Output = ValueType> + BitOr<Output = ValueType>,
441 RegisterType: Register<RegisterType = RegisterType, ValueType = ValueType>,
442{
443 R::new(holder.swap(null_mut(), SeqCst))
444}
445
446/// Releases register, so it can be borrowed again
447pub fn return_register<ValueType, RegisterType>(
448 holder: &AtomicPtr<VolatileCell<ValueType>>,
449 register: &mut R<ValueType, RegisterType>,
450) where
451 ValueType:
452 Copy + Not<Output = ValueType> + BitAnd<Output = ValueType> + BitOr<Output = ValueType>,
453 RegisterType: Register<RegisterType = RegisterType, ValueType = ValueType>,
454{
455 holder.swap(register.into(), SeqCst);
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461
462 struct TestR(R<u32, TestR>);
463
464 impl Register for TestR {
465 type RegisterType = Self;
466
467 type ValueType = u32;
468
469 const RESET_MASK: Self::ValueType = 0xF3FF_FFFF;
470
471 const RESET_VALUE: Self::ValueType = 0x2800_0000;
472 }
473
474 impl ReadableRegister for TestR {
475 fn get_bits(&self) -> Self::ValueType {
476 self.0.get_bits()
477 }
478
479 fn read(&mut self) -> &mut Self::RegisterType {
480 self.0.read();
481 self
482 }
483 }
484
485 impl WritableRegister for TestR {
486 fn set_bits(&mut self, bits: Self::ValueType) -> &mut Self::RegisterType {
487 self.0.set_bits(bits);
488 self
489 }
490
491 fn reset(&mut self) -> &mut Self::RegisterType {
492 self.set_bits(Self::RESET_VALUE)
493 }
494
495 fn write(&mut self) -> &mut Self::RegisterType {
496 self.0.write();
497 self
498 }
499 }
500
501 impl TestR {
502 #[inline]
503 pub fn get_test_30_31(&self) -> u8 {
504 value_read!(self, 0x3u32, 30) as u8
505 }
506
507 pub fn set_test_30_31(&mut self, value: u8) -> &mut Self {
508 value_write!(self, 0x3u32, 30, value as <Self as Register>::ValueType);
509 self
510 }
511
512 #[inline]
513 pub fn get_test_0_3(&self) -> u8 {
514 value_read!(self, 0xFu32, 0) as u8
515 }
516
517 pub fn set_test_0_3(&mut self, value: u8) -> &mut Self {
518 value_write!(self, 0xFu32, 0, value as <Self as Register>::ValueType);
519 self
520 }
521 }
522
523 #[test]
524 fn test_register_access() {
525 let mut registry_data: u32 = 0x89AB_CDEF;
526
527 let register_holder: AtomicPtr<VolatileCell<<TestR as Register>::ValueType>> =
528 init_register!(&mut registry_data as *mut u32, TestR);
529 let mut register_some: Option<R<u32, TestR>> = borrow_register(®ister_holder);
530 let register_none: Option<R<u32, TestR>> = borrow_register(®ister_holder);
531 assert!(register_some.is_some());
532 assert!(register_none.is_none());
533 return_register(®ister_holder, register_some.as_mut().unwrap());
534 let mut register: Option<R<u32, TestR>> = borrow_register(®ister_holder);
535 assert!(register.is_some());
536 return_register(®ister_holder, register.as_mut().unwrap());
537 }
538
539 #[test]
540 fn test_get() {
541 let mut registry_data: u32 = 0x8765_4321;
542
543 let register_holder: AtomicPtr<VolatileCell<<TestR as Register>::ValueType>> =
544 init_register!(&mut registry_data as *mut u32, TestR);
545 let mut register = borrow_register(®ister_holder).map(TestR).unwrap();
546 register.read();
547 assert_eq!(register.get_test_0_3(), 0x01);
548 assert_eq!(register.get_test_30_31(), 0x02);
549 }
550
551 #[test]
552 fn test_set() {
553 let mut registry_data: u32 = 0x8765_4321;
554
555 let register_holder: AtomicPtr<VolatileCell<<TestR as Register>::ValueType>> =
556 init_register!(&mut registry_data as *mut u32, TestR);
557 let mut register = borrow_register(®ister_holder).map(TestR).unwrap();
558 register.set_test_0_3(0xDAu8).set_test_30_31(0x0Au8).write();
559 let TestR(r) = &mut register;
560 return_register(®ister_holder, r);
561 assert_eq!(registry_data, 0x8000_000A | TestR::RESET_VALUE);
562 }
563
564 #[test]
565 fn test_update() {
566 let mut registry_data: u32 = 0x8765_4321;
567
568 let register_holder: AtomicPtr<VolatileCell<<TestR as Register>::ValueType>> =
569 init_register!(&mut registry_data as *mut u32, TestR);
570 let mut register = borrow_register(®ister_holder).map(TestR).unwrap();
571 register
572 .read()
573 .set_test_0_3(0xDAu8)
574 .set_test_30_31(0x01u8)
575 .write();
576 let TestR(r) = &mut register;
577 return_register(®ister_holder, r);
578 assert_eq!(registry_data, 0x4B65_432A);
579 }
580
581 #[test]
582 fn test_reset() {
583 let mut registry_data: u32 = 0x8765_4321;
584
585 let register_holder: AtomicPtr<VolatileCell<<TestR as Register>::ValueType>> =
586 init_register!(&mut registry_data as *mut u32, TestR);
587 let mut register = borrow_register(®ister_holder).map(TestR).unwrap();
588 register.read();
589 register.reset();
590 register.write();
591 let TestR(r) = &mut register;
592 return_register(®ister_holder, r);
593 assert_eq!(registry_data, TestR::RESET_VALUE);
594 }
595}