Compare commits

...

3 Commits

Author SHA1 Message Date
Harry Ho d8b1132b8a examples: Replace delay_ns with cortex-m delay 2021-06-03 15:06:24 +08:00
Harry Ho 999ca5f08a spi: Replace delay_ns func pointer with delay on cortex-m
* SPI NSS nanosecond delays now only takes place on Cortex-M CPUs
2021-06-03 15:03:43 +08:00
Harry Ho 9de8d77a24 Restore embedded_hal DelayUs for device init 2021-06-03 13:38:59 +08:00
5 changed files with 53 additions and 46 deletions

View File

@ -32,16 +32,17 @@ nal = [
"embedded-time", "embedded-nal", "heapless", "embedded-time", "embedded-nal", "heapless",
"smoltcp-phy", "smoltcp/socket-tcp", "smoltcp/ethernet" "smoltcp-phy", "smoltcp/socket-tcp", "smoltcp/ethernet"
] ]
cortex-m-cpu = ["cortex-m"]
# Example-based features # Example-based features
smoltcp-examples = [ smoltcp-examples = [
"smoltcp-phy", "smoltcp/socket-tcp", "smoltcp/ethernet" "smoltcp-phy", "smoltcp/socket-tcp", "smoltcp/ethernet"
] ]
tx_stm32f407 = [ tx_stm32f407 = [
"stm32f4xx-hal/stm32f407", "cortex-m", "cortex-m-rtic", "stm32f4xx-hal/stm32f407", "cortex-m", "cortex-m-rtic", "cortex-m-cpu",
"panic-itm", "log" "panic-itm", "log"
] ]
tcp_stm32f407 = [ tcp_stm32f407 = [
"stm32f4xx-hal/stm32f407", "cortex-m", "cortex-m-rt", "cortex-m-rtic", "stm32f4xx-hal/stm32f407", "cortex-m", "cortex-m-rt", "cortex-m-rtic", "cortex-m-cpu",
"smoltcp-examples", "panic-itm", "log"] "smoltcp-examples", "panic-itm", "log"]
default = [] default = []

View File

