ENC424J600/src/lib.rs

204 lines
8.3 KiB
Rust
Raw Normal View History

#![no_std]
pub mod spi;
use embedded_hal::{
blocking::{
spi::Transfer,
delay::DelayUs,
},
digital::v2::OutputPin,
2020-06-16 17:34:16 +08:00
};
pub mod rx;
2020-06-17 18:26:48 +08:00
pub mod tx;
2020-06-16 17:34:16 +08:00
#[cfg(feature="smoltcp")]
pub mod smoltcp_phy;
2020-06-24 14:17:07 +08:00
pub trait EthController<'c> {
fn init_dev(&mut self, delay: &mut dyn DelayUs<u16>) -> Result<(), EthControllerError>;
2020-06-17 18:26:48 +08:00
fn init_rxbuf(&mut self) -> Result<(), EthControllerError>;
fn init_txbuf(&mut self) -> Result<(), EthControllerError>;
2020-06-24 14:17:07 +08:00
fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError>;
fn send_raw_packet(&mut self, packet: &tx::TxPacket) -> Result<(), EthControllerError>;
2020-06-17 18:26:48 +08:00
fn set_promiscuous(&mut self) -> Result<(), EthControllerError>;
fn read_from_mac(&mut self, mac: &mut [u8]) -> Result<(), EthControllerError>;
2020-06-16 17:34:16 +08:00
}
/// TODO: Improve these error types
pub enum EthControllerError {
2020-06-17 18:26:48 +08:00
SpiPortError,
2020-06-24 14:17:07 +08:00
GeneralError,
// TODO: Better name?
NoRxPacketError
2020-06-16 17:34:16 +08:00
}
impl From<spi::SpiPortError> for EthControllerError {
2020-06-24 14:17:07 +08:00
fn from(_: spi::SpiPortError) -> EthControllerError {
2020-06-17 18:26:48 +08:00
EthControllerError::SpiPortError
}
2020-06-16 17:34:16 +08:00
}
/// Ethernet controller using SPI interface
2020-12-29 11:08:35 +08:00
pub struct SpiEth<SPI: Transfer<u8>,
2020-06-16 17:34:16 +08:00
NSS: OutputPin> {
2020-06-17 18:26:48 +08:00
spi_port: spi::SpiPort<SPI, NSS>,
rx_buf: rx::RxBuffer,
tx_buf: tx::TxBuffer
2020-06-16 17:34:16 +08:00
}
2020-12-29 11:08:35 +08:00
impl <SPI: Transfer<u8>,
2020-06-16 17:34:16 +08:00
NSS: OutputPin> SpiEth<SPI, NSS> {
2020-06-24 14:17:07 +08:00
pub fn new(spi: SPI, nss: NSS) -> Self {
2020-06-17 18:26:48 +08:00
SpiEth {
spi_port: spi::SpiPort::new(spi, nss),
rx_buf: rx::RxBuffer::new(),
tx_buf: tx::TxBuffer::new()
}
2020-06-16 17:34:16 +08:00
}
}
2020-12-29 11:08:35 +08:00
impl <'c, SPI: Transfer<u8>,
2020-06-24 14:17:07 +08:00
NSS: OutputPin> EthController<'c> for SpiEth<SPI, NSS> {
fn init_dev(&mut self, delay: &mut dyn DelayUs<u16>) -> Result<(), EthControllerError> {
2020-06-17 18:26:48 +08:00
// Write 0x1234 to EUDAST
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::EUDAST, 0x1234)?;
2020-06-17 18:26:48 +08:00
// Verify that EUDAST is 0x1234
2020-08-17 15:51:25 +08:00
let mut eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
2020-12-29 11:08:35 +08:00
if eudast != 0x1234 {
2020-06-17 18:26:48 +08:00
return Err(EthControllerError::GeneralError)
}
// Poll CLKRDY (ESTAT<12>) to check if it is set
loop {
2020-08-17 15:51:25 +08:00
let estat = self.spi_port.read_reg_16b(spi::addrs::ESTAT)?;
2020-06-17 18:26:48 +08:00
if estat & 0x1000 == 0x1000 { break }
}
// Set ETHRST (ECON2<4>) to 1
2020-08-17 15:51:25 +08:00
let econ2 = self.spi_port.read_reg_8b(spi::addrs::ECON2)?;
self.spi_port.write_reg_8b(spi::addrs::ECON2, 0x10 | (econ2 & 0b11101111))?;
// Wait for 25us
delay.delay_us(25_u16);
2020-06-17 18:26:48 +08:00
// Verify that EUDAST is 0x0000
2020-08-17 15:51:25 +08:00
eudast = self.spi_port.read_reg_16b(spi::addrs::EUDAST)?;
2020-12-29 11:08:35 +08:00
if eudast != 0x0000 {
2020-06-17 18:26:48 +08:00
return Err(EthControllerError::GeneralError)
}
// Wait for 256us
delay.delay_us(256_u16);
2020-06-17 18:26:48 +08:00
Ok(())
2020-06-16 17:34:16 +08:00
}
fn init_rxbuf(&mut self) -> Result<(), EthControllerError> {
2020-06-17 18:26:48 +08:00
// Set ERXST pointer
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ERXST, self.rx_buf.get_wrap_addr())?;
2020-06-16 17:34:16 +08:00
// Set ERXTAIL pointer
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ERXTAIL, self.rx_buf.get_tail_addr())?;
2020-06-16 17:34:16 +08:00
// Set MAMXFL to maximum number of bytes in each accepted packet
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::MAMXFL, rx::RAW_FRAME_LENGTH_MAX as u16)?;
2020-06-16 17:34:16 +08:00
// Enable RXEN (ECON1<0>)
2020-08-17 15:51:25 +08:00
let econ1 = self.spi_port.read_reg_16b(spi::addrs::ECON1)?;
self.spi_port.write_reg_16b(spi::addrs::ECON1, 0x1 | (econ1 & 0xfffe))?;
2020-06-16 17:34:16 +08:00
Ok(())
}
2020-06-17 18:26:48 +08:00
fn init_txbuf(&mut self) -> Result<(), EthControllerError> {
// Set EGPWRPT pointer
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, 0x0000)?;
2020-06-17 18:26:48 +08:00
Ok(())
}
2020-08-17 15:51:25 +08:00
/// Receive the next packet and return it
2020-06-24 14:17:07 +08:00
/// Set is_poll to true for returning until PKTIF is set;
/// Set is_poll to false for returning Err when PKTIF is not set
2020-12-29 11:08:35 +08:00
fn receive_next(&mut self, is_poll: bool) -> Result<rx::RxPacket, EthControllerError> {
2020-06-16 17:34:16 +08:00
// Poll PKTIF (EIR<4>) to check if it is set
loop {
2020-08-17 15:51:25 +08:00
let eir = self.spi_port.read_reg_16b(spi::addrs::EIR)?;
2020-06-17 18:26:48 +08:00
if eir & 0x40 == 0x40 { break }
2020-06-24 14:17:07 +08:00
if !is_poll {
return Err(EthControllerError::NoRxPacketError)
}
2020-06-16 17:34:16 +08:00
}
// Set ERXRDPT pointer to next_addr
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ERXRDPT, self.rx_buf.get_next_addr())?;
2020-06-16 17:34:16 +08:00
// Read 2 bytes to update next_addr
let mut next_addr_buf = [0; 3];
self.spi_port.read_rxdat(&mut next_addr_buf, 2)?;
self.rx_buf.set_next_addr((next_addr_buf[1] as u16) | ((next_addr_buf[2] as u16) << 8));
// Read 6 bytes to update rsv
let mut rsv_buf = [0; 7];
self.spi_port.read_rxdat(&mut rsv_buf, 6)?;
// Construct an RxPacket
// TODO: can we directly assign to fields instead of using functions?
let mut rx_packet = rx::RxPacket::new();
// Get and update frame length
rx_packet.write_to_rsv(&rsv_buf[1..]);
rx_packet.update_frame_length();
// Read frame bytes
let mut frame_buf = [0; rx::RAW_FRAME_LENGTH_MAX];
2020-12-28 15:57:21 +08:00
self.spi_port.read_rxdat(&mut frame_buf, rx_packet.get_frame_length())?;
2020-06-24 14:17:07 +08:00
rx_packet.copy_frame_from(&frame_buf[1..]);
2020-06-16 17:34:16 +08:00
// Set ERXTAIL pointer to (next_addr - 2)
if self.rx_buf.get_next_addr() > rx::ERXST_DEFAULT {
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ERXTAIL, self.rx_buf.get_next_addr() - 2)?;
2020-06-16 17:34:16 +08:00
} else {
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ERXTAIL, rx::RX_MAX_ADDRESS - 1)?;
2020-06-16 17:34:16 +08:00
}
2020-06-17 18:26:48 +08:00
// Set PKTDEC (ECON1<88>) to decrement PKTCNT
2020-08-17 15:51:25 +08:00
let econ1_hi = self.spi_port.read_reg_8b(spi::addrs::ECON1 + 1)?;
self.spi_port.write_reg_8b(spi::addrs::ECON1 + 1, 0x01 | (econ1_hi & 0xfe))?;
2020-06-16 17:34:16 +08:00
// Return the RxPacket
Ok(rx_packet)
}
2020-06-17 18:26:48 +08:00
/// Send an established packet
2020-06-24 14:17:07 +08:00
fn send_raw_packet(&mut self, packet: &tx::TxPacket) -> Result<(), EthControllerError> {
2020-06-17 18:26:48 +08:00
// Set EGPWRPT pointer to next_addr
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::EGPWRPT, self.tx_buf.get_next_addr())?;
2020-06-17 18:26:48 +08:00
// Copy packet data to SRAM Buffer
2020-12-29 11:08:35 +08:00
// 1-byte Opcode is included
2020-06-17 18:26:48 +08:00
let mut txdat_buf: [u8; tx::RAW_FRAME_LENGTH_MAX + 1] = [0; tx::RAW_FRAME_LENGTH_MAX + 1];
2020-06-24 14:17:07 +08:00
packet.write_frame_to(&mut txdat_buf[1..]);
2020-12-28 15:57:21 +08:00
self.spi_port.write_txdat(&mut txdat_buf, packet.get_frame_length())?;
2020-06-17 18:26:48 +08:00
// Set ETXST to packet start address
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ETXST, self.tx_buf.get_next_addr())?;
2020-06-17 18:26:48 +08:00
// Set ETXLEN to packet length
2020-08-17 15:51:25 +08:00
self.spi_port.write_reg_16b(spi::addrs::ETXLEN, packet.get_frame_length() as u16)?;
2020-06-17 18:26:48 +08:00
// Set TXRTS (ECON1<1>) to start transmission
2020-08-17 15:51:25 +08:00
let mut econ1_lo = self.spi_port.read_reg_8b(spi::addrs::ECON1)?;
self.spi_port.write_reg_8b(spi::addrs::ECON1, 0x02 | (econ1_lo & 0xfd))?;
2020-06-17 18:26:48 +08:00
// Poll TXRTS (ECON1<1>) to check if it is reset
loop {
2020-08-17 15:51:25 +08:00
econ1_lo = self.spi_port.read_reg_8b(spi::addrs::ECON1)?;
2020-06-17 18:26:48 +08:00
if econ1_lo & 0x02 == 0x02 { break }
}
2020-06-24 14:17:07 +08:00
// TODO: Read ETXSTAT to understand Ethernet transmission status
// (See: Register 9-2, ENC424J600 Data Sheet)
2020-06-17 18:26:48 +08:00
// Update TX buffer start address
2020-12-29 11:08:35 +08:00
self.tx_buf.set_next_addr((self.tx_buf.get_next_addr() + packet.get_frame_length() as u16) %
2020-06-17 18:26:48 +08:00
tx::GPBUFEN_DEFAULT);
Ok(())
}
2020-06-16 17:34:16 +08:00
/// Set controller to Promiscuous Mode
fn set_promiscuous(&mut self) -> Result<(), EthControllerError> {
2020-12-29 11:08:35 +08:00
// From Section 10.12, ENC424J600 Data Sheet:
// "To accept all incoming frames regardless of content (Promiscuous mode),
2020-06-17 18:26:48 +08:00
// set the CRCEN, RUNTEN, UCEN, NOTMEEN and MCEN bits."
2020-08-17 15:51:25 +08:00
let erxfcon_lo = self.spi_port.read_reg_8b(spi::addrs::ERXFCON)?;
self.spi_port.write_reg_8b(spi::addrs::ERXFCON, 0b0101_1110 | (erxfcon_lo & 0b1010_0001))?;
2020-06-17 18:26:48 +08:00
Ok(())
2020-06-16 17:34:16 +08:00
}
/// Read MAC to [u8; 6]
2020-06-17 18:26:48 +08:00
fn read_from_mac(&mut self, mac: &mut [u8]) -> Result<(), EthControllerError> {
2020-08-17 15:51:25 +08:00
mac[0] = self.spi_port.read_reg_8b(spi::addrs::MAADR1)?;
mac[1] = self.spi_port.read_reg_8b(spi::addrs::MAADR1 + 1)?;
mac[2] = self.spi_port.read_reg_8b(spi::addrs::MAADR2)?;
mac[3] = self.spi_port.read_reg_8b(spi::addrs::MAADR2 + 1)?;
mac[4] = self.spi_port.read_reg_8b(spi::addrs::MAADR3)?;
mac[5] = self.spi_port.read_reg_8b(spi::addrs::MAADR3 + 1)?;
2020-06-17 18:26:48 +08:00
Ok(())
}
2020-06-16 17:34:16 +08:00
}