n64_pac/
si.rs

1//! RCP - Serial Interface
2
3use core::ops::Deref;
4use proc_bitfield::bitfield;
5use crate::RW;
6
7/// A wrapper around a mutable reference to the Serial Interface's memory mapped registers.
8/// 
9/// See [`SerialInterface::new()`] for usage details.
10pub struct SerialInterface {
11    r: &'static mut RegisterBlock,
12}
13
14#[repr(C)]
15pub struct RegisterBlock {
16    pub dram_addr: RW<u32>,
17    pub pif_ad_rd64b: RW<u32>,
18    pub pif_ad_wr4b: RW<u32>,
19    /// Seemingly unused; more research required
20    _spacer: u32,
21    pub pif_ad_wr64b: RW<u32>,
22    pub pif_ad_rd4b: RW<u32>,
23    pub status: RW<StatusReg>,
24}
25impl SerialInterface {
26    /// Creates a new wrapped mutable reference to the Serial Interface's memory mapped registers, starting at `0xA4800000`.
27    /// 
28    /// Developers are recommended to use [`Hardware::take()`][crate::Hardware::take()] instead.
29    /// But for unrestricted, unsafe, access, this struct provides a method-based version to the
30    /// static functions available at the [module][crate::si] level.
31    /// 
32    /// # Safety
33    /// This provides unrestricted access to memory mapped registers. Data races _could_ occur if writing
34    /// to a register in both regular code and inside interrupt handlers.
35    /// 
36    /// This is especially problematic if performing a read-modify-write operation; an interrupt
37    /// could trigger between reading a register, and writing a modified value back to the same
38    /// register. Thus anything written to that register inside the interrupt, would only apply for
39    /// a short moment before being overwritten.
40    #[inline(always)]
41    pub unsafe fn new() -> Self { Self {
42        r: &mut *(0xA4800000 as *mut RegisterBlock)
43    }}
44}
45impl Deref for SerialInterface {
46    type Target = RegisterBlock;
47    
48    #[inline(always)]
49    fn deref(&self) -> &Self::Target {
50        self.r
51    }
52}
53
54regfn_rw!(SerialInterface, dram_addr, DRAM_ADDR, u32);
55regfn_rw!(SerialInterface, pif_ad_rd64b, PIF_AD_RD64B, u32);
56regfn_rw!(SerialInterface, pif_ad_wr4b, PIF_AD_WR4B, u32);
57regfn_rw!(SerialInterface, pif_ad_wr64b, PIF_AD_WR64B, u32);
58regfn_rw!(SerialInterface, pif_ad_rd4b, PIF_AD_RD4B, u32);
59regfn_rw!(SerialInterface, status, STATUS, StatusReg);
60
61
62bitfield! {
63    #[derive(Copy, Clone, PartialEq, Eq)]
64    pub struct StatusReg(pub u32): Debug {
65        pub whole_register: u32 [wo] @ ..,
66        
67        pub dma_busy: bool [ro] @ 0,
68        pub io_busy: bool [ro] @ 1,
69        pub read_pending: bool [ro] @ 2,
70        pub dma_error: bool [ro] @ 3,
71        pub pch_state: u8 [ro] @ 4..=7,
72        pub dma_state: u8 [ro] @ 8..=11,
73        
74        /// Mirror of the SI interrupt flag from the `MI_INTERRUPT` register.
75        /// 
76        /// Writing any value to the `SI_STATUS` register clears the flag across all three locations
77        /// (this bit, `MI_INTERRUPT`, and the RCP Interrupt Cause register).
78        /// 
79        /// SI Interrupts occur when a DMA write finishes.
80        pub interrupt: bool @ 12,
81    }
82}