use crate::device::{Device, DeviceContext, RegisterFile};
use crate::soc::stm32h743::generated::otg1_hs_global::{Register, otg_hs_grstctl};
pub const INSTANCES: [&str; 2] = ["OTG1_HS_GLOBAL", "OTG2_HS_GLOBAL"];
pub const GRSTCTL_RESET: u64 = otg_hs_grstctl::AHBIDL.mask();
const SELF_CLEARING: u64 = otg_hs_grstctl::CSRST.mask()
| otg_hs_grstctl::FCRST.mask()
| otg_hs_grstctl::RXFFLSH.mask()
| otg_hs_grstctl::TXFFLSH.mask();
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Otg;
impl Device for Otg {
type Register = Register;
fn write(
&mut self,
register: Register,
_written: u64,
registers: &mut RegisterFile,
_context: &mut DeviceContext<'_>,
) {
if register == Register::OtgHsGrstctl {
let held = registers.get(Register::OtgHsGrstctl);
registers.set(Register::OtgHsGrstctl, held & !SELF_CLEARING);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mcu::{Operate, Single};
use crate::soc::stm32h743::builder;
use crate::soc::stm32h743::generated::OTG1_HS_GLOBAL;
use crate::soc::{Layout, Width};
use crate::time::VirtualNanos;
const AT: VirtualNanos = VirtualNanos(0);
fn grstctl() -> u64 {
OTG1_HS_GLOBAL.base + u64::from(Register::OtgHsGrstctl.spec().offset)
}
fn core() -> Single<Otg> {
Single::new(builder(), INSTANCES[0], Otg).unwrap()
}
#[test]
fn the_core_comes_out_of_reset_with_its_master_idle() {
assert_eq!(core().read(AT, grstctl(), Width::W32), Ok(0x8000_0000));
}
#[test]
fn a_write_cannot_clear_the_idle_flag() {
let mut core = core();
core.write(AT, grstctl(), Width::W32, 0).unwrap();
assert_eq!(core.read(AT, grstctl(), Width::W32), Ok(GRSTCTL_RESET));
}
#[test]
fn every_bit_the_core_clears_for_itself_reads_back_clear() {
let mut core = core();
for bit in [
otg_hs_grstctl::CSRST,
otg_hs_grstctl::FCRST,
otg_hs_grstctl::RXFFLSH,
otg_hs_grstctl::TXFFLSH,
] {
core.write(AT, grstctl(), Width::W32, bit.mask()).unwrap();
assert_eq!(
core.read(AT, grstctl(), Width::W32),
Ok(GRSTCTL_RESET),
"{}",
bit.name
);
}
}
#[test]
fn the_partial_reset_and_the_fifo_number_are_stored() {
let mut core = core();
let written = otg_hs_grstctl::HSRST.mask() | otg_hs_grstctl::TXFNUM.set(0, 0x10);
core.write(AT, grstctl(), Width::W32, written).unwrap();
assert_eq!(
core.read(AT, grstctl(), Width::W32),
Ok(GRSTCTL_RESET | written)
);
}
#[test]
fn the_drivers_reset_sequence_leaves_every_one_of_its_waits() {
let mut core = core();
let read = |core: &mut Single<Otg>| core.read(AT, grstctl(), Width::W32).unwrap();
assert_ne!(read(&mut core) & otg_hs_grstctl::AHBIDL.mask(), 0);
core.write(AT, grstctl(), Width::W32, otg_hs_grstctl::CSRST.mask())
.unwrap();
assert_eq!(read(&mut core) & otg_hs_grstctl::CSRST.mask(), 0);
assert_ne!(read(&mut core) & otg_hs_grstctl::AHBIDL.mask(), 0);
let flush_all = otg_hs_grstctl::TXFNUM.set(0, 0x10) | otg_hs_grstctl::TXFFLSH.mask();
core.write(AT, grstctl(), Width::W32, flush_all).unwrap();
assert_eq!(read(&mut core) & otg_hs_grstctl::TXFFLSH.mask(), 0);
core.write(AT, grstctl(), Width::W32, otg_hs_grstctl::RXFFLSH.mask())
.unwrap();
assert_eq!(read(&mut core) & otg_hs_grstctl::RXFFLSH.mask(), 0);
}
}