#![allow(clippy::missing_safety_doc)]
#![allow(clippy::identity_op)]
#![allow(clippy::unnecessary_cast)]
#![allow(clippy::erasing_op)]
#[doc = "Inter-Processor Communication. Four bidirectional channels, each carrying 8 status bits with independent enable/mask/set/clear, plus four 32-bit shared message slots for short messages."]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Ipc {
ptr: *mut u8,
}
unsafe impl Send for Ipc {}
unsafe impl Sync for Ipc {}
impl Ipc {
#[inline(always)]
pub const unsafe fn from_ptr(ptr: *mut ()) -> Self {
Self { ptr: ptr as _ }
}
#[inline(always)]
pub const fn as_ptr(&self) -> *mut () {
self.ptr as _
}
#[doc = "IPC control register. Per-channel TX/RX core ID routing, interrupt enables, auto-update mode and configuration lock."]
#[inline(always)]
pub const fn ctlr(self) -> crate::common::Reg<regs::Ctlr, crate::common::RW> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x0usize) as _) }
}
#[doc = "Per-channel interrupt status (read-only summary; bits set when channel state matches the configured trigger)."]
#[inline(always)]
pub const fn isr(self) -> crate::common::Reg<regs::Channels, crate::common::R> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x04usize) as _) }
}
#[doc = "Per-channel interrupt mask status (read-only; bit set means channel is currently raising an interrupt request to its routed core)."]
#[inline(always)]
pub const fn ism(self) -> crate::common::Reg<regs::Channels, crate::common::R> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x08usize) as _) }
}
#[doc = "Per-channel status-bit interrupt enable. Each enabled bit produces TX or RX interrupts based on the value in STS."]
#[inline(always)]
pub const fn ena(self) -> crate::common::Reg<regs::Channels, crate::common::RW> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x10usize) as _) }
}
#[doc = "Per-channel status register. Bit value 1 may raise an RX interrupt; bit value 0 may raise a TX interrupt (subject to ENA / IER configuration)."]
#[inline(always)]
pub const fn sts(self) -> crate::common::Reg<regs::Channels, crate::common::RW> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x14usize) as _) }
}
#[doc = "Per-channel status set register. Writing 1 sets the corresponding bit in STS (and in ENA when AUTOEN is on)."]
#[inline(always)]
pub const fn set(self) -> crate::common::Reg<regs::Channels, crate::common::W> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x18usize) as _) }
}
#[doc = "Per-channel status clear register. Writing 1 clears the corresponding bit in STS."]
#[inline(always)]
pub const fn clr(self) -> crate::common::Reg<regs::Channels, crate::common::W> {
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x1cusize) as _) }
}
#[doc = "32-bit inline message slot. Four slots are available to carry short messages without touching shared SRAM."]
#[inline(always)]
pub const fn msg(self, n: usize) -> crate::common::Reg<regs::Msg, crate::common::RW> {
assert!(n < 4usize);
unsafe { crate::common::Reg::from_ptr(self.ptr.add(0x20usize + n * 4usize) as _) }
}
}
pub mod regs {
#[doc = "Per-channel 8-bit value (used by ISR / ISM / ENA / STS / SET / CLR). Channel n occupies bits 8n..8n+7."]
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Channels(pub u32);
impl Channels {
#[doc = "Channel byte. Each of the 8 bits is an independent status / enable / set / clear flag."]
#[inline(always)]
pub const fn ch(&self, n: usize) -> u8 {
assert!(n < 4usize);
let offs = 0usize + n * 8usize;
let val = (self.0 >> offs) & 0xff;
val as u8
}
#[doc = "Channel byte. Each of the 8 bits is an independent status / enable / set / clear flag."]
#[inline(always)]
pub fn set_ch(&mut self, n: usize, val: u8) {
assert!(n < 4usize);
let offs = 0usize + n * 8usize;
self.0 = (self.0 & !(0xff << offs)) | (((val as u32) & 0xff) << offs);
}
}
impl Default for Channels {
#[inline(always)]
fn default() -> Channels {
Channels(0)
}
}
#[doc = "IPC control register. Each of the four channels occupies 8 bits (channel n at bits 8n..8n+7)."]
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Ctlr(pub u32);
impl Ctlr {
#[doc = "Sender core ID. 0=route TX interrupt to hart 0 (V3F), 1=route to hart 1 (V5F)."]
#[inline(always)]
pub const fn tx_cid(&self, n: usize) -> bool {
assert!(n < 4usize);
let offs = 0usize + n * 8usize;
let val = (self.0 >> offs) & 0x01;
val != 0
}
#[doc = "Sender core ID. 0=route TX interrupt to hart 0 (V3F), 1=route to hart 1 (V5F)."]
#[inline(always)]
pub fn set_tx_cid(&mut self, n: usize, val: bool) {
assert!(n < 4usize);
let offs = 0usize + n * 8usize;
self.0 = (self.0 & !(0x01 << offs)) | (((val as u32) & 0x01) << offs);
}
#[doc = "Receiver core ID. 0=route RX interrupt to hart 0, 1=route to hart 1."]
#[inline(always)]
pub const fn rx_cid(&self, n: usize) -> bool {
assert!(n < 4usize);
let offs = 2usize + n * 8usize;
let val = (self.0 >> offs) & 0x01;
val != 0
}
#[doc = "Receiver core ID. 0=route RX interrupt to hart 0, 1=route to hart 1."]
#[inline(always)]
pub fn set_rx_cid(&mut self, n: usize, val: bool) {
assert!(n < 4usize);
let offs = 2usize + n * 8usize;
self.0 = (self.0 & !(0x01 << offs)) | (((val as u32) & 0x01) << offs);
}
#[doc = "TX interrupt enable."]
#[inline(always)]
pub const fn tx_ier(&self, n: usize) -> bool {
assert!(n < 4usize);
let offs = 4usize + n * 8usize;
let val = (self.0 >> offs) & 0x01;
val != 0
}
#[doc = "TX interrupt enable."]
#[inline(always)]
pub fn set_tx_ier(&mut self, n: usize, val: bool) {
assert!(n < 4usize);
let offs = 4usize + n * 8usize;
self.0 = (self.0 & !(0x01 << offs)) | (((val as u32) & 0x01) << offs);
}
#[doc = "RX interrupt enable."]
#[inline(always)]
pub const fn rx_ier(&self, n: usize) -> bool {
assert!(n < 4usize);
let offs = 5usize + n * 8usize;
let val = (self.0 >> offs) & 0x01;
val != 0
}
#[doc = "RX interrupt enable."]
#[inline(always)]
pub fn set_rx_ier(&mut self, n: usize, val: bool) {
assert!(n < 4usize);
let offs = 5usize + n * 8usize;
self.0 = (self.0 & !(0x01 << offs)) | (((val as u32) & 0x01) << offs);
}
#[doc = "Status-bit auto-update. When set, writing to STS / SET also updates ENA to the same value so the interrupt fires immediately."]
#[inline(always)]
pub const fn autoen(&self, n: usize) -> bool {
assert!(n < 4usize);
let offs = 6usize + n * 8usize;
let val = (self.0 >> offs) & 0x01;
val != 0
}
#[doc = "Status-bit auto-update. When set, writing to STS / SET also updates ENA to the same value so the interrupt fires immediately."]
#[inline(always)]
pub fn set_autoen(&mut self, n: usize, val: bool) {
assert!(n < 4usize);
let offs = 6usize + n * 8usize;
self.0 = (self.0 & !(0x01 << offs)) | (((val as u32) & 0x01) << offs);
}
#[doc = "Channel configuration lock. Write 1 to freeze the channel's other control bits until reset."]
#[inline(always)]
pub const fn lock(&self, n: usize) -> bool {
assert!(n < 4usize);
let offs = 7usize + n * 8usize;
let val = (self.0 >> offs) & 0x01;
val != 0
}
#[doc = "Channel configuration lock. Write 1 to freeze the channel's other control bits until reset."]
#[inline(always)]
pub fn set_lock(&mut self, n: usize, val: bool) {
assert!(n < 4usize);
let offs = 7usize + n * 8usize;
self.0 = (self.0 & !(0x01 << offs)) | (((val as u32) & 0x01) << offs);
}
}
impl Default for Ctlr {
#[inline(always)]
fn default() -> Ctlr {
Ctlr(0)
}
}
#[doc = "32-bit inline message register."]
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Msg(pub u32);
impl Msg {
#[doc = "32-bit message value."]
#[inline(always)]
pub const fn data(&self) -> u32 {
let val = (self.0 >> 0usize) & 0xffff_ffff;
val as u32
}
#[doc = "32-bit message value."]
#[inline(always)]
pub fn set_data(&mut self, val: u32) {
self.0 = (self.0 & !(0xffff_ffff << 0usize)) | (((val as u32) & 0xffff_ffff) << 0usize);
}
}
impl Default for Msg {
#[inline(always)]
fn default() -> Msg {
Msg(0)
}
}
}