pub mod adc;
pub mod bdma;
pub mod dbg;
pub mod dma;
pub mod dmamux;
pub mod exti;
pub mod flash;
pub mod gpio;
pub mod i2c;
pub mod otg;
pub mod pwr;
pub mod rcc;
pub mod rng;
pub mod sdmmc;
pub mod spi;
pub mod syscfg;
pub mod tim;
pub mod usart;
use crate::cpu::armv7m::Dwt;
use crate::device::{DeviceContext, ErasedDevice, RegisterFile, ResetCause};
use crate::mcu::{Mcu, Operate};
use crate::snapshot::store;
use crate::soc::{Bus, Error};
use crate::time::VirtualNanos;
use super::generated::rtc;
use adc::{Adc, AdcCommon, Block, Converter};
use bdma::Bdma;
use dbg::Dbg;
use dma::{DMA1_FIRST_CHANNEL, DMA2_FIRST_CHANNEL, Dma};
use dmamux::{Dmamux1, Dmamux2};
use exti::Exti;
use flash::Flash;
use gpio::{Gpio, PORTS};
use i2c::I2c;
use otg::Otg;
use pwr::Pwr;
use rcc::Rcc;
use rng::Rng;
use sdmmc::Sdmmc;
use spi::Spi;
use syscfg::Syscfg;
use tim::{
ADVANCED_TIMERS, Advanced, BASIC_TIMERS, Basic, General, TIMER_15, TIMER_16, TIMER_17, TIMERS,
Tim, Tim15, Tim16, Tim17,
};
use usart::Usart;
const RESET_CORE_HZ: u64 = 64_000_000;
#[derive(Debug)]
pub struct Stm32h743 {
pub rcc: Rcc,
pub pwr: Pwr,
pub flash: Flash,
pub gpio: [Gpio; PORTS.len()],
pub syscfg: Syscfg,
pub exti: Exti,
pub rng: Rng,
pub dbg: Dbg,
pub tim: [Tim<General>; TIMERS.len()],
pub advanced: [Tim<Advanced>; ADVANCED_TIMERS.len()],
pub basic: [Tim<Basic>; BASIC_TIMERS.len()],
pub tim15: Tim<Tim15>,
pub tim16: Tim<Tim16>,
pub tim17: Tim<Tim17>,
pub usart: [Usart; usart::INSTANCES.len()],
pub spi: [Spi; spi::INSTANCES.len()],
pub i2c: [I2c; i2c::INSTANCES.len()],
pub dma: [Dma; 2],
pub dmamux1: Dmamux1,
pub otg: [Otg; otg::INSTANCES.len()],
pub sdmmc: [Sdmmc; sdmmc::INSTANCES.len()],
pub adc: [Adc; Converter::ALL.len()],
pub adc_common: [AdcCommon; Block::ALL.len()],
pub bdma: Bdma,
pub dmamux2: Dmamux2,
pub dwt: Dwt,
bus: Bus,
wiring: Box<[Field]>,
slots: Slots,
}
#[derive(Debug, Clone, Copy)]
struct Slots {
rcc: usize,
pwr: usize,
flash: usize,
gpio: [usize; PORTS.len()],
dbg: usize,
usart: [usize; usart::INSTANCES.len()],
spi: [usize; spi::INSTANCES.len()],
i2c: [usize; i2c::INSTANCES.len()],
tim: [usize; TIMERS.len()],
advanced: [usize; ADVANCED_TIMERS.len()],
tim15: usize,
rtc: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Field {
None,
Rcc,
Pwr,
Flash,
Gpio(usize),
Syscfg,
Exti,
Rng,
Dbg,
Tim(usize),
Advanced(usize),
Basic(usize),
Tim15,
Tim16,
Tim17,
Usart(usize),
Spi(usize),
I2c(usize),
Dma(usize),
Dmamux1,
Otg(usize),
Sdmmc(usize),
Adc(usize),
AdcCommon(usize),
Bdma,
Dmamux2,
Dwt,
}
impl Field {
fn all() -> Vec<Self> {
let mut all = vec![Self::Rcc, Self::Pwr, Self::Flash];
all.extend((0..PORTS.len()).map(Self::Gpio));
all.extend([Self::Syscfg, Self::Exti, Self::Rng, Self::Dbg]);
all.extend((0..TIMERS.len()).map(Self::Tim));
all.extend((0..ADVANCED_TIMERS.len()).map(Self::Advanced));
all.extend((0..BASIC_TIMERS.len()).map(Self::Basic));
all.extend([Self::Tim15, Self::Tim16, Self::Tim17]);
all.extend((0..usart::INSTANCES.len()).map(Self::Usart));
all.extend((0..spi::INSTANCES.len()).map(Self::Spi));
all.extend((0..i2c::INSTANCES.len()).map(Self::I2c));
all.extend([
Self::Dma(0),
Self::Dma(1),
Self::Dmamux1,
Self::Bdma,
Self::Dmamux2,
]);
all.extend((0..otg::INSTANCES.len()).map(Self::Otg));
all.extend((0..sdmmc::INSTANCES.len()).map(Self::Sdmmc));
all.extend((0..Converter::ALL.len()).map(Self::Adc));
all.extend((0..Block::ALL.len()).map(Self::AdcCommon));
all.push(Self::Dwt);
all
}
fn instance(self) -> &'static str {
match self {
Self::None => unreachable!("the unmodeled slot answers for no instance"),
Self::Rcc => super::generated::RCC.name,
Self::Pwr => super::generated::PWR.name,
Self::Flash => super::generated::FLASH.name,
Self::Gpio(nth) => PORTS[nth],
Self::Syscfg => super::generated::SYSCFG.name,
Self::Exti => super::generated::EXTI.name,
Self::Rng => super::generated::RNG.name,
Self::Dbg => super::generated::DBGMCU.name,
Self::Tim(nth) => TIMERS[nth].instance,
Self::Advanced(nth) => ADVANCED_TIMERS[nth].instance,
Self::Basic(nth) => BASIC_TIMERS[nth].instance,
Self::Tim15 => TIMER_15.instance,
Self::Tim16 => TIMER_16.instance,
Self::Tim17 => TIMER_17.instance,
Self::Usart(nth) => usart::INSTANCES[nth],
Self::Spi(nth) => spi::INSTANCES[nth].name,
Self::I2c(nth) => i2c::INSTANCES[nth].name,
Self::Dma(nth) => [super::generated::DMA1.name, super::generated::DMA2.name][nth],
Self::Dmamux1 => super::generated::DMAMUX1.name,
Self::Otg(nth) => otg::INSTANCES[nth],
Self::Sdmmc(nth) => sdmmc::INSTANCES[nth],
Self::Adc(nth) => Converter::ALL[nth].instance(),
Self::AdcCommon(nth) => Block::ALL[nth].instance(),
Self::Bdma => super::generated::BDMA.name,
Self::Dmamux2 => super::generated::DMAMUX2.name,
Self::Dwt => crate::cpu::armv7m::DWT,
}
}
}
store!(Stm32h743 {
values: [
rcc, pwr, otg, sdmmc, adc, adc_common, flash, gpio, syscfg, exti, rng, dbg, tim, advanced,
basic, tim15, tim16, tim17, dwt,
],
parts: [usart, spi, i2c, dma, dmamux1, bdma, dmamux2, bus],
built: [wiring, slots],
});
impl Stm32h743 {
pub fn new() -> Result<Self, Error> {
let bus = super::memory_map::builder().build()?;
let mut wiring = vec![Field::None; bus.slots().len()].into_boxed_slice();
let mut slots = Slots {
rcc: 0,
pwr: 0,
flash: 0,
gpio: [0; PORTS.len()],
dbg: 0,
usart: [0; usart::INSTANCES.len()],
spi: [0; spi::INSTANCES.len()],
i2c: [0; i2c::INSTANCES.len()],
tim: [0; TIMERS.len()],
advanced: [0; ADVANCED_TIMERS.len()],
tim15: 0,
rtc: bus.slot("RTC")?,
};
for field in Field::all() {
let instance = field.instance();
let slot = bus.slot(instance)?;
wiring[slot] = field;
match field {
Field::Rcc => slots.rcc = slot,
Field::Pwr => slots.pwr = slot,
Field::Flash => slots.flash = slot,
Field::Gpio(nth) => slots.gpio[nth] = slot,
Field::Dbg => slots.dbg = slot,
Field::Usart(nth) => slots.usart[nth] = slot,
Field::Spi(nth) => slots.spi[nth] = slot,
Field::I2c(nth) => slots.i2c[nth] = slot,
Field::Tim(nth) => slots.tim[nth] = slot,
Field::Advanced(nth) => slots.advanced[nth] = slot,
Field::Tim15 => slots.tim15 = slot,
Field::None => unreachable!("Field::all names no unmodeled slot"),
_ => {}
}
}
let mut mcu = Self {
rcc: Rcc::new(),
pwr: Pwr::new(),
flash: Flash::new(),
gpio: std::array::from_fn(|_| Gpio::default()),
syscfg: Syscfg,
exti: Exti::new(super::generated::SYSCFG.base),
rng: Rng::new(rng::RESET_AHB_HZ, rng::KERNEL_HZ),
dbg: Dbg,
tim: std::array::from_fn(|nth| Tim::new(TIMERS[nth])),
advanced: std::array::from_fn(|nth| Tim::new(ADVANCED_TIMERS[nth])),
basic: std::array::from_fn(|nth| Tim::new(BASIC_TIMERS[nth])),
tim15: Tim::new(TIMER_15),
tim16: Tim::new(TIMER_16),
tim17: Tim::new(TIMER_17),
usart: std::array::from_fn(|_| Usart::new()),
spi: std::array::from_fn(|nth| Spi::new(spi::INSTANCES[nth].kind)),
i2c: std::array::from_fn(|_| I2c::default()),
dma: [Dma::new(DMA1_FIRST_CHANNEL), Dma::new(DMA2_FIRST_CHANNEL)],
dmamux1: Dmamux1::new(),
otg: [Otg; otg::INSTANCES.len()],
sdmmc: [Sdmmc::default(); sdmmc::INSTANCES.len()],
adc: Converter::ALL.map(|converter| Adc::new(converter, 0)),
adc_common: Block::ALL.map(|block| AdcCommon::new(block, 0)),
bdma: Bdma::new(),
dmamux2: Dmamux2::new(),
dwt: Dwt::with_clock(RESET_CORE_HZ),
bus,
wiring,
slots,
};
mcu.check()?;
Ok(mcu)
}
pub fn clocks(&mut self) -> (&mut Rcc, &mut RegisterFile) {
with_registers(&mut self.rcc, &mut self.bus, self.slots.rcc)
}
pub fn power(&mut self) -> (&mut Pwr, &mut RegisterFile) {
with_registers(&mut self.pwr, &mut self.bus, self.slots.pwr)
}
pub fn set_supply(&mut self, millivolts: u32) {
let (power, registers) = self.power();
power.set_supply(millivolts, registers);
}
pub fn set_analog_supply(&mut self, millivolts: u32) {
let (power, registers) = self.power();
power.set_analog_supply(millivolts, registers);
}
pub fn program(&mut self) -> (&mut Flash, &mut RegisterFile) {
with_registers(&mut self.flash, &mut self.bus, self.slots.flash)
}
pub fn timer(&mut self, nth: usize) -> (&mut Tim<General>, &mut RegisterFile) {
with_registers(&mut self.tim[nth], &mut self.bus, self.slots.tim[nth])
}
pub fn advanced_timer(&mut self, nth: usize) -> (&mut Tim<Advanced>, &mut RegisterFile) {
with_registers(
&mut self.advanced[nth],
&mut self.bus,
self.slots.advanced[nth],
)
}
pub fn timer_15(&mut self) -> (&mut Tim<Tim15>, &mut RegisterFile) {
with_registers(&mut self.tim15, &mut self.bus, self.slots.tim15)
}
pub fn drive_port<T>(
&mut self,
at: VirtualNanos,
nth: usize,
input: impl FnOnce(&mut Gpio, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
) -> T {
driving(
&mut self.gpio[nth],
&mut self.bus,
self.slots.gpio[nth],
at,
input,
)
}
}
fn kept_by_the_clock(register: rtc::Register, clock: &RegisterFile) -> Option<u64> {
let value = clock.get(register);
match register {
rtc::Register::RtcTr | rtc::Register::RtcDr | rtc::Register::RtcSsr => rtc::rtc_cr::BYPSHAD
.is_set(clock.get(rtc::Register::RtcCr))
.then_some(value),
rtc::Register::RtcIsr => Some(
value
& !(rtc::rtc_isr::INIT.mask()
| rtc::rtc_isr::INITF.mask()
| rtc::rtc_isr::RSF.mask()),
),
rtc::Register::RtcWpr => None,
_ => Some(value),
}
}
fn with_registers<'a, M>(
model: &'a mut M,
bus: &'a mut Bus,
slot: usize,
) -> (&'a mut M, &'a mut RegisterFile) {
(model, bus.slot_mut(slot).registers_mut())
}
fn driving<M, T>(
model: &mut M,
bus: &mut Bus,
slot: usize,
at: VirtualNanos,
input: impl FnOnce(&mut M, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
) -> T {
let (registers, mut context) = bus.drive(at, slot);
input(model, registers, &mut context)
}
impl Stm32h743 {
fn chips_restarted(&mut self, at: VirtualNanos) {
let Self {
usart,
spi,
i2c,
bus,
slots,
..
} = self;
for (usart, &slot) in usart.iter_mut().zip(&slots.usart) {
driving(usart, bus, slot, at, |usart, _, context| {
usart.chips_restarted(context);
});
}
for (spi, &slot) in spi.iter_mut().zip(&slots.spi) {
driving(spi, bus, slot, at, |spi, _, context| {
spi.chips_restarted(context);
});
}
for (i2c, &slot) in i2c.iter_mut().zip(&slots.i2c) {
driving(i2c, bus, slot, at, |i2c, _, context| {
i2c.chips_restarted(context);
});
}
}
}
impl Mcu for Stm32h743 {
fn bus(&self) -> &Bus {
&self.bus
}
fn reset(&mut self, at: VirtualNanos, cause: ResetCause) {
let mut fresh = Self::new().expect("a part that assembled once assembles again");
std::mem::swap(&mut fresh.rcc, &mut self.rcc);
crate::device::Device::reset(&mut fresh.rcc);
std::mem::swap(&mut fresh.pwr, &mut self.pwr);
crate::device::Device::reset(&mut fresh.pwr);
let flags = self.bus.slots()[self.slots.rcc]
.registers()
.get(super::generated::rcc::Register::Rsr);
let (clocks, registers) = fresh.clocks();
clocks.restarted(cause, flags, registers);
for (fresh, old) in fresh.spi.iter_mut().zip(&mut self.spi) {
fresh.inherit(old);
}
for (fresh, old) in fresh.i2c.iter_mut().zip(&mut self.i2c) {
fresh.inherit(old);
}
let options = self.flash.committed_options();
let (flash, registers) = fresh.program();
flash.keep_options(options, registers);
for (fresh, old) in fresh.usart.iter_mut().zip(&mut self.usart) {
fresh.inherit(old);
}
for (fresh, old) in fresh.adc.iter_mut().zip(&mut self.adc) {
std::mem::swap(fresh, old);
crate::device::Device::reset(fresh);
}
for (fresh, old) in fresh.gpio.iter_mut().zip(&mut self.gpio) {
*fresh = std::mem::take(old);
crate::device::Device::reset(fresh);
}
for register in dbg::KEPT_BY_A_SYSTEM_RESET {
let value = self.bus.slots()[self.slots.dbg].registers().get(register);
fresh
.bus
.slot_mut(fresh.slots.dbg)
.registers_mut()
.set(register, value);
}
let clock = self.bus.slots()[self.slots.rtc].registers();
let fresh_clock = fresh.bus.slot_mut(fresh.slots.rtc).registers_mut();
for register in rtc::Register::ALL {
if let Some(value) = kept_by_the_clock(register, clock) {
fresh_clock.set(register, value);
}
}
fresh
.bus
.keep_added(&self.bus)
.expect("a part rebuilt from its own description");
*self = fresh;
self.chips_restarted(at);
}
fn poll(&mut self, now: VirtualNanos) {
self.poll_every_model(now);
}
fn split(&mut self, slot: usize) -> (&mut Bus, Option<&mut dyn ErasedDevice>) {
let Self {
rcc,
pwr,
flash,
gpio,
syscfg,
exti,
rng,
dbg,
tim,
advanced,
basic,
tim15,
tim16,
tim17,
usart,
spi,
i2c,
dma,
dmamux1,
otg,
sdmmc,
adc,
adc_common,
bdma,
dmamux2,
dwt,
bus,
wiring,
..
} = self;
let field = wiring.get(slot).copied().unwrap_or(Field::None);
let model: Option<&mut dyn ErasedDevice> = match field {
Field::None => None,
Field::Rcc => Some(rcc),
Field::Pwr => Some(pwr),
Field::Flash => Some(flash),
Field::Gpio(nth) => Some(&mut gpio[nth]),
Field::Syscfg => Some(syscfg),
Field::Exti => Some(exti),
Field::Rng => Some(rng),
Field::Dbg => Some(dbg),
Field::Tim(nth) => Some(&mut tim[nth]),
Field::Advanced(nth) => Some(&mut advanced[nth]),
Field::Basic(nth) => Some(&mut basic[nth]),
Field::Tim15 => Some(tim15),
Field::Tim16 => Some(tim16),
Field::Tim17 => Some(tim17),
Field::Usart(nth) => Some(&mut usart[nth]),
Field::Spi(nth) => Some(&mut spi[nth]),
Field::I2c(nth) => Some(&mut i2c[nth]),
Field::Dma(nth) => Some(&mut dma[nth]),
Field::Dmamux1 => Some(dmamux1),
Field::Otg(nth) => Some(&mut otg[nth]),
Field::Sdmmc(nth) => Some(&mut sdmmc[nth]),
Field::Adc(nth) => Some(&mut adc[nth]),
Field::AdcCommon(nth) => Some(&mut adc_common[nth]),
Field::Bdma => Some(bdma),
Field::Dmamux2 => Some(dmamux2),
Field::Dwt => Some(dwt),
};
(bus, model)
}
fn bus_mut(&mut self) -> &mut Bus {
&mut self.bus
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_field_answers_for_the_one_instance_it_is_named_for() {
let mut mcu = Stm32h743::new().unwrap();
for field in Field::all() {
let slot = mcu.bus.slot_of(field.instance()).unwrap();
assert_eq!(mcu.wiring[slot], field);
assert!(mcu.split(slot).1.is_some(), "{}", field.instance());
}
let modeled = mcu.wiring.iter().filter(|&&field| field != Field::None);
assert_eq!(modeled.count(), Field::all().len());
}
#[test]
fn the_part_hands_flash_stores_to_its_interface_and_comes_back_from_a_reset() {
let mut mcu = Stm32h743::new().unwrap();
let at = VirtualNanos(0);
assert_eq!(
mcu.write(at, 0x0800_0000, crate::soc::Width::W32, 0),
Ok(())
);
let slots = mcu.bus.slots().len();
mcu.reset(at, ResetCause::Pin);
assert_eq!(mcu.bus.slots().len(), slots);
}
}