somethings wrong..

This commit is contained in:
Robin Müller 2024-09-19 18:37:44 +02:00
parent 6e48bf8d24
commit 21186af3bf
Signed by: muellerr
GPG Key ID: A649FB78196E3849
5 changed files with 63 additions and 49 deletions

View File

@ -105,7 +105,6 @@ fn main() -> ! {
(RomSck, RomMiso, RomMosi), (RomSck, RomMiso, RomMosi),
// These values are taken from the vorago bootloader app, don't want to experiment here.. // These values are taken from the vorago bootloader app, don't want to experiment here..
SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)), SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)),
None,
); );
let mut nvm = let mut nvm =
M95M01::new(ExclusiveDevice::new_no_delay(spi, dummy_pin::DummyPin::new_low()).unwrap()) M95M01::new(ExclusiveDevice::new_no_delay(spi, dummy_pin::DummyPin::new_low()).unwrap())

View File

@ -17,7 +17,7 @@ use crate::{
PeripheralSelect, PeripheralSelect,
}; };
use core::{convert::Infallible, fmt::Debug, marker::PhantomData, ops::Deref}; use core::{convert::Infallible, fmt::Debug, marker::PhantomData, ops::Deref};
use embedded_hal::spi::Mode; use embedded_hal::spi::{Mode, MODE_0};
//================================================================================================== //==================================================================================================
// Defintions // Defintions
@ -363,6 +363,12 @@ impl<HwCs: HwCsProvider> TransferConfigProvider for TransferConfigWithHwcs<HwCs>
/// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details /// Configuration options for the whole SPI bus. See Programmer Guide p.92 for more details
pub struct SpiConfig { pub struct SpiConfig {
clk: SpiClkConfig, clk: SpiClkConfig,
// SPI mode configuration
pub init_mode: Mode,
/// If this is enabled, all data in the FIFO is transmitted in a single frame unless
/// 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,
/// By default, configure SPI for master mode (ms == false) /// By default, configure SPI for master mode (ms == false)
ms: bool, ms: bool,
/// Slave output disable. Useful if separate GPIO pins or decoders are used for CS control /// Slave output disable. Useful if separate GPIO pins or decoders are used for CS control
@ -376,6 +382,8 @@ pub struct SpiConfig {
impl Default for SpiConfig { impl Default for SpiConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
init_mode: MODE_0,
blockmode: true,
// Default value is definitely valid. // Default value is definitely valid.
clk: SpiClkConfig::from_div(DEFAULT_CLK_DIV).unwrap(), clk: SpiClkConfig::from_div(DEFAULT_CLK_DIV).unwrap(),
ms: Default::default(), ms: Default::default(),
@ -392,6 +400,16 @@ impl SpiConfig {
self self
} }
pub fn blockmode(mut self, enable: bool) -> Self {
self.blockmode = enable;
self
}
pub fn mode(mut self, mode: Mode) -> Self {
self.init_mode = mode;
self
}
pub fn clk_cfg(mut self, clk_cfg: SpiClkConfig) -> Self { pub fn clk_cfg(mut self, clk_cfg: SpiClkConfig) -> Self {
self.clk = clk_cfg; self.clk = clk_cfg;
self self
@ -599,28 +617,17 @@ where
spi: SpiI, spi: SpiI,
pins: (Sck, Miso, Mosi), pins: (Sck, Miso, Mosi),
spi_cfg: SpiConfig, spi_cfg: SpiConfig,
transfer_cfg: Option<&TransferConfig>,
) -> Self { ) -> Self {
enable_peripheral_clock(syscfg, SpiI::PERIPH_SEL); enable_peripheral_clock(syscfg, SpiI::PERIPH_SEL);
let SpiConfig { let SpiConfig {
clk, clk,
init_mode,
blockmode,
ms, ms,
slave_output_disable, slave_output_disable,
loopback_mode, loopback_mode,
master_delayer_capture, master_delayer_capture,
} = spi_cfg; } = spi_cfg;
let mut init_mode = embedded_hal::spi::MODE_0;
let mut ss = 0;
let mut init_blockmode = false;
if let Some(transfer_cfg) = transfer_cfg {
if let Some(mode) = transfer_cfg.mode {
init_mode = mode;
}
if transfer_cfg.hw_cs != HwChipSelectId::Invalid {
ss = transfer_cfg.hw_cs as u8;
}
init_blockmode = transfer_cfg.blockmode;
}
let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(init_mode); let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(init_mode);
spi.ctrl0().write(|w| { spi.ctrl0().write(|w| {
@ -639,8 +646,8 @@ where
w.sod().bit(slave_output_disable); w.sod().bit(slave_output_disable);
w.ms().bit(ms); w.ms().bit(ms);
w.mdlycap().bit(master_delayer_capture); w.mdlycap().bit(master_delayer_capture);
w.blockmode().bit(init_blockmode); w.blockmode().bit(blockmode);
unsafe { w.ss().bits(ss) } unsafe { w.ss().bits(0) }
}); });
spi.clkprescale() spi.clkprescale()
.write(|w| unsafe { w.bits(clk.prescale_val as u32) }); .write(|w| unsafe { w.bits(clk.prescale_val as u32) });
@ -658,7 +665,7 @@ where
cfg: spi_cfg, cfg: spi_cfg,
sys_clk: sys_clk.into(), sys_clk: sys_clk.into(),
fill_word: Default::default(), fill_word: Default::default(),
blockmode: init_blockmode, blockmode,
word: PhantomData, word: PhantomData,
}, },
pins, pins,
@ -685,15 +692,22 @@ where
#[inline] #[inline]
pub fn spi(&self) -> &SpiI; pub fn spi(&self) -> &SpiI;
/// Configure the hardware chip select given a hardware chip select ID.
#[inline] #[inline]
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId); pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId);
/// Configure the hardware chip select given a physical hardware CS pin.
#[inline] #[inline]
pub fn cfg_hw_cs_with_pin<HwCs: OptionalHwCs<SpiI>>(&mut self, _hwcs: &HwCs); pub fn cfg_hw_cs_with_pin<HwCs: OptionalHwCs<SpiI>>(&mut self, _hwcs: &HwCs);
/// Disables the hardware chip select functionality. This can be used when performing
/// external chip select handling, for example with GPIO pins.
#[inline] #[inline]
pub fn cfg_hw_cs_disable(&mut self); pub fn cfg_hw_cs_disable(&mut self);
/// Utility function to configure all relevant transfer parameters in one go.
/// This is useful if multiple devices with different clock and mode configurations
/// are connected to one bus.
pub fn cfg_transfer<HwCs: OptionalHwCs<SpiI>>( pub fn cfg_transfer<HwCs: OptionalHwCs<SpiI>>(
&mut self, transfer_cfg: &TransferConfigWithHwcs<HwCs> &mut self, transfer_cfg: &TransferConfigWithHwcs<HwCs>
); );
@ -769,6 +783,7 @@ where
self.spi.perid().read().bits() self.spi.perid().read().bits()
} }
/// Configure the hardware chip select given a hardware chip select ID.
#[inline] #[inline]
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId) { pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId) {
if hw_cs == HwChipSelectId::Invalid { if hw_cs == HwChipSelectId::Invalid {
@ -783,11 +798,15 @@ where
}); });
} }
/// Configure the hardware chip select given a physical hardware CS pin.
#[inline] #[inline]
pub fn cfg_hw_cs_with_pin<HwCs: OptionalHwCs<SpiInstance>>(&mut self, _: &HwCs) { pub fn cfg_hw_cs_with_pin<HwCs: OptionalHwCs<SpiInstance>>(&mut self, _: &HwCs) {
self.cfg_hw_cs(HwCs::CS_ID); self.cfg_hw_cs(HwCs::CS_ID);
} }
/// Disables the hardware chip select functionality. This can be used when performing
/// external chip select handling, for example with GPIO pins.
#[inline]
pub fn cfg_hw_cs_disable(&mut self) { pub fn cfg_hw_cs_disable(&mut self) {
self.spi.ctrl1().modify(|_, w| { self.spi.ctrl1().modify(|_, w| {
w.sod().set_bit(); w.sod().set_bit();
@ -795,6 +814,9 @@ where
}); });
} }
/// Utility function to configure all relevant transfer parameters in one go.
/// This is useful if multiple devices with different clock and mode configurations
/// are connected to one bus.
pub fn cfg_transfer<HwCs: OptionalHwCs<SpiInstance>>( pub fn cfg_transfer<HwCs: OptionalHwCs<SpiInstance>>(
&mut self, &mut self,
transfer_cfg: &TransferConfigWithHwcs<HwCs>, transfer_cfg: &TransferConfigWithHwcs<HwCs>,
@ -966,7 +988,7 @@ where
<Word as TryFrom<u32>>::Error: core::fmt::Debug, <Word as TryFrom<u32>>::Error: core::fmt::Debug,
{ {
fn read(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { fn read(&mut self, words: &mut [Word]) -> Result<(), Self::Error> {
self.transfer_preparation(words)?; //self.transfer_preparation(words)?;
let mut current_read_idx = 0; let mut current_read_idx = 0;
let mut current_write_idx = self.initial_send_fifo_pumping_with_fill_words(words.len()); let mut current_write_idx = self.initial_send_fifo_pumping_with_fill_words(words.len());
loop { loop {
@ -986,7 +1008,7 @@ where
} }
fn write(&mut self, words: &[Word]) -> Result<(), Self::Error> { fn write(&mut self, words: &[Word]) -> Result<(), Self::Error> {
self.transfer_preparation(words)?; // self.transfer_preparation(words)?;
let mut current_write_idx = self.initial_send_fifo_pumping_with_words(words); let mut current_write_idx = self.initial_send_fifo_pumping_with_words(words);
while current_write_idx < words.len() { while current_write_idx < words.len() {
self.send_blocking(words[current_write_idx]); self.send_blocking(words[current_write_idx]);
@ -1000,7 +1022,7 @@ where
} }
fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> { fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> {
self.transfer_preparation(write)?; //self.transfer_preparation(write)?;
let mut current_read_idx = 0; let mut current_read_idx = 0;
let mut current_write_idx = self.initial_send_fifo_pumping_with_words(write); let mut current_write_idx = self.initial_send_fifo_pumping_with_words(write);
while current_read_idx < read.len() || current_write_idx < write.len() { while current_read_idx < read.len() || current_write_idx < write.len() {
@ -1018,7 +1040,7 @@ where
} }
fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> {
self.transfer_preparation(words)?; //self.transfer_preparation(words)?;
let mut current_read_idx = 0; let mut current_read_idx = 0;
let mut current_write_idx = self.initial_send_fifo_pumping_with_words(words); let mut current_write_idx = self.initial_send_fifo_pumping_with_words(words);

View File

@ -124,7 +124,7 @@ fn main() -> ! {
} }
let pinsa = PinsA::new(&mut dp.sysconfig, None, dp.porta); let pinsa = PinsA::new(&mut dp.sysconfig, None, dp.porta);
let spi_cfg = SpiConfig::default(); let spi_cfg = SpiConfig::default().clk_cfg(SpiClkConfig::from_clk(SYS_CLK, 3.MHz()).unwrap());
let (sck, mosi, miso) = ( let (sck, mosi, miso) = (
pinsa.pa20.into_funsel_2(), pinsa.pa20.into_funsel_2(),
pinsa.pa19.into_funsel_2(), pinsa.pa19.into_funsel_2(),
@ -143,19 +143,13 @@ fn main() -> ! {
.set_high() .set_high()
.expect("Setting accelerometer chip select high failed"); .expect("Setting accelerometer chip select high failed");
let transfer_cfg = TransferConfigWithHwcs::new_no_hw_cs( let transfer_cfg = TransferConfigWithHwcs::new_no_hw_cs(None, Some(spi::MODE_0), true, false);
Some(SpiClkConfig::from_clk(SYS_CLK, 3.MHz()).unwrap()),
Some(spi::MODE_0),
true,
false,
);
let spi = Spi::new( let spi = Spi::new(
&mut dp.sysconfig, &mut dp.sysconfig,
50.MHz(), 50.MHz(),
dp.spib, dp.spib,
(sck, miso, mosi), (sck, miso, mosi),
spi_cfg, spi_cfg,
Some(&transfer_cfg.downgrade()),
) )
.downgrade(); .downgrade();
let delay_provider = CountDownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim1); let delay_provider = CountDownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim1);

View File

@ -30,15 +30,10 @@ fn main() -> ! {
(RomSck, RomMiso, RomMosi), (RomSck, RomMiso, RomMosi),
// These values are taken from the vorago bootloader app, don't want to experiment here.. // These values are taken from the vorago bootloader app, don't want to experiment here..
SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)), SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)),
None,
); );
spi.cfg_mode(MODE_0);
spi.cfg_hw_cs(va108xx_hal::spi::HwChipSelectId::Id0);
spi.spi().ctrl1().modify(|_, w| w.blockmode().set_bit());
let mut read_buf: [u8; 2] = [0; 2]; let mut read_buf: [u8; 2] = [0; 2];
spi.transfer(&mut read_buf, &[RDSR, 0]); spi.transfer(&mut read_buf, &[RDSR, 0]);
rprintln!("read buf {:?}", read_buf); rprintln!("read buf {:?}", read_buf);
/*
let mut nvm = let mut nvm =
M95M01::new(ExclusiveDevice::new_no_delay(spi, dummy_pin::DummyPin::new_low()).unwrap()) M95M01::new(ExclusiveDevice::new_no_delay(spi, dummy_pin::DummyPin::new_low()).unwrap())
.expect("creating NVM structure failed"); .expect("creating NVM structure failed");
@ -56,6 +51,5 @@ fn main() -> ! {
nvm.write(0x4000, &write_buf).unwrap(); nvm.write(0x4000, &write_buf).unwrap();
nvm.read(0x4000, &mut read_buf[0..4]).unwrap(); nvm.read(0x4000, &mut read_buf[0..4]).unwrap();
assert_eq!(&read_buf[0..4], write_buf); assert_eq!(&read_buf[0..4], write_buf);
*/
loop {} loop {}
} }

View File

@ -1,5 +1,5 @@
use core::fmt::Debug; use core::fmt::Debug;
use embedded_hal::spi::SpiDevice; use embedded_hal::spi::{Operation, SpiDevice};
bitfield::bitfield! { bitfield::bitfield! {
pub struct StatusReg(u8); pub struct StatusReg(u8);
@ -97,13 +97,15 @@ where
pub fn write(&mut self, address: u32, data: &[u8]) -> Result<(), Spi::Error> { pub fn write(&mut self, address: u32, data: &[u8]) -> Result<(), Spi::Error> {
nb::block!(self.writes_are_done())?; nb::block!(self.writes_are_done())?;
self.write_enable()?; self.write_enable()?;
self.spi.write(&[ self.spi.transaction(&mut [
Operation::Write(&[
WRITE, WRITE,
((address >> 16) & 0xff) as u8, ((address >> 16) & 0xff) as u8,
((address >> 8) & 0xff) as u8, ((address >> 8) & 0xff) as u8,
(address & 0xff) as u8, (address & 0xff) as u8,
]),
Operation::Write(data),
])?; ])?;
self.spi.write(data)?;
Ok(()) Ok(())
} }
@ -112,13 +114,16 @@ where
return Err(Error::BufTooShort); return Err(Error::BufTooShort);
} }
nb::block!(self.writes_are_done())?; nb::block!(self.writes_are_done())?;
self.spi.write(&[
self.spi.transaction(&mut [
Operation::Write(&[
READ, READ,
((address >> 16) & 0xff) as u8, ((address >> 16) & 0xff) as u8,
((address >> 8) & 0xff) as u8, ((address >> 8) & 0xff) as u8,
(address & 0xff) as u8, (address & 0xff) as u8,
]),
Operation::Read(buf),
])?; ])?;
self.spi.read(buf)?;
Ok(()) Ok(())
} }