From a8afd43992d57ae95f078dac649aaee520d43752 Mon Sep 17 00:00:00 2001 From: Priec Date: Sun, 19 Oct 2025 16:27:36 +0200 Subject: [PATCH] improvements to the code, fixing incompatibilities with the PAC crate --- src/flash.rs | 55 +++++++++++++++----------------------------------- src/pwr.rs | 38 ++++++++++++++-------------------- src/rcc/rcc.rs | 22 +++++++++++++++----- 3 files changed, 48 insertions(+), 67 deletions(-) diff --git a/src/flash.rs b/src/flash.rs index 5739982..4658daa 100644 --- a/src/flash.rs +++ b/src/flash.rs @@ -20,7 +20,7 @@ use crate::pac as pac; use crate::pac::FLASH; -use core::{mem, ptr}; +use core::ptr; /// Simple Flash error set for this minimal port #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -193,9 +193,7 @@ impl<'a> FlashProgramming<'a> { let sr = self.nssr.reg().read(); if sr.eop().bit_is_set() { // Write-one-to-clear EOP - unsafe { - self.nssr.reg().write(|w| w.eop().set_bit()); - } + self.nssr.reg().write(|w| w.eop().set_bit()); } } @@ -285,45 +283,24 @@ impl<'a> FlashProgramming<'a> { /// For leading/trailing partial chunks, we fill missing bytes with 0xFF, /// which matches erased Flash default. pub fn write(&mut self, address: usize, buf: &[u8]) -> Result<(), Error> { - // Handle leading unaligned portion - let align_off = address & 0xF; - let mut cur_addr = address; - - if align_off != 0 { - let head = core::cmp::min(16 - align_off, buf.len()); - let mut q = [0xFFu8; 16]; - // Pull existing erased fill (0xFF), then overlay provided bytes - q[align_off..align_off + head].copy_from_slice(&buf[..head]); - self.write_quadword(address - align_off, &q)?; - cur_addr += head; + if buf.is_empty() { + return Ok(()); } - // Aligned middle - let aligned_len = if cur_addr > address { - buf.len() - (cur_addr - address) - } else { - buf.len() - }; - let aligned_start = buf.len() - aligned_len + (cur_addr - address); - let mut i = 0; - while i + 16 <= aligned_len { - let mut q = [0u8; 16]; - q.copy_from_slice( - &buf[aligned_start + i..aligned_start + i + 16], - ); - self.write_quadword(cur_addr, &q)?; - cur_addr += 16; - i += 16; - } + let start = address & !0xF; // align down to 16 + let end = address + buf.len(); + let mut pos = start; - // Trailing remainder - let rem = aligned_len - i; - if rem > 0 { + while pos < end { let mut q = [0xFFu8; 16]; - q[..rem].copy_from_slice( - &buf[aligned_start + i..aligned_start + i + rem], - ); - self.write_quadword(cur_addr, &q)?; + for i in 0..16 { + let a = pos + i; + if a >= address && a < end { + q[i] = buf[a - address]; + } + } + self.write_quadword(pos, &q)?; + pos += 16; } Ok(()) diff --git a/src/pwr.rs b/src/pwr.rs index 2da9f25..b1756d2 100644 --- a/src/pwr.rs +++ b/src/pwr.rs @@ -109,16 +109,12 @@ pub struct Pwr { impl Pwr { /// Enable write access to the backup domain (DBP = 1) pub fn enable_backup_write(&mut self) { - unsafe { - self.dbpr.reg().modify(|_, w| w.dbp().set_bit()); - } + self.dbpr.reg().modify(|_, w| w.dbp().set_bit()); } /// Disable write access to the backup domain (DBP = 0) pub fn disable_backup_write(&mut self) { - unsafe { - self.dbpr.reg().modify(|_, w| w.dbp().clear_bit()); - } + self.dbpr.reg().modify(|_, w| w.dbp().clear_bit()); } /// Enter Standby low-power mode. @@ -148,15 +144,13 @@ impl Pwr { // HAL C uses: MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_2); // We map to LPMS = 0b100 (Standby). Exact encoding may differ by die rev, // but LPMS field exists in U5. - unsafe { - self.cr1.reg().modify(|_, w| { - // LPMS is a field; set to Standby (0b100) - #[allow(unused_unsafe)] - unsafe { - w.lpms().bits(0b100) - } - }); - } + self.cr1.reg().modify(|_, w| { + // LPMS is a field; set to Standby (0b100) + #[allow(unused_unsafe)] + unsafe { + w.lpms().bits(0b100) + } + }); scb.set_sleepdeep(); cortex_m::asm::dsb(); @@ -186,14 +180,12 @@ impl Pwr { // Configure Shutdown in CR1.LPMS // Typical encoding: 0b110 (consult RM for your exact part). - unsafe { - self.cr1.reg().modify(|_, w| { - #[allow(unused_unsafe)] - unsafe { - w.lpms().bits(0b110) - } - }); - } + self.cr1.reg().modify(|_, w| { + #[allow(unused_unsafe)] + unsafe { + w.lpms().bits(0b110) + } + }); scb.set_sleepdeep(); cortex_m::asm::dsb(); diff --git a/src/rcc/rcc.rs b/src/rcc/rcc.rs index 66d17c1..718b415 100644 --- a/src/rcc/rcc.rs +++ b/src/rcc/rcc.rs @@ -614,9 +614,11 @@ impl CFGR { let sysclk_src_bits; if let Some(pll) = pllconf { - // Basic checks for VCO ranges (very simplified; FRACN/MBOOST ignored) + // Basic checks for VCO input/output ranges (STM32U5; FRACN/MBOOST ignored) let vco_in = (src_freq as u32) / (pll.m as u32); - assert!(vco_in >= 1_000_000 && vco_in <= 16_000_000); + // Typical U5: 2..16 MHz recommended VCI; tighten to 2 MHz unless you intentionally + // support 1..2 MHz (then map to 0b00 below). + assert!(vco_in >= 2_000_000 && vco_in <= 16_000_000); let vco = (vco_in as u64) * (pll.n as u64); assert!(vco >= 128_000_000 && vco <= 544_000_000); let sysclk_calc = (vco / (pll.r as u64)) as u32; @@ -628,11 +630,21 @@ impl CFGR { // Set PLL source let src_bits = pll_src.to_pllsrc_bits(); + fn pll1_rge_bits(vci_hz: u32) -> u8 { + if vci_hz < 2_000_000 { + 0b00 // 1..2 MHz + } else if vci_hz < 4_000_000 { + 0b01 // 2..4 MHz + } else if vci_hz < 8_000_000 { + 0b10 // 4..8 MHz + } else { + 0b11 // 8..16 MHz + } + } + rcc.pll1cfgr().modify(|_, w| unsafe { w.pll1src().bits(src_bits); - // VCI range selection (very rough): 4..8 => range0, 8..16 => range1 - let rge = if vco_in < 8_000_000 { 0b00 } else { 0b11 }; - w.pll1rge().bits(rge); + w.pll1rge().bits(pll1_rge_bits(vco_in)); // M w.pll1m().bits(pll.m - 1); // Enable only R output