@ -79,8 +79,7 @@ use stm32f4xx_hal::{
}; };
type SpiEth = enc424j600::Enc424j600< type SpiEth = enc424j600::Enc424j600<
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>, Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
PA4<Output<PushPull>>, PA4<Output<PushPull>>
fn(u32) -> ()
>; >;
pub struct NetStorage { pub struct NetStorage {
@ -153,14 +152,12 @@ const APP: () = {
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ), Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
clocks); clocks);
let delay_ns_fp: fn(u32) -> () = |time_ns| { SpiEth::new(spi_eth_port, spi1_nss)
cortex_m::asm::delay((time_ns*21)/125 + 1) .cpu_freq_mhz(168)
};
SpiEth::new(spi_eth_port, spi1_nss, delay_ns_fp)
}; };
// Init controller // Init controller
match spi_eth.reset() { match spi_eth.reset(&mut delay) {
Ok(_) => { Ok(_) => {
iprintln!(stim0, "Initializing Ethernet...") iprintln!(stim0, "Initializing Ethernet...")
} }

View File

@ -29,8 +29,7 @@ use stm32f4xx_hal::{
}; };
type SpiEth = enc424j600::Enc424j600< type SpiEth = enc424j600::Enc424j600<
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>, Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
PA4<Output<PushPull>>, PA4<Output<PushPull>>
fn(u32) -> ()
>; >;
#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] #[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
@ -84,14 +83,12 @@ const APP: () = {
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ), Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
clocks); clocks);
let delay_ns: fn(u32) -> () = |time_ns| { SpiEth::new(spi_eth_port, spi1_nss)
cortex_m::asm::delay((time_ns*21)/125 + 1) .cpu_freq_mhz(168)
};
SpiEth::new(spi_eth_port, spi1_nss, delay_ns)
}; };
// Init // Init
match spi_eth.reset() { match spi_eth.reset(&mut delay) {
Ok(_) => { Ok(_) => {
iprintln!(stim0, "Initializing Ethernet...") iprintln!(stim0, "Initializing Ethernet...")
} }

View File

@ -4,6 +4,7 @@ pub mod spi;
use embedded_hal::{ use embedded_hal::{
blocking::{ blocking::{
spi::Transfer, spi::Transfer,
delay::DelayUs,
}, },
digital::v2::OutputPin, digital::v2::OutputPin,
}; };
@ -43,32 +44,36 @@ impl From<spi::Error> for Error {
/// ENC424J600 controller in SPI mode /// ENC424J600 controller in SPI mode
pub struct Enc424j600<SPI: Transfer<u8>, pub struct Enc424j600<SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin> {
F: FnMut(u32) -> ()> { spi_port: spi::SpiPort<SPI, NSS>,
spi_port: spi::SpiPort<SPI, NSS, F>,
rx_buf: rx::RxBuffer, rx_buf: rx::RxBuffer,
tx_buf: tx::TxBuffer tx_buf: tx::TxBuffer,
} }
impl <SPI: Transfer<u8>, impl <SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin> Enc424j600<SPI, NSS> {
F: FnMut(u32) -> ()> Enc424j600<SPI, NSS, F> { pub fn new(spi: SPI, nss: NSS) -> Self {
pub fn new(spi: SPI, nss: NSS, delay_ns: F) -> Self {
Enc424j600 { Enc424j600 {
spi_port: spi::SpiPort::new(spi, nss, delay_ns), spi_port: spi::SpiPort::new(spi, nss),
rx_buf: rx::RxBuffer::new(), rx_buf: rx::RxBuffer::new(),
tx_buf: tx::TxBuffer::new() tx_buf: tx::TxBuffer::new(),
} }
} }
pub fn init(&mut self) -> Result<(), Error> { #[cfg(feature = "cortex-m-cpu")]
self.reset()?; pub fn cpu_freq_mhz(mut self, freq: u32) -> Self {
self.spi_port = self.spi_port.cpu_freq_mhz(freq);
self
}
pub fn init(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), Error> {
self.reset(delay)?;
self.init_rxbuf()?; self.init_rxbuf()?;
self.init_txbuf()?; self.init_txbuf()?;
Ok(()) Ok(())
} }
pub fn reset(&mut self) -> Result<(), Error> { pub fn reset(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), Error> {
// Write 0x1234 to EUDAST // Write 0x1234 to EUDAST
self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?; self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?;
// Verify that EUDAST is 0x1234 // Verify that EUDAST is 0x1234
@ -83,13 +88,13 @@ impl <SPI: Transfer<u8>,
} }
// Issue system reset - set ETHRST (ECON2<4>) to 1 // Issue system reset - set ETHRST (ECON2<4>) to 1
self.spi_port.send_opcode(spi::opcodes::SETETHRST)?; self.spi_port.send_opcode(spi::opcodes::SETETHRST)?;
self.spi_port.delay_us(25); delay.delay_us(25);
// Verify that EUDAST is 0x0000 // Verify that EUDAST is 0x0000
eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?; eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
if eudast != 0x0000 { if eudast != 0x0000 {
return Err(Error::RegisterError) return Err(Error::RegisterError)
} }
self.spi_port.delay_us(256); delay.delay_us(256);
Ok(()) Ok(())
} }
@ -144,8 +149,7 @@ impl <SPI: Transfer<u8>,
} }
impl <SPI: Transfer<u8>, impl <SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin> EthPhy for Enc424j600<SPI, NSS> {
F: FnMut(u32) -> ()> EthPhy for Enc424j600<SPI, NSS, F> {
/// Receive the next packet and return it /// Receive the next packet and return it
/// Set is_poll to true for returning until PKTIF is set; /// Set is_poll to true for returning until PKTIF is set;
/// Set is_poll to false for returning Err when PKTIF is not set /// Set is_poll to false for returning Err when PKTIF is not set

View File

@ -62,11 +62,11 @@ pub mod addrs {
/// Struct for SPI I/O interface on ENC424J600 /// Struct for SPI I/O interface on ENC424J600
/// Note: stm32f4xx_hal::spi's pins include: SCK, MISO, MOSI /// Note: stm32f4xx_hal::spi's pins include: SCK, MISO, MOSI
pub struct SpiPort<SPI: Transfer<u8>, pub struct SpiPort<SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin> {
F: FnMut(u32) -> ()> {
spi: SPI, spi: SPI,
nss: NSS, nss: NSS,
delay_ns: F, #[cfg(feature = "cortex-m-cpu")]
cpu_freq_mhz: f32,
} }
pub enum Error { pub enum Error {
@ -76,19 +76,25 @@ pub enum Error {
#[allow(unused_must_use)] #[allow(unused_must_use)]
impl <SPI: Transfer<u8>, impl <SPI: Transfer<u8>,
NSS: OutputPin, NSS: OutputPin> SpiPort<SPI, NSS> {
F: FnMut(u32) -> ()> SpiPort<SPI, NSS, F> {
// TODO: return as Result() // TODO: return as Result()
pub fn new(spi: SPI, mut nss: NSS, delay_ns: F) -> Self { pub fn new(spi: SPI, mut nss: NSS) -> Self {
nss.set_high(); nss.set_high();
SpiPort { SpiPort {
spi, spi,
nss, nss,
delay_ns, #[cfg(feature = "cortex-m-cpu")]
cpu_freq_mhz: 0.,
} }
} }
#[cfg(feature = "cortex-m-cpu")]
pub fn cpu_freq_mhz(mut self, freq: u32) -> Self {
self.cpu_freq_mhz = freq as f32;
self
}
pub fn read_reg_8b(&mut self, addr: u8) -> Result<u8, Error> { pub fn read_reg_8b(&mut self, addr: u8) -> Result<u8, Error> {
// Using RCRU instruction to read using unbanked (full) address // Using RCRU instruction to read using unbanked (full) address
let mut buf: [u8; 4] = [0; 4]; let mut buf: [u8; 4] = [0; 4];
@ -180,10 +186,6 @@ impl <SPI: Transfer<u8>,
} }
} }
pub fn delay_us(&mut self, duration: u32) {
(self.delay_ns)(duration * 1000)
}
// TODO: Actual data should start from buf[0], not buf[1] // TODO: Actual data should start from buf[0], not buf[1]
// Completes an SPI transfer for reading data to the given buffer, // Completes an SPI transfer for reading data to the given buffer,
// or writing data from the buffer. // or writing data from the buffer.
@ -195,10 +197,12 @@ impl <SPI: Transfer<u8>,
assert!(buf.len() > data_length); assert!(buf.len() > data_length);
// Enable chip select // Enable chip select
self.nss.set_low(); self.nss.set_low();
// >=50ns min. CS_n setup time
#[cfg(feature = "cortex-m-cpu")]
match opcode { match opcode {
opcodes::RCRU | opcodes::WCRU | opcodes::RCRU | opcodes::WCRU |
opcodes::RRXDATA | opcodes::WGPDATA => { opcodes::RRXDATA | opcodes::WGPDATA => {
(self.delay_ns)(50); // >=50ns min. CS_n setup time cortex_m::asm::delay((0.05*(self.cpu_freq_mhz+1.)) as u32);
} }
_ => { } _ => { }
} }
@ -209,9 +213,13 @@ impl <SPI: Transfer<u8>,
opcodes::RCRU | opcodes::WCRU | opcodes::RCRU | opcodes::WCRU |
opcodes::RRXDATA | opcodes::WGPDATA => { opcodes::RRXDATA | opcodes::WGPDATA => {
// Disable chip select // Disable chip select
(self.delay_ns)(50); // >=50ns min. CS_n hold time // >=50ns min. CS_n hold time
#[cfg(feature = "cortex-m-cpu")]
cortex_m::asm::delay((0.05*(self.cpu_freq_mhz+1.)) as u32);
self.nss.set_high(); self.nss.set_high();
(self.delay_ns)(20); // >=20ns min. CS_n disable time // >=20ns min. CS_n disable time
#[cfg(feature = "cortex-m-cpu")]
cortex_m::asm::delay((0.02*(self.cpu_freq_mhz+1.)) as u32);
} }
_ => { } _ => { }
} }