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(&REGISTER).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(&REGISTER, 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(&register_holder);
530        let register_none: Option<R<u32, TestR>> = borrow_register(&register_holder);
531        assert!(register_some.is_some());
532        assert!(register_none.is_none());
533        return_register(&register_holder, register_some.as_mut().unwrap());
534        let mut register: Option<R<u32, TestR>> = borrow_register(&register_holder);
535        assert!(register.is_some());
536        return_register(&register_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(&register_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(&register_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(&register_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(&register_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(&register_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(&register_holder).map(TestR).unwrap();
588        register.read();
589        register.reset();
590        register.write();
591        let TestR(r) = &mut register;
592        return_register(&register_holder, r);
593        assert_eq!(registry_data, TestR::RESET_VALUE);
594    }
595}