ra6e1_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.20.00, with svd2pac 0.6.0 on Thu, 24 Jul 2025 04:50:30 +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 unsafe {
294 #[cfg(feature = "tracing")]
295 let val = {
296 let mut buf: u64 = 0x0;
297 tracing::READ_FN.with(|rf| {
298 if let Some(rf) = rf.get() {
299 buf = rf(self.addr(), std::mem::size_of::<T::DataType>());
300 } else {
301 #[cfg(not(feature = "tracing_dummy"))]
302 panic!(
303 "Please, provide an handler for read with tracing::set_read_fn(callback);"
304 );
305 }
306 });
307 T::DataType::cast_from(buf)
308 };
309 #[cfg(not(feature = "tracing"))]
310 let val = self.ptr().read_volatile();
311 RegValueT::<T>::new(val)
312 }
313 }
314}
315
316impl<T, A> Reg<T, A>
317where
318 T: RegSpec,
319 A: Write,
320{
321 /// Write register value back to register
322 ///
323 /// # Arguments
324 ///
325 /// * `reg_value` - A string slice that holds the name of the person
326 ///
327 /// # Safety
328 /// Write operation could cause undefined behavior for some peripheral. Developers shall read the device user manual.
329 /// Register is Send and Sync to allow complete freedom. Developers are responsible of proper use in interrupt and thread.
330 ///
331 /// # Example
332 /// ```rust,ignore
333 /// // example with generic names
334 /// // write with a previously read value
335 /// let reg = unsafe { TIMER.bitfield_reg().read() };
336 /// // or start with a known value
337 /// let reg = timer::BitfieldReg::new(0).bitfieldw().set(0x55);
338 /// // or start with the register default
339 /// let reg = timer::BitfieldReg::default();
340 ///
341 /// let reg = reg.bitfieldrw().set(0x77);
342 ///
343 /// // no change has taken place to the register due to `set` calls - do that now by writing back the result
344 /// unsafe { TIMER.bitfield_reg().write(reg) }
345 /// ```
346 /// See also: [`Reg<T, A>::init`] which provides the default value to a closure
347 #[inline(always)]
348 pub unsafe fn write(&self, reg_value: RegValueT<T>) {
349 unsafe {
350 #[cfg(feature = "tracing")]
351 tracing::WRITE_FN.with(|wf| {
352 if let Some(wf) = wf.get() {
353 wf(
354 self.addr(),
355 std::mem::size_of::<T::DataType>(),
356 reg_value.data.into(),
357 )
358 } else {
359 #[cfg(not(feature = "tracing_dummy"))]
360 panic!(
361 "Please, provide an handler for read with tracing::set_read_fn(callback);"
362 );
363 }
364 });
365 #[cfg(not(feature = "tracing"))]
366 self.ptr().write_volatile(reg_value.data);
367 }
368 }
369
370 /// Write an arbitrary integer to register
371 ///
372 /// Use this function when e.g. loading data to be written from a config-page.
373 /// For normal use prefer either [`Reg<T, A>::write`] if the value was read before, or [`Reg<T, A>::init`],
374 /// both of which provide some restrictions available register fields, enums, etc.
375 ///
376 /// # Arguments
377 ///
378 /// * `value` - The unchecked value to be written to the register
379 ///
380 /// # Safety
381 ///
382 /// Write operation could cause undefined behavior for some peripheral. Developers shall read the device user manual.
383 /// Register is Send and Sync to allow complete freedom. Developers are responsible of proper use in interrupt and thread.
384 ///
385 /// # Example
386 /// ```rust,ignore
387 /// // example with generic names
388 /// unsafe { TIMER.bitfield_reg().write_raw(0xdead) }
389 /// ```
390 /// See also [`Reg<T, A>::init`] and [`Reg<T, A>::write`] both of which are the safe, preferred functions.
391 #[inline(always)]
392 pub unsafe fn write_raw(&self, value: T::DataType) {
393 unsafe {
394 #[cfg(feature = "tracing")]
395 tracing::WRITE_FN.with(|wf| {
396 if let Some(wf) = wf.get() {
397 wf(
398 self.addr(),
399 std::mem::size_of::<T::DataType>(),
400 value.into(),
401 )
402 } else {
403 #[cfg(not(feature = "tracing_dummy"))]
404 panic!(
405 "Please, provide an handler for read with tracing::set_read_fn(callback);"
406 );
407 }
408 });
409 #[cfg(not(feature = "tracing"))]
410 self.ptr().write_volatile(value);
411 }
412 }
413}
414
415impl<T, A> Reg<T, A>
416where
417 T: RegSpec,
418 A: Write,
419 RegValueT<T>: Default,
420{
421 /// Write register with register value built from default register value
422 ///
423 /// # Arguments
424 ///
425 /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset.
426 ///
427 /// # Safety
428 /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
429 /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
430 ///
431 /// # Example
432 /// ```rust,ignore
433 /// // example with generic names
434 /// TIMER
435 /// .bitfield_reg()
436 /// .init(|r| r.bitfieldw().set(0b1010).boolw().set(true));
437 /// ```
438 #[inline(always)]
439 /// Write value computed by closure that receive as input the reset value of register
440 pub unsafe fn init(&self, f: impl FnOnce(RegValueT<T>) -> RegValueT<T>) {
441 unsafe {
442 let val = RegValueT::<T>::default();
443 let res = f(val);
444 self.write(res);
445 }
446 }
447}
448
449impl<T, A> Reg<T, A>
450where
451 T: RegSpec,
452 A: Read + Write,
453{
454 /// Read/modify/write register
455 ///
456 /// # Arguments
457 ///
458 /// * `f` - Closure that receive as input a register value read from register. The result of the closure
459 /// is written back to the register.
460 ///
461 /// # Safety
462 /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
463 /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
464 ///
465 /// # Example
466 /// ```rust,ignore
467 /// // example with generic names
468 /// TIMER
469 /// .bitfield_reg()
470 /// .modify(|r| r.boolrw().set(!r.boolrw().get()));
471 /// ```
472 #[inline(always)]
473 pub unsafe fn modify(&self, f: impl FnOnce(RegValueT<T>) -> RegValueT<T>) {
474 unsafe {
475 let val = self.read();
476 let res = f(val);
477 self.write(res);
478 }
479 }
480}
481
482/// Proxy struct for enumerated bitfields
483#[repr(transparent)]
484#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
485pub struct EnumBitfieldStruct<Q: RegNumberT, T>(pub Q, PhantomData<T>);
486
487impl<Q: RegNumberT, T> EnumBitfieldStruct<Q, T> {
488 pub const fn new(value: Q) -> Self {
489 Self(value, PhantomData)
490 }
491}
492
493impl<Q: RegNumberT, T> From<EnumBitfieldStruct<Q, T>> for u64 {
494 #[inline(always)]
495 fn from(value: EnumBitfieldStruct<Q, T>) -> Self {
496 value.0.into()
497 }
498}
499impl<Q: RegNumberT, T> CastFrom<u64> for EnumBitfieldStruct<Q, T> {
500 #[inline(always)]
501 fn cast_from(val: u64) -> Self {
502 Self(Q::cast_from(val), PhantomData)
503 }
504}
505
506impl<Q: RegNumberT, T> From<Q> for EnumBitfieldStruct<Q, T> {
507 #[inline(always)]
508 fn from(value: Q) -> Self {
509 Self(value, PhantomData)
510 }
511}
512
513/// Proxy struct for numeric bitfields
514pub struct RegisterField<
515 const START_OFFSET: usize,
516 const MASK: u64,
517 const DIM: u8,
518 const DIM_INCREMENT: u8,
519 ValueTypeRead,
520 ValueTypeWrite,
521 T,
522 A,
523> where
524 T: RegSpec,
525 A: Access,
526{
527 data: RegValueT<T>,
528 index: u8,
529 marker: PhantomData<(ValueTypeRead, ValueTypeWrite, A)>,
530}
531
532impl<
533 const START_OFFSET: usize,
534 const MASK: u64,
535 const DIM: u8,
536 const DIM_INCREMENT: u8,
537 ValueTypeRead,
538 ValueTypeWrite,
539 T,
540 A,
541> RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead, ValueTypeWrite, T, A>
542where
543 T: RegSpec,
544 A: Access,
545{
546 #[allow(dead_code)]
547 #[inline(always)]
548 pub(crate) fn from_register(data: RegValueT<T>, index: u8) -> Self {
549 Self {
550 data,
551 index,
552 marker: PhantomData,
553 }
554 }
555
556 /// Get mask for bitfield, the mask is unshifted and at offset 0
557 ///
558 /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead,ValueTypeWrite, T, A>::get()`] to
559 /// extract a bitfield value.
560 #[inline(always)]
561 #[must_use]
562 pub fn mask(&self) -> T::DataType {
563 T::DataType::cast_from(MASK)
564 }
565
566 /// Get offset of bitfield in containing register
567 ///
568 /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead,ValueTypeWrite, T, A>::get()`] to
569 /// extract a bitfield value.
570 #[inline(always)]
571 #[must_use]
572 pub const fn offset(&self) -> usize {
573 START_OFFSET + (self.index * DIM_INCREMENT) as usize
574 }
575}
576
577impl<
578 const START_OFFSET: usize,
579 const MASK: u64,
580 const DIM: u8,
581 const DIM_INCREMENT: u8,
582 ValueTypeRead,
583 ValueTypeWrite,
584 T,
585 A,
586> RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead, ValueTypeWrite, T, A>
587where
588 T: RegSpec,
589 A: Read,
590 ValueTypeRead: CastFrom<u64>,
591{
592 /// Extract bitfield from read register value
593 #[inline(always)]
594 pub fn get(&self) -> ValueTypeRead {
595 let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
596 let filtered: T::DataType = (self.data.data >> offset) & T::DataType::cast_from(MASK);
597 ValueTypeRead::cast_from(filtered.into())
598 }
599}
600
601impl<
602 const START_OFFSET: usize,
603 const MASK: u64,
604 const DIM: u8,
605 const DIM_INCREMENT: u8,
606 ValueTypeRead,
607 ValueTypeWrite,
608 T,
609 A,
610> RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueTypeRead, ValueTypeWrite, T, A>
611where
612 T: RegSpec,
613 A: Write,
614 u64: From<ValueTypeWrite>,
615{
616 /// Prepare bitfield value that could be written to register
617 ///
618 /// # Example
619 /// ```rust,ignore
620 /// // example with generic names
621 /// // get an instance by reading
622 /// let values = TIMER.bitfield_reg().read();
623 /// // or by starting with a known value
624 /// let value = timer::BitfieldReg::new(0);
625 /// // or by starting with the default
626 /// let value = timer::BitfieldReg::default();
627 ///
628 /// // set bitfields
629 /// let value = value
630 /// // set numeric bitfield
631 /// .bitfieldw()
632 /// .set(0x55)
633 /// // set enumerated bitfield with enumeration
634 /// .bitfieldenumerated()
635 /// .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0)
636 /// // set enumerated bitfield from integer
637 /// .bitfieldenumerated()
638 /// .set(1.into());
639 ///
640 /// // up until now no hardware change has taken place, do that now by writing
641 /// TIMER.bitfield_reg().write(value);
642 /// ```
643 #[inline(always)]
644 #[must_use]
645 pub fn set(mut self, value: ValueTypeWrite) -> RegValueT<T> {
646 let mask = T::DataType::cast_from(MASK);
647 let value: T::DataType = T::DataType::cast_from(Into::<u64>::into(value)) & mask;
648 let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
649 let masked_offset: T::DataType = mask << offset;
650 self.data.mask |= masked_offset;
651 self.data.data &= !masked_offset;
652 self.data.data |= value << offset;
653 self.data
654 }
655}
656
657/// Proxy struct for boolean bitfields
658pub struct RegisterFieldBool<
659 const START_OFFSET: usize,
660 const DIM: u8,
661 const DIM_INCREMENT: u8,
662 T,
663 A,
664> where
665 T: RegSpec,
666 A: Access,
667{
668 data: RegValueT<T>,
669 index: u8,
670 marker: PhantomData<A>,
671}
672
673impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
674 RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
675where
676 T: RegSpec,
677 A: Read,
678{
679 /// Extract bitfield from read register value
680 #[inline(always)]
681 pub fn get(&self) -> bool {
682 let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
683 let filtered = (self.data.data.into() >> offset) & 1;
684 filtered == 1
685 }
686}
687
688impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
689 RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
690where
691 T: RegSpec,
692 A: Write,
693{
694 /// Prepare bitfield value to be written to register
695 ///
696 /// # Example
697 /// ```rust,ignore
698 /// // example with generic names
699 /// // get an instance by reading
700 /// let values = TIMER.bitfield_reg().read();
701 /// // or by starting with a known value
702 /// let value = timer::BitfieldReg::new(0);
703 /// // or by starting with the default
704 /// let value = timer::BitfieldReg::default();
705 ///
706 /// // set bitfield
707 /// let value = value
708 /// .boolrw()
709 /// .set(true);
710 ///
711 /// // up until now no hardware change has taken place, do that now by writing
712 /// TIMER.bitfield_reg().write(value);
713 /// ```
714 #[inline(always)]
715 #[must_use]
716 pub fn set(mut self, value: bool) -> RegValueT<T> {
717 let value: T::DataType = if value {
718 T::DataType::cast_from(1u64)
719 } else {
720 T::DataType::cast_from(0u64)
721 };
722 let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
723 let masked_offset = T::DataType::cast_from(0x1u64) << offset;
724 self.data.mask |= masked_offset;
725 self.data.data &= !masked_offset;
726 self.data.data |= value << offset;
727 self.data
728 }
729}
730
731impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
732 RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
733where
734 T: RegSpec,
735 A: Access,
736{
737 #[inline(always)]
738 #[allow(dead_code)]
739 pub(crate) fn from_register(data: RegValueT<T>, index: u8) -> Self {
740 Self {
741 data,
742 index,
743 marker: PhantomData,
744 }
745 }
746
747 /// Get mask for bitfield, the mask is unshifted and at offset 0
748 ///
749 /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
750 /// extract a bitfield value.
751 #[inline(always)]
752 #[must_use]
753 pub fn mask(&self) -> T::DataType {
754 T::DataType::cast_from(1)
755 }
756
757 /// Get offset of bitfield in containing register
758 ///
759 /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
760 /// extract a bitfield value.
761 #[inline(always)]
762 #[must_use]
763 pub const fn offset(&self) -> usize {
764 START_OFFSET + (self.index * DIM_INCREMENT) as usize
765 }
766}
767
768/// An array of identical register clusters.
769pub struct ClusterRegisterArray<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> {
770 _t: ::core::marker::PhantomData<T>,
771}
772
773impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize>
774 ClusterRegisterArray<T, DIM, DIM_INCREMENT>
775{
776 /// Returns the number of register blocks in the cluster.
777 #[inline(always)]
778 pub const fn len(&self) -> usize {
779 DIM
780 }
781
782 /// Returns whether the cluster is empty (DIM == 0).
783 #[inline(always)]
784 pub const fn is_empty(&self) -> bool {
785 DIM == 0
786 }
787
788 /// Returns an iterator over the elements of this cluster.
789 #[inline(always)]
790 pub fn iter(&self) -> impl ::core::iter::ExactSizeIterator<Item = &T> {
791 self.into_iter()
792 }
793
794 /// Returns the cluster element with the specified index.
795 ///
796 /// Panics if the index is out of bounds.
797 #[inline]
798 pub const fn get(&self, index: usize) -> &T {
799 assert!(index < DIM);
800 unsafe { self.get_unchecked(index) }
801 }
802
803 /// Returns the cluster element with the specified index.
804 ///
805 /// # Safety
806 ///
807 /// `index` must be less than `DIM`.
808 #[inline(always)]
809 pub const unsafe fn get_unchecked(&self, index: usize) -> &T {
810 unsafe { &*(self.as_ptr().add(index * DIM_INCREMENT) as *const _) }
811 }
812
813 #[allow(dead_code)]
814 #[inline(always)]
815 pub(crate) const unsafe fn from_ptr(ptr: *mut u8) -> &'static Self {
816 unsafe { &*(ptr as *const Self) }
817 }
818
819 #[inline(always)]
820 const fn as_ptr(&self) -> *mut u8 {
821 self as *const _ as *mut _
822 }
823}
824
825impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ::core::ops::Index<usize>
826 for ClusterRegisterArray<T, DIM, DIM_INCREMENT>
827{
828 type Output = T;
829
830 #[inline(always)]
831 fn index(&self, index: usize) -> &T {
832 self.get(index)
833 }
834}
835
836impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> IntoIterator
837 for &'a ClusterRegisterArray<T, DIM, DIM_INCREMENT>
838{
839 type Item = &'a T;
840 type IntoIter = ClusterRegisterArrayIterator<'a, T, DIM, DIM_INCREMENT>;
841
842 #[inline(always)]
843 fn into_iter(self) -> Self::IntoIter {
844 ClusterRegisterArrayIterator {
845 array: self,
846 index: 0,
847 }
848 }
849}
850
851pub struct ClusterRegisterArrayIterator<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize>
852{
853 array: &'a ClusterRegisterArray<T, DIM, DIM_INCREMENT>,
854 index: usize,
855}
856
857impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> Iterator
858 for ClusterRegisterArrayIterator<'a, T, DIM, DIM_INCREMENT>
859{
860 type Item = &'a T;
861 #[inline(always)]
862 fn next(&mut self) -> Option<&'a T> {
863 if self.index < self.array.len() {
864 let result = &self.array[self.index];
865 self.index += 1;
866 Some(result)
867 } else {
868 None
869 }
870 }
871
872 #[inline(always)]
873 fn size_hint(&self) -> (usize, Option<usize>) {
874 let len = self.array.len() - self.index;
875 (len, Some(len))
876 }
877}
878
879impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ExactSizeIterator
880 for ClusterRegisterArrayIterator<'_, T, DIM, DIM_INCREMENT>
881{
882}