From 836c836aec1cc102eb88c03872eeb080d034225e Mon Sep 17 00:00:00 2001 From: bunnie Date: Mon, 26 Apr 2021 14:55:45 +0800 Subject: [PATCH] wip for susres extensions --- svd2utra/src/generate.rs | 112 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/svd2utra/src/generate.rs b/svd2utra/src/generate.rs index 0ce7c79c3..b7c8c68ee 100644 --- a/svd2utra/src/generate.rs +++ b/svd2utra/src/generate.rs @@ -1,7 +1,7 @@ use quick_xml::events::Event; use quick_xml::Reader; use std::io::{BufRead, BufReader, Read, Write}; - +use convert_case::{Case, Casing}; #[derive(Debug)] pub enum ParseError { UnexpectedTag, @@ -477,6 +477,7 @@ fn parse_vendor_extensions( fn print_header(out: &mut U) -> std::io::Result<()> { let s = r####" +#![allow(dead_code)] use core::convert::TryInto; pub struct Register { /// Offset of this register within this CSR @@ -549,6 +550,7 @@ impl Field { } } } +#[derive(Debug, Copy, Clone)] pub struct CSR { pub base: *mut T, } @@ -676,10 +678,116 @@ fn print_peripherals(peripherals: &[Peripheral], out: &mut U) -> std:: } writeln!(out)?; - writeln!(out, "pub mod utra {{")?; + let s = r####" +pub mod utra { + pub enum Error { + OutOfMemory, + } + + #[derive(Debug, Copy, Clone)] + pub struct ManagedReg { + pub offset: T, + pub mask: usize, + pub value: usize, + } + //#[derive(Debug)] + pub struct SusResRegManager { + pub csr: crate::CSR, + pub registers: [Option>; N], + pub sus_prologue: Option, + pub sus_epilogue: Option, + pub res_prologue: Option, + pub res_epilogue: Option, + } + impl SusResRegManager:: where ManagedReg: core::marker::Copy { + pub fn new(reg_base: *mut u32) -> SusResRegManager { + SusResRegManager:: { + csr: crate::CSR::new(reg_base), + registers: [None; N], + sus_prologue: None, + sus_epilogue: None, + res_prologue: None, + res_epilogue: None, + } + } + } + pub trait SusResReg { + fn push(&mut self, mr: ManagedReg) -> Result<(), Error>; + fn suspend(&mut self); + fn resume(&mut self); + } + impl SusResReg for SusResRegManager where T: core::convert::Into + Copy { + // push registers into the manager in the order you want them suspended + fn push(&mut self, mr: ManagedReg) -> Result<(), Error> { + for entry in self.registers.iter_mut() { + if entry.is_none() { + *entry = Some(mr); + return Ok(()) + } + } + Err(Error::OutOfMemory) + } + fn suspend(&mut self) { + if let Some(sp) = self.sus_prologue { + sp(self); + } + for entry in self.registers.iter_mut() { + if let Some(reg) = entry { + // masking is done on the write side + reg.value = self.csr.r(crate::Register{offset: reg.offset.into()}) as usize; + } + } + if let Some(se) = self.sus_epilogue { + se(self); + } + } + fn resume(&mut self) { + if let Some(rp) = self.res_prologue { + rp(self); + } + for entry in self.registers.iter().rev() { // this is in reverse order to the suspend + if let Some(reg) = entry { + self.csr.wo(crate::Register{offset: reg.offset.into()}, (reg.value & reg.mask) as u32); + } + } + if let Some(re) = self.res_epilogue { + re(self); + } + } + } +/* + pub struct ManagedMem { + pub mem: xous::MemoryRange, + pub backing: [u32; N], + } + pub trait SusResMem { + fn suspend(&mut self) { + let src = self.mem.as_ptr() as *const u32; + for words in 0..self.mem.len() { + self.backing[words] = unsafe{src.add(words).read_volatile()}; + } + } + fn resume(&mut self) { + let dst = self.mem.as_ptr() as *mut u32; + for words in 0..self.mem.len() { + unsafe{dst.add(words).write_volatile(self.backing[words])}; + } + } + } +*/ +"####; + out.write_all(s.as_bytes())?; + for peripheral in peripherals { writeln!(out)?; writeln!(out, " pub mod {} {{", peripheral.name.to_lowercase())?; + writeln!(out, " #[derive(Debug, Copy, Clone)]")?; + writeln!(out, " pub enum {}Offset {{", peripheral.name.to_case(Case::UpperCamel))?; + for register in &peripheral.registers { + writeln!(out, " {} = {},", register.name.to_case(Case::UpperCamel), register.offset / 4)?; + } + writeln!(out, " }}")?; + writeln!(out, " pub const {}_NUMREGS: usize = {};", peripheral.name.to_uppercase(), peripheral.registers.len())?; for register in &peripheral.registers { writeln!(out)?; if let Some(description) = ®ister.description {