3 unstable releases

0.2.0 Dec 27, 2020
0.1.1 Dec 22, 2020
0.1.0 Dec 22, 2020

#531 in Hardware support

MIT/Apache

75KB
1.5K SLoC

ksz8863 Actions Status Crates.io Crates.io docs.rs

A driver for the KSZ8863 (MLL/FLL/RLL) Ethernet Switch.

This driver is split into two main modules:

  • miim for the MII Management Interface (MIIM).
  • smi for the Serial Management Interface (SMI).

While these two terms often refer to same protocol, their usage in the KSZ8863 documentation refers to two distinct protocols and sets of registers. Please refer to the datasheet for details.

These modules contain a type and module for every documented register along with typed access to each of their respective fields. High-level read/write/modify access to these registers are provided via the Miim and Smi types respectively.

Note that the SPI and I2C interfaces are not currently supported, though PRs are welcome.

Usage

At the foundation of this crate are the miim::{Read, Write} and smi::{Read, Write} traits. The first step is to implement these for your respective MIIM and SMI interfaces. For details on how to implement these, visit sections 3.3.10 and 3.3.11 of the datasheet.

Implementing these traits unlocks high level access via the Smi and Miim interface type wrappers. These types provide short-hand methods for reading, writing and modifying registers and their individual fields. The provided API for these types is inspired by the svd2rust crate.

Here is an example of using the Miim.

use ksz8863::{miim, Miim};

fn main() {
    // ... Setup our device and `miim_iface`...

    // Wrap the type that impls the Read/Write traits with `Miim`.
    // Note: We could also wrap `&mut miim_iface` here if we only local scope access is needed.
    let mut miim = Miim(miim_iface);

    // Specify which phy we want to communicate with via its PHY address.
    let mut phy = miim.phy(0);

    // Read the value of the "Basic Control Register".
    assert_eq!(phy.bcr().read().unwrap(), miim::Bcr::default());

    // Modify the "Force 100BT" field of the "Basic Control Register" in place.
    let mut bcr = phy.bcr();
    assert!(bcr.read().unwrap().read().force_fd().bit_is_clear());
    bcr.modify(|w| w.force_fd().set_bit()).unwrap();
    let reg = bcr.read().unwrap();
    assert!(reg != miim::Bcr::default());
    assert!(reg.read().force_fd().bit_is_set());
}

The Smi API is similar, but we don't need to specify a PHY.

use ksz8863::{smi, Smi};

fn main() {
    // ... Setup our device and `smi_iface`...

    let mut smi = Smi(smi_iface);
    assert_eq!(smi.gc1().read().unwrap(), smi::Gc1::default());
    smi.gc1().modify(|w| w.tx_flow_control().clear_bit()).unwrap();
    assert!(smi.gc1().read().unwrap() != smi::Gc1::default());
}

Extras

The Address type in each module represents the unique index at which the register is located.

The State type from each module is a dynamic representation of register state, useful for storing the state of multiple registers in a collection.

The Map type from each module is a collection that is guaranteed to contain the state of all registers. This is useful for remotely monitoring the state of registers while reducing I/O, and for simulating an MIIM/SMI interface in the case that you don't have access to one.

Features

  • hash-32 provides hash32::Hash implementations from the hash32 crate.
  • serde provides Deserialize and Serialize implementations.
  • ufmt provides ufmt::uDebug implementations.

All of these features are opt-in and disabled by default.

Dependencies

~1MB
~28K SLoC