use crate::filter::{FilterExtendedId, FilterStandardId};
use crate::message::{rx, tx, TxEvent};
use core::mem::MaybeUninit;
use generic_array::{
typenum::{consts::*, IsLessOrEqual, LeEq, Same},
ArrayLength, GenericArray,
};
use vcell::VolatileCell;
pub trait Capacities {
type StandardFilters: LimitedArrayLength<VolatileCell<FilterStandardId>, U128>;
type ExtendedFilters: LimitedArrayLength<VolatileCell<FilterExtendedId>, U64>;
type RxBufferMessage: rx::AnyMessage;
type DedicatedRxBuffers: LimitedArrayLength<VolatileCell<Self::RxBufferMessage>, U64>;
type RxFifo0Message: rx::AnyMessage;
type RxFifo0: LimitedArrayLength<VolatileCell<Self::RxFifo0Message>, U64>;
type RxFifo1Message: rx::AnyMessage;
type RxFifo1: LimitedArrayLength<VolatileCell<Self::RxFifo1Message>, U64>;
type TxMessage: tx::AnyMessage;
type TxBuffers: LimitedArrayLength<VolatileCell<Self::TxMessage>, U32>;
type DedicatedTxBuffers: LimitedArrayLength<VolatileCell<Self::TxMessage>, Self::TxBuffers>;
type TxEventFifo: LimitedArrayLength<VolatileCell<TxEvent>, U32>;
}
pub trait LimitedArrayLength<T, MaxLength>: ArrayLength<T> {}
impl<T, N, MaxLength> LimitedArrayLength<T, MaxLength> for N
where
N: ArrayLength<T> + IsLessOrEqual<MaxLength>,
LeEq<N, MaxLength>: Same<True>,
{
}
#[repr(C)]
pub(super) struct SharedMemoryInner<C: Capacities> {
pub(super) filters_standard: GenericArray<VolatileCell<FilterStandardId>, C::StandardFilters>,
pub(super) filters_extended: GenericArray<VolatileCell<FilterExtendedId>, C::ExtendedFilters>,
pub(super) rx_fifo_0: GenericArray<VolatileCell<C::RxFifo0Message>, C::RxFifo0>,
pub(super) rx_fifo_1: GenericArray<VolatileCell<C::RxFifo1Message>, C::RxFifo1>,
pub(super) rx_dedicated_buffers:
GenericArray<VolatileCell<C::RxBufferMessage>, C::DedicatedRxBuffers>,
pub(super) tx_event_fifo: GenericArray<VolatileCell<TxEvent>, C::TxEventFifo>,
pub(super) tx_buffers: GenericArray<VolatileCell<C::TxMessage>, C::TxBuffers>,
}
pub struct SharedMemory<C: Capacities>(MaybeUninit<SharedMemoryInner<C>>);
impl<C: Capacities> SharedMemory<C> {
pub(super) fn init(&mut self) -> &mut SharedMemoryInner<C> {
self.0 = MaybeUninit::zeroed();
unsafe { self.0.assume_init_mut() }
}
pub const fn new() -> Self {
Self(MaybeUninit::uninit())
}
pub(crate) fn is_addressable(&self, eligible_message_ram_start: *const ()) -> bool {
let eligible_message_ram_start = eligible_message_ram_start as usize;
let start = self as *const _ as usize;
let end_exclusive = start + core::mem::size_of::<Self>();
eligible_message_ram_start <= start && end_exclusive - eligible_message_ram_start <= 1 << 16
}
}
impl<C: Capacities> Default for SharedMemory<C> {
fn default() -> Self {
Self::new()
}
}