use crate::pac::icm::uasr::URAT_A;
use paste::paste;
use seq_macro::seq;
use bitflags::bitflags;
use crate::pac::icm::*;
use crate::typelevel::Sealed;
use core::marker::PhantomData;
pub use crate::icm::cfg::UALGO_A as icm_algorithm;
bitflags! {
pub struct RegionHashCompleted: u8 {
const R0 = 1;
const R1 = 2;
const R2 = 4;
const R3 = 8;
}
}
bitflags! {
pub struct RegionDigestMismatch: u8 {
const R0 = 1;
const R1 = 2;
const R2 = 4;
const R3 = 8;
}
}
bitflags! {
pub struct RegionBusError: u8 {
const R0 = 1;
const R1 = 2;
const R2 = 4;
const R3 = 8;
}
}
bitflags! {
pub struct RegionWrapConditionDetected: u8 {
const R0 = 1;
const R1 = 2;
const R2 = 4;
const R3 = 8;
}
}
bitflags! {
pub struct RegionEndConditionDetected: u8 {
const R0 = 1;
const R1 = 2;
const R2 = 4;
const R3 = 8;
}
}
bitflags! {
pub struct RegionStatusUpdatedDetected: u8 {
const R0 = 1;
const R1 = 2;
const R2 = 4;
const R3 = 8;
}
}
bitfield::bitfield! {
#[derive(Default)]
pub struct Interrupt(u32);
impl Debug;
u8;
get_rhc, _: 3, 0;
get_rdm, _: 7, 4;
get_rbe, _: 11, 8;
get_rwc, _: 15, 12;
get_rec, _: 19, 16;
get_rsu, _: 23, 20;
get_urad, _: 24, 24;
}
impl Interrupt {
#[inline]
pub fn get_rsu_int(&self) -> RegionStatusUpdatedDetected {
RegionStatusUpdatedDetected::from_bits_truncate(self.get_rsu())
}
#[inline]
pub fn get_rec_int(&self) -> RegionEndConditionDetected {
RegionEndConditionDetected::from_bits_truncate(self.get_rec())
}
#[inline]
pub fn get_rwc_int(&self) -> RegionWrapConditionDetected {
RegionWrapConditionDetected::from_bits_truncate(self.get_rwc())
}
#[inline]
pub fn get_rbe_int(&self) -> RegionBusError {
RegionBusError::from_bits_truncate(self.get_rbe())
}
#[inline]
pub fn get_rdm_int(&self) -> RegionDigestMismatch {
RegionDigestMismatch::from_bits_truncate(self.get_rdm())
}
#[inline]
pub fn get_rhc_int(&self) -> RegionHashCompleted {
RegionHashCompleted::from_bits_truncate(self.get_rhc())
}
}
pub struct RegionInterrupt<I: RegionNum> {
region: PhantomData<I>,
interrupt: Interrupt,
}
macro_rules! match_on_interrupt_status {
($self:ident, $name:ident) => {
paste! {
matches!($self.interrupt.[<get_$name>]() & $self.mask(), 1)
}
};
}
impl<I: RegionNum> RegionInterrupt<I> {
#[inline]
fn mask(&self) -> u8 {
1 << I::NUM
}
#[inline]
pub fn get_rsu_int(&self) -> bool {
match_on_interrupt_status!(self, rsu)
}
#[inline]
pub fn get_rec_int(&self) -> bool {
match_on_interrupt_status!(self, rec)
}
#[inline]
pub fn get_rwc_int(&self) -> bool {
match_on_interrupt_status!(self, rwc)
}
#[inline]
pub fn get_rbe_int(&self) -> bool {
match_on_interrupt_status!(self, rbe)
}
#[inline]
pub fn get_rdm_int(&self) -> bool {
match_on_interrupt_status!(self, rdm)
}
#[inline]
pub fn get_rhc_int(&self) -> bool {
match_on_interrupt_status!(self, rhc)
}
}
pub struct Region<I: RegionNum> {
region: PhantomData<I>,
}
macro_rules! match_on_interrupt_mask {
($self:ident, $name:ident) => {
paste! {
matches!($self.imr().read().[<$name>]().bits() & $self.mask(), 1)
}
};
}
macro_rules! match_on_interrupt_status {
($self:ident, $name:ident) => {
paste! {
matches!($self.isr().read().[<$name>]().bits() & $self.mask(), 1)
}
};
}
impl<I: RegionNum> Region<I> {
pub(super) fn new() -> Self {
Self {
region: PhantomData,
}
}
#[inline]
fn mask(&self) -> u8 {
1 << I::NUM
}
#[inline]
fn icm(&self) -> &RegisterBlock {
unsafe { &*crate::pac::ICM::ptr() }
}
#[inline]
fn ctrl(&self) -> &CTRL {
&self.icm().ctrl
}
#[inline]
fn idr(&self) -> &IDR {
&self.icm().idr
}
#[inline]
fn ier(&self) -> &IER {
&self.icm().ier
}
#[inline]
fn imr(&self) -> &IMR {
&self.icm().imr
}
#[inline]
fn isr(&self) -> &ISR {
&self.icm().isr
}
#[inline]
fn sr(&self) -> &SR {
&self.icm().sr
}
#[inline]
pub fn enable_monitoring(&self) {
self.ctrl().write(|w| unsafe { w.rmen().bits(self.mask()) });
}
#[inline]
pub fn get_monitoring_status(&self) -> bool {
self.sr().read().rmdis().bits() & self.mask() != 1
}
#[inline]
pub fn get_monitoring_raw_status(&self) -> bool {
self.sr().read().rawrmdis().bits() & self.mask() != 1
}
#[inline]
pub fn disable_monitoring(&self) {
self.ctrl()
.write(|w| unsafe { w.rmdis().bits(self.mask()) });
}
#[inline]
pub fn trigger_rehash(&self) {
self.ctrl()
.write(|w| unsafe { w.rehash().bits(self.mask()) });
}
#[inline]
pub fn set_rsu_int(&self) {
self.ier().write(|w| unsafe { w.rsu().bits(self.mask()) });
}
#[inline]
pub fn set_rec_int(&self) {
self.ier().write(|w| unsafe { w.rec().bits(self.mask()) });
}
#[inline]
pub fn set_rwc_int(&self) {
self.ier().write(|w| unsafe { w.rwc().bits(self.mask()) });
}
#[inline]
pub fn set_rbe_int(&self) {
self.ier().write(|w| unsafe { w.rbe().bits(self.mask()) });
}
#[inline]
pub fn set_rdm_int(&self) {
self.ier().write(|w| unsafe { w.rdm().bits(self.mask()) });
}
#[inline]
pub fn set_rhc_int(&self) {
self.ier().write(|w| unsafe { w.rhc().bits(self.mask()) });
}
#[inline]
pub fn disable_rsu_int(&self) {
self.idr().write(|w| unsafe { w.rsu().bits(self.mask()) });
}
#[inline]
pub fn disable_rec_int(&self) {
self.idr().write(|w| unsafe { w.rec().bits(self.mask()) });
}
#[inline]
pub fn disable_rwc_int(&self) {
self.idr().write(|w| unsafe { w.rwc().bits(self.mask()) });
}
#[inline]
pub fn disable_rbe_int(&self) {
self.idr().write(|w| unsafe { w.rbe().bits(self.mask()) });
}
#[inline]
pub fn disable_rdm_int(&self) {
self.idr().write(|w| unsafe { w.rdm().bits(self.mask()) });
}
#[inline]
pub fn disable_rhc_int(&self) {
self.idr().write(|w| unsafe { w.rhc().bits(self.mask()) });
}
#[inline]
pub fn get_rsu_int_mask(&self) -> bool {
match_on_interrupt_mask!(self, rsu)
}
#[inline]
pub fn get_rec_int_mask(&self) -> bool {
match_on_interrupt_mask!(self, rec)
}
#[inline]
pub fn get_rwc_int_mask(&self) -> bool {
match_on_interrupt_mask!(self, rwc)
}
#[inline]
pub fn get_rbe_int_mask(&self) -> bool {
match_on_interrupt_mask!(self, rbe)
}
#[inline]
pub fn get_rdm_int_mask(&self) -> bool {
match_on_interrupt_mask!(self, rdm)
}
#[inline]
pub fn get_rhc_int_mask(&self) -> bool {
match_on_interrupt_mask!(self, rhc)
}
#[inline]
pub fn get_rsu_int(&self) -> bool {
match_on_interrupt_status!(self, rsu)
}
#[inline]
pub fn get_rec_int(&self) -> bool {
match_on_interrupt_status!(self, rec)
}
#[inline]
pub fn get_rwc_int(&self) -> bool {
match_on_interrupt_status!(self, rwc)
}
#[inline]
pub fn get_rbe_int(&self) -> bool {
match_on_interrupt_status!(self, rbe)
}
#[inline]
pub fn get_rdm_int(&self) -> bool {
match_on_interrupt_status!(self, rdm)
}
#[inline]
pub fn get_rhc_int(&self) -> bool {
match_on_interrupt_status!(self, rhc)
}
#[inline]
pub fn get_interrupt_status(&mut self) -> RegionInterrupt<I> {
let interrupt = Interrupt(self.isr().read().bits());
RegionInterrupt {
region: PhantomData,
interrupt,
}
}
}
pub struct Icm {
icm: crate::pac::ICM,
}
impl Icm {
#[inline]
pub fn new(icm: crate::pac::ICM) -> Self {
Self { icm }
}
#[inline]
fn icm(&self) -> &RegisterBlock {
&self.icm
}
#[inline]
fn cfg(&self) -> &CFG {
&self.icm().cfg
}
#[inline]
fn ctrl(&self) -> &CTRL {
&self.icm().ctrl
}
#[inline]
fn dscr(&self) -> &DSCR {
&self.icm().dscr
}
#[inline]
fn hash(&self) -> &HASH {
&self.icm().hash
}
#[inline]
fn idr(&self) -> &IDR {
&self.icm().idr
}
#[inline]
fn ier(&self) -> &IER {
&self.icm().ier
}
#[inline]
fn imr(&self) -> &IMR {
&self.icm().imr
}
#[inline]
fn isr(&self) -> &ISR {
&self.icm().isr
}
#[inline]
fn sr(&self) -> &SR {
&self.icm().sr
}
#[inline]
fn uasr(&self) -> &UASR {
&self.icm().uasr
}
#[inline]
pub fn enable(&mut self) {
self.ctrl().write(|w| w.enable().set_bit());
}
#[inline]
pub fn icm_status(&self) -> bool {
self.sr().read().enable().bit_is_set()
}
#[inline]
pub fn disable(&mut self) {
self.ctrl().write(|w| w.disable().set_bit());
}
#[inline]
pub fn swrst(&mut self) {
self.ctrl().write(|w| w.swrst().set_bit());
}
#[inline]
pub fn destroy(self) -> crate::pac::ICM {
self.icm
}
#[inline]
pub fn enable_region<N: RegionNum>(&mut self) -> Region<N> {
Region::<N>::new()
}
#[inline]
pub fn enable_region0(&mut self) -> Region<Region0> {
Region::new()
}
#[inline]
pub fn enable_region1(&mut self) -> Region<Region1> {
Region::new()
}
#[inline]
pub fn enable_region2(&mut self) -> Region<Region2> {
Region::new()
}
#[inline]
pub fn enable_region3(&mut self) -> Region<Region3> {
Region::new()
}
#[inline]
pub fn set_hash_addr(&mut self, hash_addr_pointer: &HashArea) {
self.hash()
.write(|w| unsafe { w.hasa().bits((hash_addr_pointer as *const _) as u32 / 128) })
}
pub fn set_dscr_addr(&self, icm_region_desc: &MainRegionDesc<Region0>) {
self.dscr()
.write(|w| unsafe { w.dasa().bits((icm_region_desc as *const _) as u32 / 64) })
}
#[inline]
pub fn set_user_initial_hash_value(&self, user_initial_hash_value: [u32; 8]) {
for (index, initial_value) in user_initial_hash_value.iter().enumerate() {
self.icm().uihval[index].write(|w| unsafe { w.val().bits(*initial_value) });
}
}
#[inline]
pub fn set_user_algorithm(self, algo: icm_algorithm) {
self.cfg().write(|w| w.ualgo().variant(algo));
}
#[inline]
pub fn set_user_configurable_hash(&self, user_configurable_hash: bool) {
self.cfg().write(|w| w.uihash().bit(user_configurable_hash));
}
#[inline]
pub fn set_dual_input_buffer(&self, dualbuffer: bool) {
self.cfg().write(|w| w.dualbuff().bit(dualbuffer));
}
#[inline]
pub fn set_ascd(&self, automaticswitch: bool) {
self.cfg().write(|w| w.ascd().bit(automaticswitch));
}
#[inline]
pub fn set_busburden(&self, busburden: u8) {
self.cfg().write(|w| unsafe { w.bbc().bits(busburden) });
}
#[inline]
pub fn set_slbdis(&self, disable_secondary_lists: bool) {
self.cfg()
.write(|w| w.slbdis().bit(disable_secondary_lists));
}
#[inline]
pub fn set_eomdis(&self, disable_eom: bool) {
self.cfg().write(|w| w.eomdis().bit(disable_eom));
}
#[inline]
pub fn set_wbdis(&self, disable_eom: bool) {
self.cfg().write(|w| w.wbdis().bit(disable_eom));
}
#[inline]
pub fn set_urad_int(self) {
self.ier().write(|w| unsafe { w.rsu().bits(1) });
}
#[inline]
pub fn disable_urad_int(self) {
self.idr().write(|w| unsafe { w.rsu().bits(1) });
}
#[inline]
pub fn get_urad_int_mask(&self) -> bool {
self.imr().read().urad().bits()
}
#[inline]
pub fn get_urad_int(&self) -> bool {
self.isr().read().urad().bits()
}
#[inline]
pub fn get_urat(&self) -> URAT_A {
self.uasr().read().urat().variant().unwrap()
}
#[inline]
pub fn get_interrupt_status(&mut self) -> Interrupt {
let interrupt_vector = self.isr().read().bits();
Interrupt(interrupt_vector)
}
#[inline]
pub fn trigger_rehash(&self, bitmask: u8) {
self.ctrl().write(|w| unsafe { w.rehash().bits(bitmask) });
}
}
pub trait RegionNum: Sealed {
const NUM: usize;
const OFFSET: u32;
}
seq!(N in 0..=3 {
paste! {
#[doc = "ICM Region " N]
pub enum Region~N {}
impl Sealed for Region~N {}
impl RegionNum for Region~N {
const NUM: usize = N;
#[allow(clippy::identity_op)]
#[allow(clippy::erasing_op)]
const OFFSET: u32 = 0x10 * N;
}
}
});
pub trait RegionDesc {
fn set_region_address<T>(&mut self, addr: *const T);
fn set_region_configuration(&mut self, cfg: RegionConfiguration);
fn set_region_next(&mut self, next: RegionNext);
fn reset_region_configuration_to_default(&mut self);
}
#[repr(C)]
#[repr(align(64))]
pub struct Regions {
pub region0: MainRegionDesc<Region0>,
pub region1: MainRegionDesc<Region1>,
pub region2: MainRegionDesc<Region2>,
pub region3: MainRegionDesc<Region3>,
}
impl Regions {
pub const fn default() -> Self {
let region0 = MainRegionDesc::new_region0();
let region1 = MainRegionDesc::new_region1();
let region2 = MainRegionDesc::new_region2();
let region3 = MainRegionDesc::new_region3();
Self {
region0,
region1,
region2,
region3,
}
}
}
#[repr(C)]
#[repr(align(16))]
pub struct MainRegionDesc<N: RegionNum> {
num: PhantomData<N>,
pub raddr: RegionAddress,
pub rcfg: RegionConfiguration,
pub rctrl: RegionControl,
pub rnext: RegionNext,
}
impl MainRegionDesc<Region0> {
pub fn set_dscr_addr(&self, icm: &Icm) {
icm.dscr()
.write(|w| unsafe { w.dasa().bits((self as *const _) as u32 / 64) })
}
}
seq!(N in 0..=3 {
paste! {
#[doc = "Create region descriptor " N]
impl MainRegionDesc<Region~N> {
const fn new_region~N() -> Self {
MainRegionDesc {
num: PhantomData,
raddr: RegionAddress::default(),
rcfg: RegionConfiguration::default(),
rctrl: RegionControl::default(),
rnext: RegionNext::default(),
}
}
}
}
});
impl<N: RegionNum> RegionDesc for MainRegionDesc<N> {
#[inline]
fn set_region_address<T>(&mut self, addr: *const T) {
self.raddr.set_region_address(addr);
}
#[inline]
fn set_region_configuration(&mut self, cfg: RegionConfiguration) {
self.rcfg = cfg;
}
#[inline]
fn reset_region_configuration_to_default(&mut self) {
self.rcfg = RegionConfiguration::default();
}
#[inline]
fn set_region_next(&mut self, next: RegionNext) {
self.rnext = next;
}
}
impl<N: RegionNum> MainRegionDesc<N> {
#[inline]
pub fn set_rctrl(mut self, ctrl: RegionControl) {
self.rctrl = ctrl;
}
}
#[repr(C)]
#[repr(align(16))]
pub struct SecondaryRegionDesc {
pub raddr: RegionAddress,
pub rcfg: RegionConfiguration,
_pad: u32,
pub rnext: RegionNext,
}
impl RegionDesc for SecondaryRegionDesc {
fn set_region_address<T>(&mut self, addr: *const T) {
self.raddr.set_region_address(addr);
}
#[inline]
fn set_region_configuration(&mut self, cfg: RegionConfiguration) {
self.rcfg = cfg;
}
#[inline]
fn reset_region_configuration_to_default(&mut self) {
self.rcfg = RegionConfiguration::default();
}
#[inline]
fn set_region_next(&mut self, next: RegionNext) {
self.rnext = next;
}
}
impl SecondaryRegionDesc {
pub const fn default() -> Self {
SecondaryRegionDesc {
raddr: RegionAddress::default(),
rcfg: RegionConfiguration::default(),
_pad: 0,
rnext: RegionNext::default(),
}
}
}
#[derive(Debug)]
#[repr(C)]
#[repr(align(128))]
pub struct HashArea {
pub region0: [u32; 8],
pub region1: [u32; 8],
pub region2: [u32; 8],
pub region3: [u32; 8],
}
impl HashArea {
pub const fn default() -> Self {
HashArea {
region0: [0; 8],
region1: [0; 8],
region2: [0; 8],
region3: [0; 8],
}
}
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct RegionAddress {
pub raddr: u32,
}
impl RegionAddress {
pub fn set_region_address<T>(&mut self, raddr: *const T) {
self.raddr = raddr as u32;
}
const fn default() -> Self {
RegionAddress {
raddr: 0xDEADBEEF_u32,
}
}
}
bitfield::bitfield! {
#[derive(Clone, Copy)]
#[repr(C)]
pub struct RegionConfiguration(u32);
impl Debug;
u8;
#[inline]
pub get_cdwbn, set_cdwbn: 0;
#[inline]
pub
get_wrap, set_wrap: 1;
#[inline]
pub
get_eom, set_eom: 2;
#[inline]
pub
get_rhien, set_rhien: 4;
#[inline]
pub
get_dmien, set_dmien: 5;
#[inline]
pub
get_beien, set_beien: 6;
#[inline]
pub get_wcien, set_wcien: 7;
#[inline]
pub get_ecien, set_ecien: 8;
#[inline]
pub get_suien, set_suien: 9;
#[inline]
pub get_procdly, set_procdly: 10;
get_algo_bits, set_algo_bits: 14, 12;
}
impl RegionConfiguration {
const fn default() -> Self {
RegionConfiguration(0x3F0)
}
}
impl RegionConfiguration {
#[inline]
pub fn set_algo(&mut self, value: icm_algorithm) {
self.set_algo_bits(value.into());
}
#[inline]
pub fn get_algo(&mut self) -> icm_algorithm {
match self.get_algo_bits() {
2 => icm_algorithm::SHA224,
4 => icm_algorithm::SHA256,
_ => icm_algorithm::SHA1,
}
}
#[inline]
pub fn reset_region_configuration_to_default(&mut self) {
self.0 = 0x3F0_u32;
}
}
pub enum ProcessingDelay {
Shortest = 0,
Longest = 1,
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct RegionControl {
pub trsize: u16,
}
impl RegionControl {
const fn default() -> Self {
RegionControl { trsize: 0 }
}
}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct RegionNext {
rnext: u32,
}
impl RegionNext {
pub fn set_region_next(&mut self, rnext: &impl RegionDesc) {
self.rnext = (rnext as *const _) as u32;
}
const fn default() -> Self {
RegionNext { rnext: 0 }
}
}