This commit is contained in:
parent
c34fbb01f5
commit
6e48bf8d24
@ -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, MODE_0, MODE_1, MODE_2, MODE_3};
|
use embedded_hal::spi::Mode;
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Defintions
|
// Defintions
|
||||||
@ -226,6 +226,7 @@ hw_cs_pins!(
|
|||||||
pub struct RomSck;
|
pub struct RomSck;
|
||||||
pub struct RomMosi;
|
pub struct RomMosi;
|
||||||
pub struct RomMiso;
|
pub struct RomMiso;
|
||||||
|
pub struct RomCs;
|
||||||
|
|
||||||
impl Sealed for RomSck {}
|
impl Sealed for RomSck {}
|
||||||
impl PinSck<pac::Spic> for RomSck {}
|
impl PinSck<pac::Spic> for RomSck {}
|
||||||
@ -233,6 +234,7 @@ impl Sealed for RomMosi {}
|
|||||||
impl PinMosi<pac::Spic> for RomMosi {}
|
impl PinMosi<pac::Spic> for RomMosi {}
|
||||||
impl Sealed for RomMiso {}
|
impl Sealed for RomMiso {}
|
||||||
impl PinMiso<pac::Spic> for RomMiso {}
|
impl PinMiso<pac::Spic> for RomMiso {}
|
||||||
|
impl Sealed for RomCs {}
|
||||||
|
|
||||||
hw_cs_pins!(
|
hw_cs_pins!(
|
||||||
pac::Spic, SpiPort::Portc:
|
pac::Spic, SpiPort::Portc:
|
||||||
@ -250,6 +252,12 @@ hw_cs_pins!(
|
|||||||
(PA20, AltFunc3, HwChipSelectId::Id4, HwCs4SpiCPortA),
|
(PA20, AltFunc3, HwChipSelectId::Id4, HwCs4SpiCPortA),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
impl HwCsProvider for RomCs {
|
||||||
|
const CS_ID: HwChipSelectId = HwChipSelectId::Id0;
|
||||||
|
const SPI_PORT: SpiPort = SpiPort::Portc;
|
||||||
|
}
|
||||||
|
impl OptionalHwCs<pac::Spic> for RomCs {}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Config
|
// Config
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -674,6 +682,18 @@ where
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn fill_word(&self) -> Word;
|
pub fn fill_word(&self) -> Word;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn spi(&self) -> &SpiI;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId);
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn cfg_hw_cs_with_pin<HwCs: OptionalHwCs<SpiI>>(&mut self, _hwcs: &HwCs);
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn cfg_hw_cs_disable(&mut self);
|
||||||
|
|
||||||
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>
|
||||||
);
|
);
|
||||||
@ -698,6 +718,11 @@ impl<SpiInstance: Instance, Word: WordProvider> SpiBase<SpiInstance, Word>
|
|||||||
where
|
where
|
||||||
<Word as TryFrom<u32>>::Error: core::fmt::Debug,
|
<Word as TryFrom<u32>>::Error: core::fmt::Debug,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
pub fn spi(&self) -> &SpiInstance {
|
||||||
|
&self.spi
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cfg_clock(&mut self, cfg: SpiClkConfig) {
|
pub fn cfg_clock(&mut self, cfg: SpiClkConfig) {
|
||||||
self.spi
|
self.spi
|
||||||
@ -717,12 +742,7 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cfg_mode(&mut self, mode: Mode) {
|
pub fn cfg_mode(&mut self, mode: Mode) {
|
||||||
let (cpo_bit, cph_bit) = match mode {
|
let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(mode);
|
||||||
MODE_0 => (false, false),
|
|
||||||
MODE_1 => (false, true),
|
|
||||||
MODE_2 => (true, false),
|
|
||||||
MODE_3 => (true, true),
|
|
||||||
};
|
|
||||||
self.spi.ctrl0().modify(|_, w| {
|
self.spi.ctrl0().modify(|_, w| {
|
||||||
w.spo().bit(cpo_bit);
|
w.spo().bit(cpo_bit);
|
||||||
w.sph().bit(cph_bit)
|
w.sph().bit(cph_bit)
|
||||||
|
@ -33,6 +33,8 @@ panic-halt = "0.2"
|
|||||||
nb = "1"
|
nb = "1"
|
||||||
rtt-target = "0.5"
|
rtt-target = "0.5"
|
||||||
panic-rtt-target = "0.1"
|
panic-rtt-target = "0.1"
|
||||||
|
embedded-hal-bus = "0.2"
|
||||||
|
dummy-pin = "1"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
|
61
vorago-reb1/examples/nvm.rs
Normal file
61
vorago-reb1/examples/nvm.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use cortex_m_rt::entry;
|
||||||
|
use embedded_hal::spi::{SpiBus, MODE_0};
|
||||||
|
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||||
|
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},
|
||||||
|
time::Hertz,
|
||||||
|
};
|
||||||
|
use vorago_reb1::m95m01::{regs::RDSR, M95M01};
|
||||||
|
|
||||||
|
const CLOCK_FREQ: Hertz = Hertz::from_raw(50_000_000);
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
rtt_init_print!();
|
||||||
|
rprintln!("-- VA108XX REB1 NVM example --");
|
||||||
|
|
||||||
|
let mut dp = pac::Peripherals::take().unwrap();
|
||||||
|
let cp = cortex_m::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let mut spi = Spi::new(
|
||||||
|
&mut dp.sysconfig,
|
||||||
|
CLOCK_FREQ,
|
||||||
|
dp.spic,
|
||||||
|
(RomSck, RomMiso, RomMosi),
|
||||||
|
// These values are taken from the vorago bootloader app, don't want to experiment here..
|
||||||
|
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];
|
||||||
|
spi.transfer(&mut read_buf, &[RDSR, 0]);
|
||||||
|
rprintln!("read buf {:?}", read_buf);
|
||||||
|
/*
|
||||||
|
let mut nvm =
|
||||||
|
M95M01::new(ExclusiveDevice::new_no_delay(spi, dummy_pin::DummyPin::new_low()).unwrap())
|
||||||
|
.expect("creating NVM structure failed");
|
||||||
|
let status_reg = nvm.read_status_reg().expect("reading status reg failed");
|
||||||
|
rprintln!("status reg: {:?}", status_reg);
|
||||||
|
if status_reg.zero_segment() == 0b111 {
|
||||||
|
panic!("status register unexpected values");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut read_buf: [u8; 16] = [0; 16];
|
||||||
|
nvm.read(0x4000, &mut read_buf[0..4])
|
||||||
|
.expect("reading NVM failed");
|
||||||
|
rprintln!("NVM address 0x4000: {:x?}", &read_buf[0..4]);
|
||||||
|
let write_buf: [u8; 4] = [1, 2, 3, 4];
|
||||||
|
nvm.write(0x4000, &write_buf).unwrap();
|
||||||
|
nvm.read(0x4000, &mut read_buf[0..4]).unwrap();
|
||||||
|
assert_eq!(&read_buf[0..4], write_buf);
|
||||||
|
*/
|
||||||
|
loop {}
|
||||||
|
}
|
@ -1,13 +1,15 @@
|
|||||||
|
use core::fmt::Debug;
|
||||||
use embedded_hal::spi::SpiDevice;
|
use embedded_hal::spi::SpiDevice;
|
||||||
|
|
||||||
bitfield::bitfield! {
|
bitfield::bitfield! {
|
||||||
pub struct StatusReg(u8);
|
pub struct StatusReg(u8);
|
||||||
impl Debug;
|
impl Debug;
|
||||||
u8;
|
u8;
|
||||||
status_register_write_protect, _: 7, 0;
|
pub status_register_write_protect, _: 7;
|
||||||
block_protection_bits, set_block_protection_bits: 3, 2;
|
pub zero_segment, _: 6, 4;
|
||||||
write_enable_latch, _: 1;
|
pub block_protection_bits, set_block_protection_bits: 3, 2;
|
||||||
write_in_progress, _: 0;
|
pub write_enable_latch, _: 1;
|
||||||
|
pub write_in_progress, _: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers.
|
// Registers.
|
||||||
@ -33,18 +35,22 @@ pub struct M95M01<Spi: SpiDevice> {
|
|||||||
spi: Spi,
|
spi: Spi,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Error<SpiError> {
|
#[derive(Debug)]
|
||||||
|
pub enum Error<SpiError: Debug> {
|
||||||
Spi(SpiError),
|
Spi(SpiError),
|
||||||
BufTooShort,
|
BufTooShort,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SpiError> From<SpiError> for Error<SpiError> {
|
impl<SpiError: Debug> From<SpiError> for Error<SpiError> {
|
||||||
fn from(value: SpiError) -> Self {
|
fn from(value: SpiError) -> Self {
|
||||||
Self::Spi(value)
|
Self::Spi(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Spi: SpiDevice> M95M01<Spi> {
|
impl<Spi: SpiDevice> M95M01<Spi>
|
||||||
|
where
|
||||||
|
Spi::Error: Debug,
|
||||||
|
{
|
||||||
pub fn new(spi: Spi) -> Result<Self, Spi::Error> {
|
pub fn new(spi: Spi) -> Result<Self, Spi::Error> {
|
||||||
let mut spi_dev = Self { spi };
|
let mut spi_dev = Self { spi };
|
||||||
spi_dev.clear_block_protection()?;
|
spi_dev.clear_block_protection()?;
|
||||||
@ -59,21 +65,27 @@ impl<Spi: SpiDevice> M95M01<Spi> {
|
|||||||
// Wait until the write-in-progress state is cleared. This exposes a [nb] API, so this function
|
// Wait until the write-in-progress state is cleared. This exposes a [nb] API, so this function
|
||||||
// will return [nb::Error::WouldBlock] if the EEPROM is still busy.
|
// will return [nb::Error::WouldBlock] if the EEPROM is still busy.
|
||||||
pub fn writes_are_done(&mut self) -> nb::Result<(), Spi::Error> {
|
pub fn writes_are_done(&mut self) -> nb::Result<(), Spi::Error> {
|
||||||
let mut read: [u8; 2] = [0; 2];
|
let rdsr = self.read_status_reg()?;
|
||||||
self.spi.transfer(&mut read, &[regs::RDSR, 0x00])?;
|
|
||||||
let rdsr = StatusReg(read[1]);
|
|
||||||
if rdsr.write_in_progress() {
|
if rdsr.write_in_progress() {
|
||||||
return Err(nb::Error::WouldBlock);
|
return Err(nb::Error::WouldBlock);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_status_reg(&mut self) -> Result<StatusReg, Spi::Error> {
|
||||||
|
let mut write_read: [u8; 2] = [regs::RDSR, 0x00];
|
||||||
|
self.spi.transfer_in_place(&mut write_read)?;
|
||||||
|
Ok(StatusReg(write_read[1]))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_enable(&mut self) -> Result<(), Spi::Error> {
|
pub fn write_enable(&mut self) -> Result<(), Spi::Error> {
|
||||||
self.spi.write(&[regs::WREN])
|
self.spi.write(&[regs::WREN])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_block_protection(&mut self) -> Result<(), Spi::Error> {
|
pub fn clear_block_protection(&mut self) -> Result<(), Spi::Error> {
|
||||||
self.spi.write(&[WREN, WRSR, 0x00])
|
// Has to be written separately.
|
||||||
|
self.spi.write(&[WREN])?;
|
||||||
|
self.spi.write(&[WRSR, 0x00])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_block_protection(&mut self) -> Result<(), Spi::Error> {
|
pub fn set_block_protection(&mut self) -> Result<(), Spi::Error> {
|
||||||
@ -83,6 +95,7 @@ impl<Spi: SpiDevice> M95M01<Spi> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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())?;
|
||||||
self.write_enable()?;
|
self.write_enable()?;
|
||||||
self.spi.write(&[
|
self.spi.write(&[
|
||||||
WRITE,
|
WRITE,
|
||||||
@ -94,26 +107,23 @@ impl<Spi: SpiDevice> M95M01<Spi> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(
|
pub fn read(&mut self, address: u32, buf: &mut [u8]) -> Result<(), Error<Spi::Error>> {
|
||||||
&mut self,
|
if buf.len() < buf.len() {
|
||||||
address: u32,
|
|
||||||
size: usize,
|
|
||||||
buf: &mut [u8],
|
|
||||||
) -> Result<(), Error<Spi::Error>> {
|
|
||||||
if buf.len() < size {
|
|
||||||
return Err(Error::BufTooShort);
|
return Err(Error::BufTooShort);
|
||||||
}
|
}
|
||||||
|
nb::block!(self.writes_are_done())?;
|
||||||
self.spi.write(&[
|
self.spi.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,
|
||||||
])?;
|
])?;
|
||||||
self.spi.read(&mut buf[0..size])?;
|
self.spi.read(buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(&mut self, address: u32, data: &[u8]) -> Result<bool, Spi::Error> {
|
pub fn verify(&mut self, address: u32, data: &[u8]) -> Result<bool, Spi::Error> {
|
||||||
|
nb::block!(self.writes_are_done())?;
|
||||||
// Write the read command and address
|
// Write the read command and address
|
||||||
self.spi.write(&[
|
self.spi.write(&[
|
||||||
READ,
|
READ,
|
||||||
|
Loading…
Reference in New Issue
Block a user