Skip to main content

da14582_pac/
common.rs

1/*
2DISCLAIMER
3This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products.
4No other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
5applicable laws, including copyright laws.
6THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED
7OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
8NON-INFRINGEMENT.  ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY
9LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE FOR ANY DIRECT,
10INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR
11ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
12Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability
13of this software. By using this software, you agree to the additional terms and conditions found by accessing the
14following link:
15http://www.renesas.com/disclaimer
16
17*/
18// Generated from SVD 1.2, with svd2pac 0.6.0 on Thu, 24 Jul 2025 04:44:29 +0000
19
20use core::convert::From;
21use core::marker::PhantomData;
22
23#[cfg(feature = "tracing")]
24use crate::tracing;
25
26#[derive(Copy, Clone, PartialEq, Eq)]
27pub struct RW;
28#[derive(Copy, Clone, PartialEq, Eq)]
29pub struct R;
30#[derive(Copy, Clone, PartialEq, Eq)]
31pub struct W;
32
33pub(crate) mod sealed {
34    use super::*;
35    pub trait Access {}
36    impl Access for R {}
37    impl Access for W {}
38    impl Access for RW {}
39    use core::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Shl, Shr};
40
41    // It would be better with const fn
42    // waiting for RFC: const functions in traits #3490
43    pub trait CastFrom<A> {
44        fn cast_from(val: A) -> Self;
45    }
46
47    impl CastFrom<u64> for u8 {
48        #[inline(always)]
49        fn cast_from(val: u64) -> Self {
50            val as Self
51        }
52    }
53
54    impl CastFrom<u64> for u16 {
55        #[inline(always)]
56        fn cast_from(val: u64) -> Self {
57            val as Self
58        }
59    }
60
61    impl CastFrom<u64> for u32 {
62        #[inline(always)]
63        fn cast_from(val: u64) -> Self {
64            val as Self
65        }
66    }
67
68    impl CastFrom<u64> for u64 {
69        #[inline(always)]
70        fn cast_from(val: u64) -> Self {
71            val as Self
72        }
73    }
74
75    pub trait RegNumberT:
76        Copy
77        + From<u8>
78        + Into<u64>
79        + CastFrom<u64>
80        + Shr<usize, Output = Self>
81        + Shl<usize, Output = Self>
82        + BitAndAssign
83        + BitAnd<Output = Self>
84        + Not<Output = Self>
85        + BitOrAssign
86    {
87    }
88    impl RegNumberT for u8 {}
89    impl RegNumberT for u16 {}
90    impl RegNumberT for u32 {}
91    impl RegNumberT for u64 {}
92
93    pub trait RegSpec {
94        type DataType: RegNumberT;
95    }
96}
97
98pub trait Access: sealed::Access + Copy {}
99impl Access for R {}
100impl Access for W {}
101impl Access for RW {}
102
103pub trait Read: Access {}
104impl Read for RW {}
105impl Read for R {}
106
107pub trait Write: Access {}
108impl Write for RW {}
109impl Write for W {}
110
111#[derive(Copy, Clone, PartialEq, Eq)]
112pub struct Reg<T, A: Access> {
113    phantom: PhantomData<*mut (T, A)>,
114}
115unsafe impl<T, A: Access> Send for Reg<T, A> {}
116unsafe impl<T, A: Access> Sync for Reg<T, A> {}
117
118use sealed::CastFrom;
119
120use sealed::{RegNumberT, RegSpec};
121#[doc(hidden)]
122#[derive(Copy, Clone)]
123pub struct RegValueT<Reg: sealed::RegSpec> {
124    pub(crate) data: Reg::DataType,
125    pub(crate) mask: Reg::DataType,
126}
127
128pub trait RegisterValue<T: RegSpec> {
129    /// Create a register value that could be written to a register from raw integer
130    ///
131    /// ```rust, ignore
132    /// // example with generic names
133    /// // needs: use test_pac::{timer, RegisterValue, TIMER}
134    /// let to_write = timer::BitfieldReg::new(0xdeadbeef);
135    /// TIMER.bitfield_reg().write(to_write);
136    /// let to_write = to_write.boolw().set(true);
137    /// TIMER.bitfield_reg().write(to_write);
138    /// ```
139    #[must_use]
140    fn new(data: T::DataType) -> Self;
141
142    /// Get raw integer from value read from register
143    ///
144    /// ```rust,ignore
145    /// // example with generic names
146    /// // needs: use pac::{RegisterValue, TIMER}
147    /// let x = TIMER.bitfield_reg().read().get_raw();
148    /// ```
149    #[must_use]
150    fn get_raw(&self) -> T::DataType;
151
152    /// Prepare a register value that could be written to a register with an arbitrary value
153    ///
154    /// Use this function for setting a register to a custom value, independent
155    /// of bitfields, enumerations, etc. No checks are performed on the passed
156    /// value. The whole register is updated on write.
157    ///
158    /// ```rust,ignore
159    /// // example with generic names
160    /// // needs: use pac::{RegisterValue, TIMER}
161    /// TIMER.bitfield_reg().init(|r| r.set_raw(0xdeadbeef))
162    /// ```
163    #[must_use]
164    fn set_raw(self, value: T::DataType) -> Self;
165}
166
167impl<T: RegSpec> RegisterValue<T> for RegValueT<T> {
168    /// Create a register value that could be written to a register from raw integer
169    ///
170    /// ```rust, ignore
171    /// // example with generic names
172    /// // needs: use pac::{timer, RegisterValue, TIMER}
173    /// let to_write = timer::BitfieldReg::new(0xdeadbeef);
174    /// TIMER.bitfield_reg().write(to_write);
175    /// let to_write = to_write.boolw().set(true);
176    /// TIMER.bitfield_reg().write(to_write);
177    /// ```
178    #[inline(always)]
179    fn new(data: T::DataType) -> RegValueT<T> {
180        Self {
181            data,
182            mask: 0x0u8.into(),
183        }
184    }
185
186    /// Get raw integer from value read from register
187    ///
188    /// ```rust,ignore
189    /// // example with generic names
190    /// // needs: use pac::{RegisterValue, TIMER}
191    /// let x = TIMER.bitfield_reg().read().get_raw();
192    /// ```
193    #[inline(always)]
194    fn get_raw(&self) -> T::DataType {
195        self.data
196    }
197
198    /// Prepare a register value that could be written to a register with an arbitrary value
199    ///
200    /// Use this function for setting a register to a custom value, independent
201    /// of bitfields, enumerations, etc. No checks are performed on the passed
202    /// value.
203    ///
204    /// ```rust,ignore
205    /// // example with generic names
206    /// // needs: use pac::{RegisterValue, TIMER}
207    /// TIMER.bitfield_reg().init(|r| r.set_raw(0xdeadbeef))
208    /// ```
209    #[inline(always)]
210    fn set_raw(mut self, value: T::DataType) -> Self {
211        self.data = value;
212        self.mask = !(Into::<T::DataType>::into(0x0u8));
213        self
214    }
215}
216
217pub trait NoBitfieldReg<Reg: RegSpec>: RegisterValue<Reg>
218where
219    Self: Sized,
220{
221    /// Get value read from register
222    ///
223    /// ```rust,ignore
224    /// // example with generic names
225    /// // needs: use pac::{NoBitfieldReg, TIMER}
226    /// let x = TIMER.nobitfield_reg().read().get();
227    /// ```
228    #[inline(always)]
229    #[must_use]
230    fn get(&self) -> Reg::DataType {
231        self.get_raw()
232    }
233
234    /// Prepare value to be written to register
235    ///
236    /// ```rust,ignore
237    /// // example with generic names
238    /// // needs: use pac::{NoBitfieldReg, TIMER}
239    /// TIMER.nobitfield_reg().init(|r| r.set(0xc0ffee));
240    /// ```
241    #[inline(always)]
242    #[must_use]
243    fn set(self, value: Reg::DataType) -> Self {
244        self.set_raw(value)
245    }
246}
247
248impl<T, A> Reg<T, A>
249where
250    T: RegSpec,
251    A: Access,
252{
253    #[allow(dead_code)]
254    #[inline(always)]
255    #[must_use]
256    #[allow(dead_code)]
257    pub(crate) const fn from_ptr(ptr: *mut u8) -> &'static Self {
258        unsafe { &*(ptr as *const Self) }
259    }
260
261    #[inline(always)]
262    #[must_use]
263    pub const fn ptr(&self) -> *mut T::DataType {
264        self as *const _ as *mut T::DataType
265    }
266
267    /// Returns the address of the register.
268    pub fn addr(&self) -> usize {
269        (self as *const _) as usize
270    }
271}
272
273impl<T, A> Reg<T, A>
274where
275    T: RegSpec,
276    A: Read,
277{
278    /// Read register and return a register value
279    ///
280    /// # Safety
281    /// Read operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
282    /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
283    ///
284    /// # Example
285    /// ```rust,ignore
286    /// // example with generic names
287    /// let reg = unsafe { TIMER.bitfield_reg().read() };
288    /// if reg.boolr().get() { /* ... */ }
289    /// ```
290    #[inline(always)]
291    #[must_use]
292    pub unsafe fn read(&self) -> RegValueT<T> {
293        #[cfg(feature = "tracing")]
294        let val = {
295            let mut buf: u64 = 0x0;
296            tracing::READ_FN.with(|rf| {
297                if let Some(rf) = rf.get() {
298                    buf = rf(self.addr(), std::mem::size_of::<T::DataType>());
299                } else {
300                    #[cfg(not(feature = "tracing_dummy"))]
301                    panic!(
302                        "Please, provide an handler for read with tracing::set_read_fn(callback);"
303                    );
304                }
305            });
306            T::DataType::cast_from(buf)
307        };
308        #[cfg(not(feature = "tracing"))]
309        let val = self.ptr().read_volatile();
310        RegValueT::<T>::new(val)
311    }
312}
313
314impl<T, A> Reg<T, A>
315where
316    T: RegSpec,
317    A: Write,
318{
319    /// Write register value back to register
320    ///
321    /// # Arguments
322    ///
323    /// * `reg_value` - A string slice that holds the name of the person
324    ///
325    /// # Safety
326    /// Write operation could cause undefined behavior for some peripheral. Developers shall read the device user manual.
327    /// Register is Send and Sync to allow complete freedom. Developers are responsible of proper use in interrupt and thread.
328    ///
329    /// # Example
330    /// ```rust,ignore
331    /// // example with generic names
332    /// // write with a previously read value
333    /// let reg = unsafe { TIMER.bitfield_reg().read() };
334    /// // or start with a known value
335    /// let reg = timer::BitfieldReg::new(0).bitfieldw().set(0x55);
336    /// // or start with the register default
337    /// let reg = timer::BitfieldReg::default();
338    ///
339    /// let reg = reg.bitfieldrw().set(0x77);
340    ///
341    /// // no change has taken place to the register due to `set` calls - do that now by writing back the result
342    /// unsafe { TIMER.bitfield_reg().write(reg) }
343    /// ```
344    /// See also: [`Reg<T, A>::init`] which provides the default value to a closure
345    #[inline(always)]
346    pub unsafe fn write(&self, reg_value: RegValueT<T>) {
347        #[cfg(feature = "tracing")]
348        tracing::WRITE_FN.with(|wf| {
349            if let Some(wf) = wf.get() {
350                wf(
351                    self.addr(),
352                    std::mem::size_of::<T::DataType>(),
353                    reg_value.data.into(),
354                )
355            } else {
356                #[cfg(not(feature = "tracing_dummy"))]
357                panic!("Please, provide an handler for read with tracing::set_read_fn(callback);");
358            }
359        });
360        #[cfg(not(feature = "tracing"))]
361        self.ptr().write_volatile(reg_value.data);
362    }
363
364    /// Write an arbitrary integer to register
365    ///
366    /// Use this function when e.g. loading data to be written from a config-page.
367    /// For normal use prefer either [`Reg<T, A>::write`] if the value was read before, or [`Reg<T, A>::init`],
368    /// both of which provide some restrictions available register fields, enums, etc.
369    ///
370    /// # Arguments
371    ///
372    /// * `value` - The unchecked value to be written to the register
373    ///
374    /// # Safety
375    ///
376    /// Write operation could cause undefined behavior for some peripheral. Developers shall read the device user manual.
377    /// Register is Send and Sync to allow complete freedom. Developers are responsible of proper use in interrupt and thread.
378    ///
379    /// # Example
380    /// ```rust,ignore
381    /// // example with generic names
382    /// unsafe { TIMER.bitfield_reg().write_raw(0xdead) }
383    /// ```
384    /// See also [`Reg<T, A>::init`] and [`Reg<T, A>::write`] both of which are the safe, preferred functions.
385    #[inline(always)]
386    pub unsafe fn write_raw(&self, value: T::DataType) {
387        #[cfg(feature = "tracing")]
388        tracing::WRITE_FN.with(|wf| {
389            if let Some(wf) = wf.get() {
390                wf(
391                    self.addr(),
392                    std::mem::size_of::<T::DataType>(),
393                    value.into(),
394                )
395            } else {
396                #[cfg(not(feature = "tracing_dummy"))]
397                panic!("Please, provide an handler for read with tracing::set_read_fn(callback);");
398            }
399        });
400        #[cfg(not(feature = "tracing"))]
401        self.ptr().write_volatile(value);
402    }
403}
404
405impl<T, A> Reg<T, A>
406where
407    T: RegSpec,
408    A: Write,
409    RegValueT<T>: Default,
410{
411    /// Write register with register value built from default register value
412    ///
413    /// # Arguments
414    ///
415    /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset.
416    ///
417    /// # Safety
418    /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
419    /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
420    ///
421    /// # Example
422    /// ```rust,ignore
423    /// // example with generic names
424    /// TIMER
425    ///     .bitfield_reg()
426    ///     .init(|r| r.bitfieldw().set(0b1010).boolw().set(true));
427    /// ```
428    #[inline(always)]
429    /// Write value computed by closure that receive as input the reset value of register
430    pub unsafe fn init(&self, f: impl FnOnce(RegValueT<T>) -> RegValueT<T>) {
431        let val = RegValueT::<T>::default();
432        let res = f(val);
433        self.write(res);
434    }
435}
436
437impl<T, A> Reg<T, A>
438where
439    T: RegSpec,
440    A: Read + Write,
441{
442    /// Read/modify/write register
443    ///
444    /// # Arguments
445    ///
446    /// * `f` - Closure that receive as input a register value read from register. The result of the closure
447    ///   is written back to the register.
448    ///
449    /// # Safety
450    /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
451    /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
452    ///
453    /// # Example
454    /// ```rust,ignore
455    /// // example with generic names
456    /// TIMER
457    ///     .bitfield_reg()
458    ///     .modify(|r| r.boolrw().set(!r.boolrw().get()));
459    /// ```
460    #[inline(always)]
461    pub unsafe fn modify(&self, f: impl FnOnce(RegValueT<T>) -> RegValueT<T>) {
462        let val = self.read();
463        let res = f(val);
464        self.write(res);
465    }
466}
467
468/// Proxy struct for enumerated bitfields
469#[repr(transparent)]
470#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
471pub struct EnumBitfieldStruct<Q: RegNumberT, T>(pub Q, PhantomData<T>);
472
473impl<Q: RegNumberT, T> EnumBitfieldStruct<Q, T> {
474    pub const fn new(value: Q) -> Self {
475        Self(value, PhantomData)
476    }
477}
478
479impl<Q: RegNumberT, T> From<EnumBitfieldStruct<Q, T>> for u64 {
480    #[inline(always)]
481    fn from(value: EnumBitfieldStruct<Q, T>) -> Self {
482        value.0.into()
483    }
484}
485impl<Q: RegNumberT, T> CastFrom<u64> for EnumBitfieldStruct<Q, T> {
486    #[inline(always)]
487    fn cast_from(val: u64) -> Self {
488        Self(Q::cast_from(val), PhantomData)
489    }
490}
491
492impl<Q: RegNumberT, T> From<Q> for EnumBitfieldStruct<Q, T> {
493    #[inline(always)]
494    fn from(value: Q) -> Self {
495        Self(value, PhantomData)
496    }
497}
498
499/// Proxy struct for numeric bitfields
500pub struct RegisterField<
501    const START_OFFSET: usize,
502    const MASK: u64,
503    const DIM: u8,
504    const DIM_INCREMENT: u8,
505    ValueTypeRead,
506    ValueTypeWrite,
507    T,
508    A,
509> where
510    T: RegSpec,
511    A: Access,
512{
513    data: RegValueT<T>,
514    index: u8,
515    marker: PhantomData<(ValueTypeRead, ValueTypeWrite, A)>,
516}
517
518impl<
519    const START_OFFSET: usize,
520    const MASK: u64,
521    const DIM: u8,
522    const DIM_INCREMENT: u8,
523    ValueTypeRead,
524    ValueTypeWrite,
525    T,
526    A,
527> RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead, ValueTypeWrite, T, A>
528where
529    T: RegSpec,
530    A: Access,
531{
532    #[allow(dead_code)]
533    #[inline(always)]
534    pub(crate) fn from_register(data: RegValueT<T>, index: u8) -> Self {
535        Self {
536            data,
537            index,
538            marker: PhantomData,
539        }
540    }
541
542    /// Get mask for bitfield, the mask is unshifted and at offset 0
543    ///
544    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead,ValueTypeWrite, T, A>::get()`] to
545    /// extract a bitfield value.
546    #[inline(always)]
547    #[must_use]
548    pub fn mask(&self) -> T::DataType {
549        T::DataType::cast_from(MASK)
550    }
551
552    /// Get offset of bitfield in containing register
553    ///
554    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead,ValueTypeWrite, T, A>::get()`] to
555    /// extract a bitfield value.
556    #[inline(always)]
557    #[must_use]
558    pub const fn offset(&self) -> usize {
559        START_OFFSET + (self.index * DIM_INCREMENT) as usize
560    }
561}
562
563impl<
564    const START_OFFSET: usize,
565    const MASK: u64,
566    const DIM: u8,
567    const DIM_INCREMENT: u8,
568    ValueTypeRead,
569    ValueTypeWrite,
570    T,
571    A,
572> RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead, ValueTypeWrite, T, A>
573where
574    T: RegSpec,
575    A: Read,
576    ValueTypeRead: CastFrom<u64>,
577{
578    /// Extract bitfield from read register value
579    #[inline(always)]
580    pub fn get(&self) -> ValueTypeRead {
581        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
582        let filtered: T::DataType = (self.data.data >> offset) & T::DataType::cast_from(MASK);
583        ValueTypeRead::cast_from(filtered.into())
584    }
585}
586
587impl<
588    const START_OFFSET: usize,
589    const MASK: u64,
590    const DIM: u8,
591    const DIM_INCREMENT: u8,
592    ValueTypeRead,
593    ValueTypeWrite,
594    T,
595    A,
596> RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead, ValueTypeWrite, T, A>
597where
598    T: RegSpec,
599    A: Write,
600    u64: From<ValueTypeWrite>,
601{
602    /// Prepare bitfield value that could be written to register
603    ///
604    /// # Example
605    /// ```rust,ignore
606    /// // example with generic names
607    /// // get an instance by reading
608    /// let values = TIMER.bitfield_reg().read();
609    /// // or by starting with a known value
610    /// let value = timer::BitfieldReg::new(0);
611    /// // or by starting with the default
612    /// let value = timer::BitfieldReg::default();
613    ///
614    /// // set bitfields
615    /// let value = value
616    ///     // set numeric bitfield
617    ///     .bitfieldw()
618    ///     .set(0x55)
619    ///     // set enumerated bitfield with enumeration
620    ///     .bitfieldenumerated()
621    ///     .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0)
622    ///     // set enumerated bitfield from integer
623    ///     .bitfieldenumerated()
624    ///     .set(1.into());
625    ///
626    /// // up until now no hardware change has taken place, do that now by writing
627    /// TIMER.bitfield_reg().write(value);
628    /// ```
629    #[inline(always)]
630    #[must_use]
631    pub fn set(mut self, value: ValueTypeWrite) -> RegValueT<T> {
632        let mask = T::DataType::cast_from(MASK);
633        let value: T::DataType = T::DataType::cast_from(Into::<u64>::into(value)) & mask;
634        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
635        let masked_offset: T::DataType = mask << offset;
636        self.data.mask |= masked_offset;
637        self.data.data &= !masked_offset;
638        self.data.data |= value << offset;
639        self.data
640    }
641}
642
643/// Proxy struct for boolean bitfields
644pub struct RegisterFieldBool<
645    const START_OFFSET: usize,
646    const DIM: u8,
647    const DIM_INCREMENT: u8,
648    T,
649    A,
650> where
651    T: RegSpec,
652    A: Access,
653{
654    data: RegValueT<T>,
655    index: u8,
656    marker: PhantomData<A>,
657}
658
659impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
660    RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
661where
662    T: RegSpec,
663    A: Read,
664{
665    /// Extract bitfield from read register value
666    #[inline(always)]
667    pub fn get(&self) -> bool {
668        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
669        let filtered = (self.data.data.into() >> offset) & 1;
670        filtered == 1
671    }
672}
673
674impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
675    RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
676where
677    T: RegSpec,
678    A: Write,
679{
680    /// Prepare bitfield value to be written to register
681    ///
682    /// # Example
683    /// ```rust,ignore
684    /// // example with generic names
685    /// // get an instance by reading
686    /// let values = TIMER.bitfield_reg().read();
687    /// // or by starting with a known value
688    /// let value = timer::BitfieldReg::new(0);
689    /// // or by starting with the default
690    /// let value = timer::BitfieldReg::default();
691    ///
692    /// // set bitfield
693    /// let value = value
694    ///     .boolrw()
695    ///     .set(true);
696    ///
697    /// // up until now no hardware change has taken place, do that now by writing
698    /// TIMER.bitfield_reg().write(value);
699    /// ```
700    #[inline(always)]
701    #[must_use]
702    pub fn set(mut self, value: bool) -> RegValueT<T> {
703        let value: T::DataType = if value {
704            T::DataType::cast_from(1u64)
705        } else {
706            T::DataType::cast_from(0u64)
707        };
708        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
709        let masked_offset = T::DataType::cast_from(0x1u64) << offset;
710        self.data.mask |= masked_offset;
711        self.data.data &= !masked_offset;
712        self.data.data |= value << offset;
713        self.data
714    }
715}
716
717impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
718    RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
719where
720    T: RegSpec,
721    A: Access,
722{
723    #[inline(always)]
724    #[allow(dead_code)]
725    pub(crate) fn from_register(data: RegValueT<T>, index: u8) -> Self {
726        Self {
727            data,
728            index,
729            marker: PhantomData,
730        }
731    }
732
733    /// Get mask for bitfield, the mask is unshifted and at offset 0
734    ///
735    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
736    /// extract a bitfield value.
737    #[inline(always)]
738    #[must_use]
739    pub fn mask(&self) -> T::DataType {
740        T::DataType::cast_from(1)
741    }
742
743    /// Get offset of bitfield in containing register
744    ///
745    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
746    /// extract a bitfield value.
747    #[inline(always)]
748    #[must_use]
749    pub const fn offset(&self) -> usize {
750        START_OFFSET + (self.index * DIM_INCREMENT) as usize
751    }
752}
753
754/// An array of identical register clusters.
755pub struct ClusterRegisterArray<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> {
756    _t: ::core::marker::PhantomData<T>,
757}
758
759impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize>
760    ClusterRegisterArray<T, DIM, DIM_INCREMENT>
761{
762    /// Returns the number of register blocks in the cluster.
763    #[inline(always)]
764    pub const fn len(&self) -> usize {
765        DIM
766    }
767
768    /// Returns whether the cluster is empty (DIM == 0).
769    #[inline(always)]
770    pub const fn is_empty(&self) -> bool {
771        DIM == 0
772    }
773
774    /// Returns an iterator over the elements of this cluster.
775    #[inline(always)]
776    pub fn iter(&self) -> impl ::core::iter::ExactSizeIterator<Item = &T> {
777        self.into_iter()
778    }
779
780    /// Returns the cluster element with the specified index.
781    ///
782    /// Panics if the index is out of bounds.
783    #[inline]
784    pub const fn get(&self, index: usize) -> &T {
785        assert!(index < DIM);
786        unsafe { self.get_unchecked(index) }
787    }
788
789    /// Returns the cluster element with the specified index.
790    ///
791    /// # Safety
792    ///
793    /// `index` must be less than `DIM`.
794    #[inline(always)]
795    pub const unsafe fn get_unchecked(&self, index: usize) -> &T {
796        &*(self.as_ptr().add(index * DIM_INCREMENT) as *const _)
797    }
798
799    #[allow(dead_code)]
800    #[inline(always)]
801    pub(crate) const unsafe fn from_ptr(ptr: *mut u8) -> &'static Self {
802        &*(ptr as *const Self)
803    }
804
805    #[inline(always)]
806    const fn as_ptr(&self) -> *mut u8 {
807        self as *const _ as *mut _
808    }
809}
810
811impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ::core::ops::Index<usize>
812    for ClusterRegisterArray<T, DIM, DIM_INCREMENT>
813{
814    type Output = T;
815
816    #[inline(always)]
817    fn index(&self, index: usize) -> &T {
818        self.get(index)
819    }
820}
821
822impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> IntoIterator
823    for &'a ClusterRegisterArray<T, DIM, DIM_INCREMENT>
824{
825    type Item = &'a T;
826    type IntoIter = ClusterRegisterArrayIterator<'a, T, DIM, DIM_INCREMENT>;
827
828    #[inline(always)]
829    fn into_iter(self) -> Self::IntoIter {
830        ClusterRegisterArrayIterator {
831            array: self,
832            index: 0,
833        }
834    }
835}
836
837pub struct ClusterRegisterArrayIterator<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize>
838{
839    array: &'a ClusterRegisterArray<T, DIM, DIM_INCREMENT>,
840    index: usize,
841}
842
843impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> Iterator
844    for ClusterRegisterArrayIterator<'a, T, DIM, DIM_INCREMENT>
845{
846    type Item = &'a T;
847    #[inline(always)]
848    fn next(&mut self) -> Option<&'a T> {
849        if self.index < self.array.len() {
850            let result = &self.array[self.index];
851            self.index += 1;
852            Some(result)
853        } else {
854            None
855        }
856    }
857
858    #[inline(always)]
859    fn size_hint(&self) -> (usize, Option<usize>) {
860        let len = self.array.len() - self.index;
861        (len, Some(len))
862    }
863}
864
865impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ExactSizeIterator
866    for ClusterRegisterArrayIterator<'_, T, DIM, DIM_INCREMENT>
867{
868}