Compare commits
3 Commits
ec20970a50
...
d8b1132b8a
Author | SHA1 | Date |
---|---|---|
Harry Ho | d8b1132b8a | |
Harry Ho | 999ca5f08a | |
Harry Ho | 9de8d77a24 |
|
@ -32,16 +32,17 @@ nal = [
|
|||
"embedded-time", "embedded-nal", "heapless",
|
||||
"smoltcp-phy", "smoltcp/socket-tcp", "smoltcp/ethernet"
|
||||
]
|
||||
cortex-m-cpu = ["cortex-m"]
|
||||
# Example-based features
|
||||
smoltcp-examples = [
|
||||
"smoltcp-phy", "smoltcp/socket-tcp", "smoltcp/ethernet"
|
||||
]
|
||||
tx_stm32f407 = [
|
||||
"stm32f4xx-hal/stm32f407", "cortex-m", "cortex-m-rtic",
|
||||
"stm32f4xx-hal/stm32f407", "cortex-m", "cortex-m-rtic", "cortex-m-cpu",
|
||||
"panic-itm", "log"
|
||||
]
|
||||
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"]
|
||||
default = []
|
||||
|
||||
|
|
|
@ -79,8 +79,7 @@ use stm32f4xx_hal::{
|
|||
};
|
||||
type SpiEth = enc424j600::Enc424j600<
|
||||
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
|
||||
PA4<Output<PushPull>>,
|
||||
fn(u32) -> ()
|
||||
PA4<Output<PushPull>>
|
||||
>;
|
||||
|
||||
pub struct NetStorage {
|
||||
|
@ -153,14 +152,12 @@ const APP: () = {
|
|||
Hertz(enc424j600::spi::interfaces::SPI_CLOCK_FREQ),
|
||||
clocks);
|
||||
|
||||
let delay_ns_fp: fn(u32) -> () = |time_ns| {
|
||||
cortex_m::asm::delay((time_ns*21)/125 + 1)
|
||||
};
|
||||
SpiEth::new(spi_eth_port, spi1_nss, delay_ns_fp)
|
||||
SpiEth::new(spi_eth_port, spi1_nss)
|
||||
.cpu_freq_mhz(168)
|
||||
};
|
||||
|
||||
// Init controller
|
||||
match spi_eth.reset() {
|
||||
match spi_eth.reset(&mut delay) {
|
||||
Ok(_) => {
|
||||
iprintln!(stim0, "Initializing Ethernet...")
|
||||
}
|
||||
|
|
|
@ -29,8 +29,7 @@ use stm32f4xx_hal::{
|
|||
};
|
||||
type SpiEth = enc424j600::Enc424j600<
|
||||
Spi<SPI1, (PA5<Alternate<AF5>>, PA6<Alternate<AF5>>, PA7<Alternate<AF5>>)>,
|
||||
PA4<Output<PushPull>>,
|
||||
fn(u32) -> ()
|
||||
PA4<Output<PushPull>>
|
||||
>;
|
||||
|
||||
#[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),
|
||||
clocks);
|
||||
|
||||
let delay_ns: fn(u32) -> () = |time_ns| {
|
||||
cortex_m::asm::delay((time_ns*21)/125 + 1)
|
||||
};
|
||||
SpiEth::new(spi_eth_port, spi1_nss, delay_ns)
|
||||
SpiEth::new(spi_eth_port, spi1_nss)
|
||||
.cpu_freq_mhz(168)
|
||||
};
|
||||
|
||||
// Init
|
||||
match spi_eth.reset() {
|
||||
match spi_eth.reset(&mut delay) {
|
||||
Ok(_) => {
|
||||
iprintln!(stim0, "Initializing Ethernet...")
|
||||
}
|
||||
|
|
36
src/lib.rs
36
src/lib.rs
|
@ -4,6 +4,7 @@ pub mod spi;
|
|||
use embedded_hal::{
|
||||
blocking::{
|
||||
spi::Transfer,
|
||||
delay::DelayUs,
|
||||
},
|
||||
digital::v2::OutputPin,
|
||||
};
|
||||
|
@ -43,32 +44,36 @@ impl From<spi::Error> for Error {
|
|||
|
||||
/// ENC424J600 controller in SPI mode
|
||||
pub struct Enc424j600<SPI: Transfer<u8>,
|
||||
NSS: OutputPin,
|
||||
F: FnMut(u32) -> ()> {
|
||||
spi_port: spi::SpiPort<SPI, NSS, F>,
|
||||
NSS: OutputPin> {
|
||||
spi_port: spi::SpiPort<SPI, NSS>,
|
||||
rx_buf: rx::RxBuffer,
|
||||
tx_buf: tx::TxBuffer
|
||||
tx_buf: tx::TxBuffer,
|
||||
}
|
||||
|
||||
impl <SPI: Transfer<u8>,
|
||||
NSS: OutputPin,
|
||||
F: FnMut(u32) -> ()> Enc424j600<SPI, NSS, F> {
|
||||
pub fn new(spi: SPI, nss: NSS, delay_ns: F) -> Self {
|
||||
NSS: OutputPin> Enc424j600<SPI, NSS> {
|
||||
pub fn new(spi: SPI, nss: NSS) -> Self {
|
||||
Enc424j600 {
|
||||
spi_port: spi::SpiPort::new(spi, nss, delay_ns),
|
||||
spi_port: spi::SpiPort::new(spi, nss),
|
||||
rx_buf: rx::RxBuffer::new(),
|
||||
tx_buf: tx::TxBuffer::new()
|
||||
tx_buf: tx::TxBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self) -> Result<(), Error> {
|
||||
self.reset()?;
|
||||
#[cfg(feature = "cortex-m-cpu")]
|
||||
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_txbuf()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) -> Result<(), Error> {
|
||||
pub fn reset(&mut self, delay: &mut impl DelayUs<u16>) -> Result<(), Error> {
|
||||
// Write 0x1234 to EUDAST
|
||||
self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?;
|
||||
// Verify that EUDAST is 0x1234
|
||||
|
@ -83,13 +88,13 @@ impl <SPI: Transfer<u8>,
|
|||
}
|
||||
// Issue system reset - set ETHRST (ECON2<4>) to 1
|
||||
self.spi_port.send_opcode(spi::opcodes::SETETHRST)?;
|
||||
self.spi_port.delay_us(25);
|
||||
delay.delay_us(25);
|
||||
// Verify that EUDAST is 0x0000
|
||||
eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
|
||||
if eudast != 0x0000 {
|
||||
return Err(Error::RegisterError)
|
||||
}
|
||||
self.spi_port.delay_us(256);
|
||||
delay.delay_us(256);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -144,8 +149,7 @@ impl <SPI: Transfer<u8>,
|
|||
}
|
||||
|
||||
impl <SPI: Transfer<u8>,
|
||||
NSS: OutputPin,
|
||||
F: FnMut(u32) -> ()> EthPhy for Enc424j600<SPI, NSS, F> {
|
||||
NSS: OutputPin> EthPhy for Enc424j600<SPI, NSS> {
|
||||
/// Receive the next packet and return it
|
||||
/// Set is_poll to true for returning until PKTIF is set;
|
||||
/// Set is_poll to false for returning Err when PKTIF is not set
|
||||
|
|
36
src/spi.rs
36
src/spi.rs
|
@ -62,11 +62,11 @@ pub mod addrs {
|
|||
/// Struct for SPI I/O interface on ENC424J600
|
||||
/// Note: stm32f4xx_hal::spi's pins include: SCK, MISO, MOSI
|
||||
pub struct SpiPort<SPI: Transfer<u8>,
|
||||
NSS: OutputPin,
|
||||
F: FnMut(u32) -> ()> {
|
||||
NSS: OutputPin> {
|
||||
spi: SPI,
|
||||
nss: NSS,
|
||||
delay_ns: F,
|
||||
#[cfg(feature = "cortex-m-cpu")]
|
||||
cpu_freq_mhz: f32,
|
||||
}
|
||||
|
||||
pub enum Error {
|
||||
|
@ -76,19 +76,25 @@ pub enum Error {
|
|||
|
||||
#[allow(unused_must_use)]
|
||||
impl <SPI: Transfer<u8>,
|
||||
NSS: OutputPin,
|
||||
F: FnMut(u32) -> ()> SpiPort<SPI, NSS, F> {
|
||||
NSS: OutputPin> SpiPort<SPI, NSS> {
|
||||
// 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();
|
||||
|
||||
SpiPort {
|
||||
spi,
|
||||
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> {
|
||||
// Using RCRU instruction to read using unbanked (full) address
|
||||
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]
|
||||
// Completes an SPI transfer for reading data to the given buffer,
|
||||
// or writing data from the buffer.
|
||||
|
@ -195,10 +197,12 @@ impl <SPI: Transfer<u8>,
|
|||
assert!(buf.len() > data_length);
|
||||
// Enable chip select
|
||||
self.nss.set_low();
|
||||
// >=50ns min. CS_n setup time
|
||||
#[cfg(feature = "cortex-m-cpu")]
|
||||
match opcode {
|
||||
opcodes::RCRU | opcodes::WCRU |
|
||||
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::RRXDATA | opcodes::WGPDATA => {
|
||||
// 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.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);
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue