From a1a5156cafbfe4d6a4e000fb8a33a3c16b7dff7d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 27 Sep 2024 19:06:13 +0200 Subject: [PATCH] re-work NVM interface --- vorago-reb1/examples/nvm.rs | 48 +++++++++++-------------- vorago-reb1/src/m95m01.rs | 72 +++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/vorago-reb1/examples/nvm.rs b/vorago-reb1/examples/nvm.rs index 07bdb28..df0d00a 100644 --- a/vorago-reb1/examples/nvm.rs +++ b/vorago-reb1/examples/nvm.rs @@ -2,12 +2,15 @@ #![no_main] #![no_std] +use core::fmt::write; + +use cortex_m::{asm, register::control::read}; use cortex_m_rt::entry; use embedded_hal::delay::DelayNs; use panic_rtt_target as _; use rtt_target::{rprintln, rtt_init_print}; use va108xx_hal::{pac, pwm::CountDownTimer, time::Hertz}; -use vorago_reb1::m95m01::M95M01; +use vorago_reb1::m95m01::{M95M01, PAGE_SIZE}; const CLOCK_FREQ: Hertz = Hertz::from_raw(50_000_000); @@ -25,39 +28,30 @@ fn main() -> ! { panic!("status register unexpected values"); } - let mut orig_content: [u8; 16] = [0; 16]; - let mut read_buf: [u8; 16] = [0; 16]; - let write_buf: [u8; 16] = [0; 16]; - for (idx, val) in read_buf.iter_mut().enumerate() { - *val = idx as u8; + let mut orig_content: [u8; 512] = [0; 512]; + let mut read_buf: [u8; 512] = [0; 512]; + let mut write_buf: [u8; 512] = [0; 512]; + for (idx, val) in write_buf.iter_mut().enumerate() { + *val = ((idx as u16) % (u8::MAX as u16 + 1)) as u8; } - nvm.read(0x4000, &mut orig_content).unwrap(); + nvm.read(0, &mut orig_content).unwrap(); - // One byte write and read. - nvm.write(0x4000, &write_buf[0..1]).unwrap(); - nvm.read(0x4000, &mut read_buf[0..1]).unwrap(); - assert_eq!(write_buf[0], read_buf[0]); - read_buf.fill(0); + nvm.write_page(0, 0, &[1, 2, 3, 4]).unwrap(); + nvm.read(0, &mut read_buf[0..4]).unwrap(); - // Four bytes write and read. - nvm.write(0x4000, &write_buf[0..4]).unwrap(); - nvm.read(0x4000, &mut read_buf[0..4]).unwrap(); - assert_eq!(&read_buf[0..4], &write_buf[0..4]); - read_buf.fill(0); - - // Full sixteen bytes - nvm.write(0x4000, &write_buf).unwrap(); - nvm.read(0x4000, &mut read_buf).unwrap(); + // Read the whole content. Write will internally be split across two page bounaries. + nvm.write(0, &write_buf).unwrap(); + // Memory can be read in one go. + nvm.read(0, &mut read_buf).unwrap(); assert_eq!(&read_buf, &write_buf); read_buf.fill(0); - // 3 bytes - nvm.write(0x4000, &write_buf[0..3]).unwrap(); - nvm.read(0x4000, &mut read_buf[0..3]).unwrap(); - assert_eq!(&read_buf[0..3], &write_buf[0..3]); + // Write along page boundary + nvm.write(PAGE_SIZE - 2, &write_buf[0..8]).unwrap(); + nvm.read(PAGE_SIZE - 2, &mut read_buf[0..8]).unwrap(); + assert_eq!(&read_buf[0..8], &write_buf[0..8]); - // Write back original content. - nvm.write(0x4000, &orig_content).unwrap(); + nvm.write(0, &orig_content); loop { timer.delay_ms(500); } diff --git a/vorago-reb1/src/m95m01.rs b/vorago-reb1/src/m95m01.rs index 7dd794a..aaf897a 100644 --- a/vorago-reb1/src/m95m01.rs +++ b/vorago-reb1/src/m95m01.rs @@ -10,6 +10,8 @@ use core::convert::Infallible; use embedded_hal::spi::SpiBus; +pub const PAGE_SIZE: usize = 256; + bitfield::bitfield! { pub struct StatusReg(u8); impl Debug; @@ -53,6 +55,9 @@ pub struct M95M01 { pub spi: RomSpi, } +#[derive(Debug, PartialEq, Eq)] +pub struct PageBoundaryExceededError; + impl M95M01 { pub fn new(syscfg: &mut pac::Sysconfig, sys_clk: impl Into, spi: pac::Spic) -> Self { let spi = RomSpi::new( @@ -105,7 +110,7 @@ impl M95M01 { self.spi.write(&[WRSR, reg.0]) } - fn common_init_write_and_read(&mut self, address: u32, reg: u8) -> Result<(), Infallible> { + fn common_init_write_and_read(&mut self, address: usize, reg: u8) -> Result<(), Infallible> { nb::block!(self.writes_are_done())?; self.spi.flush()?; if reg == WRITE { @@ -114,13 +119,14 @@ impl M95M01 { } else { self.spi.write_fifo_unchecked(READ as u32); } - self.spi.write_fifo_unchecked((address >> 16) & 0xff); - self.spi.write_fifo_unchecked((address >> 8) & 0xff); - self.spi.write_fifo_unchecked(address & 0xff); + self.spi.write_fifo_unchecked((address as u32 >> 16) & 0xff); + self.spi + .write_fifo_unchecked((address as u32 & 0x00ff00) >> 8); + self.spi.write_fifo_unchecked(address as u32 & 0xff); Ok(()) } - fn common_read(&mut self, address: u32) -> Result<(), Infallible> { + fn common_read(&mut self, address: usize) -> Result<(), Infallible> { self.common_init_write_and_read(address, READ)?; for _ in 0..4 { // Pump the FIFO. @@ -131,24 +137,60 @@ impl M95M01 { Ok(()) } - pub fn write(&mut self, address: u32, data: &[u8]) -> Result<(), Infallible> { - self.common_init_write_and_read(address, WRITE)?; + pub fn write(&mut self, mut address: usize, mut data: &[u8]) -> Result<(), Infallible> { + // Loop until all data is written + while !data.is_empty() { + // Calculate the page and the offset within the page from the address + let page = address / PAGE_SIZE; + let offset = address % PAGE_SIZE; + + // Calculate how much space is left in the current page + let space_left = PAGE_SIZE - offset; + + // Determine how much data to write in the current page + let to_write = data.len().min(space_left); + + // Write the current portion of the data + self.write_page(page, offset, &data[..to_write]).unwrap(); + + // Update the address and data for the next iteration + address += to_write; + data = &data[to_write..]; + } + + Ok(()) + } + + pub fn write_page( + &mut self, + page: usize, + offset: usize, + data: &[u8], + ) -> Result<(), PageBoundaryExceededError> { + // Check that the total data to be written does not exceed the page boundary + if offset + data.len() > PAGE_SIZE { + return Err(PageBoundaryExceededError); + } + + self.common_init_write_and_read(page * PAGE_SIZE + offset, WRITE) + .unwrap(); for val in data.iter().take(data.len() - 1) { - nb::block!(self.spi.write_fifo(*val as u32))?; + nb::block!(self.spi.write_fifo(*val as u32)).unwrap(); self.spi.read_fifo_unchecked(); } nb::block!(self .spi - .write_fifo(*data.last().unwrap() as u32 | BMSTART_BMSTOP_MASK))?; - self.spi.flush()?; - nb::block!(self.writes_are_done())?; + .write_fifo(*data.last().unwrap() as u32 | BMSTART_BMSTOP_MASK)) + .unwrap(); + self.spi.flush().unwrap(); + nb::block!(self.writes_are_done()).unwrap(); Ok(()) } - pub fn read(&mut self, address: u32, buf: &mut [u8]) -> Result<(), Infallible> { + pub fn read(&mut self, address: usize, buf: &mut [u8]) -> Result<(), Infallible> { self.common_read(address)?; for val in buf.iter_mut() { - nb::block!(self.spi.write_fifo(0))?; + self.spi.write_fifo_unchecked(0); *val = (nb::block!(self.spi.read_fifo()).unwrap() & 0xff) as u8; } nb::block!(self.spi.write_fifo(BMSTART_BMSTOP_MASK))?; @@ -156,10 +198,10 @@ impl M95M01 { Ok(()) } - pub fn verify(&mut self, address: u32, data: &[u8]) -> Result { + pub fn verify(&mut self, address: usize, data: &[u8]) -> Result { self.common_read(address)?; for val in data.iter() { - nb::block!(self.spi.write_fifo(0))?; + self.spi.write_fifo_unchecked(0); let read_val = (nb::block!(self.spi.read_fifo()).unwrap() & 0xff) as u8; if read_val != *val { return Ok(false);