diff --git a/va108xx-hal/src/spi.rs b/va108xx-hal/src/spi.rs index 390eaea..5589d45 100644 --- a/va108xx-hal/src/spi.rs +++ b/va108xx-hal/src/spi.rs @@ -26,6 +26,8 @@ use embedded_hal::spi::{Mode, MODE_0}; // FIFO has a depth of 16. const FILL_DEPTH: usize = 12; +pub const BMSTART_BMSTOP_MASK: u32 = 1 << 31; + pub const DEFAULT_CLK_DIV: u16 = 2; #[derive(Debug, PartialEq, Eq, Copy, Clone)] @@ -369,6 +371,8 @@ pub struct SpiConfig { /// the BMSTOP bit is set on a dataword. A frame is defined as CSn being active for the /// duration of multiple data words. Defaults to true. pub blockmode: bool, + /// This enables the stalling of the SPI SCK if in blockmode and the FIFO is empty. + pub bmstall: bool, /// By default, configure SPI for master mode (ms == false) ms: bool, /// Slave output disable. Useful if separate GPIO pins or decoders are used for CS control @@ -384,6 +388,7 @@ impl Default for SpiConfig { Self { init_mode: MODE_0, blockmode: true, + bmstall: true, // Default value is definitely valid. clk: SpiClkConfig::from_div(DEFAULT_CLK_DIV).unwrap(), ms: Default::default(), @@ -623,6 +628,7 @@ where clk, init_mode, blockmode, + bmstall, ms, slave_output_disable, loopback_mode, @@ -647,6 +653,7 @@ where w.ms().bit(ms); w.mdlycap().bit(master_delayer_capture); w.blockmode().bit(blockmode); + w.bmstall().bit(bmstall); unsafe { w.ss().bits(0) } }); spi.clkprescale() @@ -850,15 +857,15 @@ where /// Sends a word to the slave #[inline(always)] - fn send_blocking(&self, word: Word) { + fn send_blocking(&self, data: u32) { // TODO: Upper limit for wait cycles to avoid complete hangups? while self.spi.status().read().tnf().bit_is_clear() {} - self.send(word) + self.send(data) } #[inline(always)] - fn send(&self, word: Word) { - self.spi.data().write(|w| unsafe { w.bits(word.into()) }); + fn send(&self, data: u32) { + self.spi.data().write(|w| unsafe { w.bits(data) }); } /// Read a word from the slave. Must be preceeded by a [`send`](Self::send) call @@ -905,7 +912,11 @@ where // Fill the first half of the write FIFO let mut current_write_idx = 0; for _ in 0..core::cmp::min(FILL_DEPTH, words.len()) { - self.send_blocking(words[current_write_idx]); + if current_write_idx == words.len() - 1 { + self.send_blocking(words[current_write_idx].into() | BMSTART_BMSTOP_MASK); + } else { + self.send_blocking(words[current_write_idx].into()); + } current_write_idx += 1; } if self.blockmode { @@ -921,7 +932,11 @@ where // Fill the first half of the write FIFO let mut current_write_idx = 0; for _ in 0..core::cmp::min(FILL_DEPTH, send_len) { - self.send_blocking(self.fill_word); + if current_write_idx == send_len - 1 { + self.send_blocking(self.fill_word.into() | BMSTART_BMSTOP_MASK); + } else { + self.send_blocking(self.fill_word.into()); + } current_write_idx += 1; } if self.blockmode { @@ -992,14 +1007,18 @@ where let mut current_read_idx = 0; let mut current_write_idx = self.initial_send_fifo_pumping_with_fill_words(words.len()); loop { - if current_write_idx < words.len() { - self.send_blocking(self.fill_word); - current_write_idx += 1; - } if current_read_idx < words.len() { words[current_read_idx] = self.read_blocking(); current_read_idx += 1; } + if current_write_idx < words.len() { + if current_write_idx == words.len() - 1 { + self.send_blocking(self.fill_word.into() | BMSTART_BMSTOP_MASK); + } else { + self.send_blocking(self.fill_word.into()); + } + current_write_idx += 1; + } if current_read_idx >= words.len() && current_write_idx >= words.len() { break; } @@ -1011,7 +1030,11 @@ where // self.transfer_preparation(words)?; let mut current_write_idx = self.initial_send_fifo_pumping_with_words(words); while current_write_idx < words.len() { - self.send_blocking(words[current_write_idx]); + if current_write_idx == words.len() - 1 { + self.send_blocking(words[current_write_idx].into() | BMSTART_BMSTOP_MASK); + } else { + self.send_blocking(words[current_write_idx].into()); + } current_write_idx += 1; // Ignore received words. if self.spi.status().read().rne().bit_is_set() { @@ -1027,7 +1050,11 @@ where let mut current_write_idx = self.initial_send_fifo_pumping_with_words(write); while current_read_idx < read.len() || current_write_idx < write.len() { if current_write_idx < write.len() { - self.send_blocking(write[current_write_idx]); + if current_write_idx == write.len() - 1 { + self.send_blocking(write[current_write_idx].into() | BMSTART_BMSTOP_MASK); + } else { + self.send_blocking(write[current_write_idx].into()); + } current_write_idx += 1; } if current_read_idx < read.len() { @@ -1046,7 +1073,11 @@ where while current_read_idx < words.len() || current_write_idx < words.len() { if current_write_idx < words.len() { - self.send_blocking(words[current_write_idx]); + if current_write_idx == words.len() - 1 { + self.send_blocking(words[current_write_idx].into() | BMSTART_BMSTOP_MASK); + } else { + self.send_blocking(words[current_write_idx].into()); + } current_write_idx += 1; } if current_read_idx < words.len() && current_read_idx < current_write_idx { diff --git a/vorago-reb1/examples/nvm.rs b/vorago-reb1/examples/nvm.rs index 3e19ddc..3224738 100644 --- a/vorago-reb1/examples/nvm.rs +++ b/vorago-reb1/examples/nvm.rs @@ -8,10 +8,16 @@ use panic_rtt_target as _; use rtt_target::{rprintln, rtt_init_print}; use va108xx_hal::{ pac, - spi::{RomCs, RomMiso, RomMosi, RomSck, Spi, SpiClkConfig, SpiConfig, TransferConfigWithHwcs}, + spi::{ + RomCs, RomMiso, RomMosi, RomSck, Spi, SpiClkConfig, SpiConfig, TransferConfigWithHwcs, + BMSTART_BMSTOP_MASK, + }, time::Hertz, }; -use vorago_reb1::m95m01::{regs::RDSR, M95M01}; +use vorago_reb1::m95m01::{ + regs::{RDSR, WREN}, + StatusReg, M95M01, +}; const CLOCK_FREQ: Hertz = Hertz::from_raw(50_000_000); @@ -23,7 +29,7 @@ fn main() -> ! { let mut dp = pac::Peripherals::take().unwrap(); let cp = cortex_m::Peripherals::take().unwrap(); - let mut spi = Spi::new( + let mut spi = Spi::::new( &mut dp.sysconfig, CLOCK_FREQ, dp.spic, @@ -32,8 +38,21 @@ fn main() -> ! { SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)), ); let mut read_buf: [u8; 2] = [0; 2]; - spi.transfer(&mut read_buf, &[RDSR, 0]); + let spi = spi.spi(); + unsafe { + spi.data().write(|w| w.bits(RDSR.into())); + spi.data().write(|w| w.bits(0 | BMSTART_BMSTOP_MASK)); + } + while spi.status().read().tfe().bit_is_clear() {} + while spi.status().read().rne().bit_is_clear() {} + let dummy = spi.data().read().bits(); + while spi.status().read().rne().bit_is_clear() {} + let reg = StatusReg(spi.data().read().bits() as u8); + rprintln!("status reg {:?}", reg); + //spi.transfer(&mut read_buf, &[RDSR, 0]); rprintln!("read buf {:?}", read_buf); + //spi.write(&[WREN]); + /* let mut nvm = M95M01::new(ExclusiveDevice::new_no_delay(spi, dummy_pin::DummyPin::new_low()).unwrap()) .expect("creating NVM structure failed"); @@ -51,5 +70,6 @@ fn main() -> ! { nvm.write(0x4000, &write_buf).unwrap(); nvm.read(0x4000, &mut read_buf[0..4]).unwrap(); assert_eq!(&read_buf[0..4], write_buf); + */ loop {} }