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
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Tock Register Interface
//!
//! Provides efficient mechanisms to express and use type-checked
//! memory mapped registers and bitfields.
//!
//! ```rust
//! # fn main() {}
//!
//! use tock_registers::registers::{ReadOnly, ReadWrite};
//! use tock_registers::register_bitfields;
//!
//! // Register maps are specified like this:
//! #[repr(C)]
//! struct Registers {
//!     // Control register: read-write
//!     cr: ReadWrite<u32, Control::Register>,
//!     // Status register: read-only
//!     s: ReadOnly<u32, Status::Register>,
//! }
//!
//! // Register fields and definitions look like this:
//! register_bitfields![u32,
//!     // Simpler bitfields are expressed concisely:
//!     Control [
//!         /// Stop the Current Transfer
//!         STOP 8,
//!         /// Software Reset
//!         SWRST 7,
//!         /// Master Disable
//!         MDIS 1,
//!         /// Master Enable
//!         MEN 0
//!     ],
//!
//!     // More complex registers can express subtypes:
//!     Status [
//!         TXCOMPLETE  OFFSET(0) NUMBITS(1) [],
//!         TXINTERRUPT OFFSET(1) NUMBITS(1) [],
//!         RXCOMPLETE  OFFSET(2) NUMBITS(1) [],
//!         RXINTERRUPT OFFSET(3) NUMBITS(1) [],
//!         MODE        OFFSET(4) NUMBITS(3) [
//!             FullDuplex = 0,
//!             HalfDuplex = 1,
//!             Loopback = 2,
//!             Disabled = 3
//!         ],
//!         ERRORCOUNT OFFSET(6) NUMBITS(3) []
//!     ]
//! ];
//! ```
//!
//! Author
//! ------
//! - Shane Leonard <shanel@stanford.edu>

#![no_std]
// If we don't build any actual register types, we don't need unsafe
// code in this crate
#![cfg_attr(not(feature = "register_types"), forbid(unsafe_code))]

pub mod fields;
pub mod interfaces;
pub mod macros;

#[cfg(feature = "register_types")]
pub mod registers;

pub mod debug;

mod local_register;
pub use local_register::LocalRegisterCopy;

use core::fmt::Debug;
use core::ops::{BitAnd, BitOr, BitOrAssign, Not, Shl, Shr};

/// Trait representing the base type of registers.
///
/// UIntLike defines basic properties of types required to
/// read/write/modify a register through its methods and supertrait
/// requirements.
///
/// It features a range of default implementations for common unsigned
/// integer types, such as [`u8`], [`u16`], [`u32`], [`u64`], [`u128`],
/// and [`usize`].
pub trait UIntLike:
    BitAnd<Output = Self>
    + BitOr<Output = Self>
    + BitOrAssign
    + Not<Output = Self>
    + Eq
    + Shr<usize, Output = Self>
    + Shl<usize, Output = Self>
    + Copy
    + Clone
    + Debug
{
    /// Return the representation of the value `0` in the implementing
    /// type.
    ///
    /// This can be used to acquire values of the [`UIntLike`] type,
    /// even in generic implementations. For instance, to get the
    /// value `1`, one can use `<T as UIntLike>::zero() + 1`. To get
    /// the largest representable value, use a bitwise negation: `~(<T
    /// as UIntLike>::zero())`.
    fn zero() -> Self;
}

// Helper macro for implementing the UIntLike trait on differrent
// types.
macro_rules! UIntLike_impl_for {
    ($type:ty) => {
        impl UIntLike for $type {
            fn zero() -> Self {
                0
            }
        }
    };
}

UIntLike_impl_for!(u8);
UIntLike_impl_for!(u16);
UIntLike_impl_for!(u32);
UIntLike_impl_for!(u64);
UIntLike_impl_for!(u128);
UIntLike_impl_for!(usize);

/// Descriptive name for each register.
pub trait RegisterLongName {}

// Useful implementation for when no RegisterLongName is required
// (e.g. no fields need to be accessed, just the raw register values)
impl RegisterLongName for () {}