mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 00:02:28 +00:00
wiznet: add version check to initialization sequence
This commit is contained in:
parent
26e660722c
commit
c4b88b5781
@ -8,10 +8,17 @@ pub use w5100s::W5100S;
|
|||||||
pub(crate) trait SealedChip {
|
pub(crate) trait SealedChip {
|
||||||
type Address;
|
type Address;
|
||||||
|
|
||||||
|
/// The version of the chip as reported by the VERSIONR register.
|
||||||
|
/// This is used to verify that the chip is supported by the driver,
|
||||||
|
/// and that SPI communication is working.
|
||||||
|
const CHIP_VERSION: u8;
|
||||||
|
|
||||||
const COMMON_MODE: Self::Address;
|
const COMMON_MODE: Self::Address;
|
||||||
const COMMON_MAC: Self::Address;
|
const COMMON_MAC: Self::Address;
|
||||||
const COMMON_SOCKET_INTR: Self::Address;
|
const COMMON_SOCKET_INTR: Self::Address;
|
||||||
const COMMON_PHY_CFG: Self::Address;
|
const COMMON_PHY_CFG: Self::Address;
|
||||||
|
const COMMON_VERSION: Self::Address;
|
||||||
|
|
||||||
const SOCKET_MODE: Self::Address;
|
const SOCKET_MODE: Self::Address;
|
||||||
const SOCKET_COMMAND: Self::Address;
|
const SOCKET_COMMAND: Self::Address;
|
||||||
const SOCKET_RXBUF_SIZE: Self::Address;
|
const SOCKET_RXBUF_SIZE: Self::Address;
|
||||||
|
@ -11,10 +11,13 @@ impl super::Chip for W5100S {}
|
|||||||
impl super::SealedChip for W5100S {
|
impl super::SealedChip for W5100S {
|
||||||
type Address = u16;
|
type Address = u16;
|
||||||
|
|
||||||
|
const CHIP_VERSION: u8 = 0x51;
|
||||||
|
|
||||||
const COMMON_MODE: Self::Address = 0x00;
|
const COMMON_MODE: Self::Address = 0x00;
|
||||||
const COMMON_MAC: Self::Address = 0x09;
|
const COMMON_MAC: Self::Address = 0x09;
|
||||||
const COMMON_SOCKET_INTR: Self::Address = 0x16;
|
const COMMON_SOCKET_INTR: Self::Address = 0x16;
|
||||||
const COMMON_PHY_CFG: Self::Address = 0x3c;
|
const COMMON_PHY_CFG: Self::Address = 0x3c;
|
||||||
|
const COMMON_VERSION: Self::Address = 0x80;
|
||||||
|
|
||||||
const SOCKET_MODE: Self::Address = SOCKET_BASE + 0x00;
|
const SOCKET_MODE: Self::Address = SOCKET_BASE + 0x00;
|
||||||
const SOCKET_COMMAND: Self::Address = SOCKET_BASE + 0x01;
|
const SOCKET_COMMAND: Self::Address = SOCKET_BASE + 0x01;
|
||||||
|
@ -15,10 +15,13 @@ impl super::Chip for W5500 {}
|
|||||||
impl super::SealedChip for W5500 {
|
impl super::SealedChip for W5500 {
|
||||||
type Address = (RegisterBlock, u16);
|
type Address = (RegisterBlock, u16);
|
||||||
|
|
||||||
|
const CHIP_VERSION: u8 = 0x04;
|
||||||
|
|
||||||
const COMMON_MODE: Self::Address = (RegisterBlock::Common, 0x00);
|
const COMMON_MODE: Self::Address = (RegisterBlock::Common, 0x00);
|
||||||
const COMMON_MAC: Self::Address = (RegisterBlock::Common, 0x09);
|
const COMMON_MAC: Self::Address = (RegisterBlock::Common, 0x09);
|
||||||
const COMMON_SOCKET_INTR: Self::Address = (RegisterBlock::Common, 0x18);
|
const COMMON_SOCKET_INTR: Self::Address = (RegisterBlock::Common, 0x18);
|
||||||
const COMMON_PHY_CFG: Self::Address = (RegisterBlock::Common, 0x2E);
|
const COMMON_PHY_CFG: Self::Address = (RegisterBlock::Common, 0x2E);
|
||||||
|
const COMMON_VERSION: Self::Address = (RegisterBlock::Common, 0x39);
|
||||||
|
|
||||||
const SOCKET_MODE: Self::Address = (RegisterBlock::Socket0, 0x00);
|
const SOCKET_MODE: Self::Address = (RegisterBlock::Socket0, 0x00);
|
||||||
const SOCKET_COMMAND: Self::Address = (RegisterBlock::Socket0, 0x01);
|
const SOCKET_COMMAND: Self::Address = (RegisterBlock::Socket0, 0x01);
|
||||||
|
@ -24,9 +24,57 @@ pub(crate) struct WiznetDevice<C, SPI> {
|
|||||||
_phantom: PhantomData<C>,
|
_phantom: PhantomData<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error type when initializing a new Wiznet device
|
||||||
|
pub enum InitError<SE> {
|
||||||
|
/// Error occurred when sending or receiving SPI data
|
||||||
|
SpiError(SE),
|
||||||
|
/// The chip returned a version that isn't expected or supported
|
||||||
|
InvalidChipVersion {
|
||||||
|
/// The version that is supported
|
||||||
|
expected: u8,
|
||||||
|
/// The version that was returned by the chip
|
||||||
|
actual: u8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SE> From<SE> for InitError<SE> {
|
||||||
|
fn from(e: SE) -> Self {
|
||||||
|
InitError::SpiError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SE> core::fmt::Debug for InitError<SE>
|
||||||
|
where
|
||||||
|
SE: core::fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self {
|
||||||
|
InitError::SpiError(e) => write!(f, "SpiError({:?})", e),
|
||||||
|
InitError::InvalidChipVersion { expected, actual } => {
|
||||||
|
write!(f, "InvalidChipVersion {{ expected: {}, actual: {} }}", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
impl<SE> defmt::Format for InitError<SE>
|
||||||
|
where
|
||||||
|
SE: defmt::Format,
|
||||||
|
{
|
||||||
|
fn format(&self, f: defmt::Formatter) {
|
||||||
|
match self {
|
||||||
|
InitError::SpiError(e) => defmt::write!(f, "SpiError({})", e),
|
||||||
|
InitError::InvalidChipVersion { expected, actual } => {
|
||||||
|
defmt::write!(f, "InvalidChipVersion {{ expected: {}, actual: {} }}", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<C: Chip, SPI: SpiDevice> WiznetDevice<C, SPI> {
|
impl<C: Chip, SPI: SpiDevice> WiznetDevice<C, SPI> {
|
||||||
/// Create and initialize the driver
|
/// Create and initialize the driver
|
||||||
pub async fn new(spi: SPI, mac_addr: [u8; 6]) -> Result<Self, SPI::Error> {
|
pub async fn new(spi: SPI, mac_addr: [u8; 6]) -> Result<Self, InitError<SPI::Error>> {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
spi,
|
spi,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
@ -35,6 +83,18 @@ impl<C: Chip, SPI: SpiDevice> WiznetDevice<C, SPI> {
|
|||||||
// Reset device
|
// Reset device
|
||||||
this.bus_write(C::COMMON_MODE, &[0x80]).await?;
|
this.bus_write(C::COMMON_MODE, &[0x80]).await?;
|
||||||
|
|
||||||
|
// Check the version of the chip
|
||||||
|
let mut version = [0];
|
||||||
|
this.bus_read(C::COMMON_VERSION, &mut version).await?;
|
||||||
|
if version[0] != C::CHIP_VERSION {
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
defmt::error!("invalid chip version: {} (expected {})", version[0], C::CHIP_VERSION);
|
||||||
|
return Err(InitError::InvalidChipVersion {
|
||||||
|
actual: version[0],
|
||||||
|
expected: C::CHIP_VERSION,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Enable interrupt pin
|
// Enable interrupt pin
|
||||||
this.bus_write(C::COMMON_SOCKET_INTR, &[0x01]).await?;
|
this.bus_write(C::COMMON_SOCKET_INTR, &[0x01]).await?;
|
||||||
// Enable receive interrupt
|
// Enable receive interrupt
|
||||||
|
@ -15,6 +15,7 @@ use embedded_hal_async::digital::Wait;
|
|||||||
use embedded_hal_async::spi::SpiDevice;
|
use embedded_hal_async::spi::SpiDevice;
|
||||||
|
|
||||||
use crate::chip::Chip;
|
use crate::chip::Chip;
|
||||||
|
pub use crate::device::InitError;
|
||||||
use crate::device::WiznetDevice;
|
use crate::device::WiznetDevice;
|
||||||
|
|
||||||
// If you change this update the docs of State
|
// If you change this update the docs of State
|
||||||
@ -105,7 +106,7 @@ pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevi
|
|||||||
spi_dev: SPI,
|
spi_dev: SPI,
|
||||||
int: INT,
|
int: INT,
|
||||||
mut reset: RST,
|
mut reset: RST,
|
||||||
) -> (Device<'a>, Runner<'a, C, SPI, INT, RST>) {
|
) -> Result<(Device<'a>, Runner<'a, C, SPI, INT, RST>), InitError<SPI::Error>> {
|
||||||
// Reset the chip.
|
// Reset the chip.
|
||||||
reset.set_low().ok();
|
reset.set_low().ok();
|
||||||
// Ensure the reset is registered.
|
// Ensure the reset is registered.
|
||||||
@ -116,10 +117,11 @@ pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevi
|
|||||||
// Slowest is w5100s which is 100ms, so let's just wait that.
|
// Slowest is w5100s which is 100ms, so let's just wait that.
|
||||||
Timer::after_millis(100).await;
|
Timer::after_millis(100).await;
|
||||||
|
|
||||||
let mac = WiznetDevice::new(spi_dev, mac_addr).await.unwrap();
|
let mac = WiznetDevice::new(spi_dev, mac_addr).await?;
|
||||||
|
|
||||||
let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ethernet(mac_addr));
|
let (runner, device) = ch::new(&mut state.ch_state, ch::driver::HardwareAddress::Ethernet(mac_addr));
|
||||||
(
|
|
||||||
|
Ok((
|
||||||
device,
|
device,
|
||||||
Runner {
|
Runner {
|
||||||
ch: runner,
|
ch: runner,
|
||||||
@ -127,5 +129,5 @@ pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevi
|
|||||||
int,
|
int,
|
||||||
_reset: reset,
|
_reset: reset,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,8 @@ async fn main(spawner: Spawner) {
|
|||||||
w5500_int,
|
w5500_int,
|
||||||
w5500_reset,
|
w5500_reset,
|
||||||
)
|
)
|
||||||
.await;
|
.await
|
||||||
|
.unwrap();
|
||||||
unwrap!(spawner.spawn(ethernet_task(runner)));
|
unwrap!(spawner.spawn(ethernet_task(runner)));
|
||||||
|
|
||||||
// Generate random seed
|
// Generate random seed
|
||||||
|
@ -66,7 +66,8 @@ async fn main(spawner: Spawner) {
|
|||||||
w5500_int,
|
w5500_int,
|
||||||
w5500_reset,
|
w5500_reset,
|
||||||
)
|
)
|
||||||
.await;
|
.await
|
||||||
|
.unwrap();
|
||||||
unwrap!(spawner.spawn(ethernet_task(runner)));
|
unwrap!(spawner.spawn(ethernet_task(runner)));
|
||||||
|
|
||||||
// Generate random seed
|
// Generate random seed
|
||||||
|
@ -65,7 +65,8 @@ async fn main(spawner: Spawner) {
|
|||||||
w5500_int,
|
w5500_int,
|
||||||
w5500_reset,
|
w5500_reset,
|
||||||
)
|
)
|
||||||
.await;
|
.await
|
||||||
|
.unwrap();
|
||||||
unwrap!(spawner.spawn(ethernet_task(runner)));
|
unwrap!(spawner.spawn(ethernet_task(runner)));
|
||||||
|
|
||||||
// Generate random seed
|
// Generate random seed
|
||||||
|
@ -63,7 +63,8 @@ async fn main(spawner: Spawner) {
|
|||||||
w5500_int,
|
w5500_int,
|
||||||
w5500_reset,
|
w5500_reset,
|
||||||
)
|
)
|
||||||
.await;
|
.await
|
||||||
|
.unwrap();
|
||||||
unwrap!(spawner.spawn(ethernet_task(runner)));
|
unwrap!(spawner.spawn(ethernet_task(runner)));
|
||||||
|
|
||||||
// Generate random seed
|
// Generate random seed
|
||||||
|
@ -80,7 +80,9 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let mac_addr = [0x02, 234, 3, 4, 82, 231];
|
let mac_addr = [0x02, 234, 3, 4, 82, 231];
|
||||||
static STATE: StaticCell<State<2, 2>> = StaticCell::new();
|
static STATE: StaticCell<State<2, 2>> = StaticCell::new();
|
||||||
let state = STATE.init(State::<2, 2>::new());
|
let state = STATE.init(State::<2, 2>::new());
|
||||||
let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset).await;
|
let (device, runner) = embassy_net_wiznet::new(mac_addr, state, spi, w5500_int, w5500_reset)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
unwrap!(spawner.spawn(ethernet_task(runner)));
|
unwrap!(spawner.spawn(ethernet_task(runner)));
|
||||||
|
|
||||||
let config = embassy_net::Config::dhcpv4(Default::default());
|
let config = embassy_net::Config::dhcpv4(Default::default());
|
||||||
|
@ -59,7 +59,8 @@ async fn main(spawner: Spawner) {
|
|||||||
w5500_int,
|
w5500_int,
|
||||||
w5500_reset,
|
w5500_reset,
|
||||||
)
|
)
|
||||||
.await;
|
.await
|
||||||
|
.unwrap();
|
||||||
unwrap!(spawner.spawn(ethernet_task(runner)));
|
unwrap!(spawner.spawn(ethernet_task(runner)));
|
||||||
|
|
||||||
// Generate random seed
|
// Generate random seed
|
||||||
|
Loading…
Reference in New Issue
Block a user