Skip to content

Commit 65be6a8

Browse files
More docs, renames
1 parent 2ad785e commit 65be6a8

File tree

5 files changed

+71
-11
lines changed

5 files changed

+71
-11
lines changed

connectivity/drivers/emac/CompositeEMAC.md

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,66 @@ How does the DMA know where in RAM to read and write packets, though? On every e
3232

3333
![DMA descriptor ring](doc/stm32f2-eth-dma-descriptors.png)
3434

35-
A descriptor is a few-word-long structure in memory that contains control information and one or more pointers to memory buffers (which contain the actual packet data). For Tx, the DMA will fetch the descriptor, and then transmit the data in the buffers. For Rx, the DMA will fetch the descriptor, then write the packet to the descriptor's buffers. Either way, when done with the descriptor, the DMA will write status information (e.g. whether the checksum passed, or what timestamp the packet was sent at) back to the descriptor, set a flag, and then interrupt the CPU to tell it it has something to process.
36-
37-
But we don't want the DMA to have to wait for the CPU, do we? To avoid this, each descriptor also specifies a "next descriptor", either via an offset or a pointer. The DMA can move to this next descriptor and start processing it right away to send or receive the next packet. The CPU will process the completed descriptor on its own time and give it back to the DMA. In this manner, as long as your ring of descriptors is big enough and your CPU can keep up with processing them, the CPU and MAC never have to wait for each other!
35+
A descriptor is a structure in memory that contains control information and one or more pointers to memory buffers (which contain the actual packet data). For Tx, the DMA will fetch the descriptor, then transmit the data in the buffers. For Rx, the DMA will fetch the descriptor, then write the packet to the descriptor's buffers. Either way, when the MAC is done with the descriptor, the DMA will write back status information (e.g. whether the checksum passed, or what timestamp the packet was sent at) to the descriptor, set a "done" flag, and then interrupt the CPU to tell it it has something to process.
36+
37+
But we don't want the DMA to have to wait for the CPU, do we? To avoid this, each descriptor also specifies a "next descriptor", either via an offset or a pointer. The DMA can move to this next descriptor and start processing it right away to send or receive the next packet. The CPU will process the completed descriptor on its own time and give it back to the DMA. In this manner, as long as your ring of descriptors is big enough and your CPU can keep up with the processing them, the CPU and MAC never have to wait for each other!
38+
39+
## Components of the Composite EMAC
40+
### MAC Driver
41+
42+
The MAC driver (which must be implemented as a subclass of `CompositeEMAC::MACDriver`) is usually fairly simple. It provides an interface between Mbed and the MAC's configuration register block and MDIO master interface. Its responsibilities include:
43+
- Initializing and muxing the RMII and MDIO pins
44+
- Initializing all needed clocks
45+
- Configuring all settings needed for MAC operation
46+
- Configuring the unicast MAC address (as in, the MAC address that the device uses on the network)
47+
- Adding and removing multicast subscriptions
48+
- Configuring interrupts
49+
- Talking to the PHY over MDIO
50+
51+
### PHY Driver
52+
53+
The PHY driver must be a subclass of `CompositeEMAC::PHYDriver`. It must:
54+
- Confirm the existence of the PHY chip and initialize it
55+
- Configure the selected Ethernet settings (autonegotiation, speed, duplex) into the PHY
56+
- Check if link has been established and, if so, what kind
57+
58+
Unlike the MAC driver and the DMA, the PHY driver does not need to be subclassed for each target device. Thankfully, the Ethernet standard imposes some order on the chaotic sea of PHY parts, and it mandates that the lower 16 registers are standardized and must work the same way on each part. Using this standard behavior, we have implemented the `mbed::GenericEthPhy` class, which should function as a driver for any 802.3u standard compliant PHY. All it needs is configuration, like the PHY's part number and its address on the MDIO bus. When porting to a new target, all you need to do is indicate the PHY model in `mbed-os/connectivity/netsocket/mbed_lib.json` like so:
59+
60+
```json5
61+
"MY_TARGET": {
62+
"nsapi.emac-phy-model": "LAN8742",
63+
"nsapi.emac-phy-mdio-address": 0
64+
}
65+
```
66+
67+
This will work out of the box, as long as `LAN8742` names a PHY driver defined in PhyDrivers.cpp. Individual PHY models will generally need their own drivers, since often PHYs have errata that need to be worked around or need other configuration that isn't defined in the standard. However, GenericEthPhy allows implementing the absolute minimum amount of logic per-phy as possible!
68+
69+
Since user boards may want to use a different ethernet PHY, the driver can be customized in an application by overriding the `mbed::get_eth_phy_driver` weak function. This might look something like
70+
71+
```c++
72+
namespace MY_PHY {
73+
inline constexpr GenericEthPhy::Config Config = {
74+
// These are found in the PHY datasheet. See GenericEthPhy::Config for documentation.
75+
.OUI = 0x123,
76+
.model = 0x45,
77+
.address = 0,
78+
};
79+
80+
class Driver : public GenericEthPhy {
81+
public:
82+
explicit Driver(GenericEthPhy::Config const & config = DefaultConfig):
83+
GenericEthPhy(config)
84+
{}
85+
86+
// You may override/replace any functions of `GenericEthPhy` here
87+
};
88+
}
89+
90+
namespace mbed {
91+
CompositeEMAC::PHYDriver * get_eth_phy_driver()
92+
{
93+
static MY_PHY::Driver(MY_PHY::Config) phyDriver;
94+
return &phyDriver;
95+
}
96+
}
97+
```

connectivity/drivers/emac/include/CompositeEMAC.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,14 @@ class CompositeEMAC : public EMAC
225225
*
226226
* Thread safety: CompositeEMAC will guarantee only one thread is utilizing this class at a time.
227227
*/
228-
class PhyDriver : NonCopyable<PhyDriver>
228+
class PHYDriver : NonCopyable<PHYDriver>
229229
{
230230
protected:
231231
/// MAC driver. Shall be set in init().
232232
MACDriver * mac = nullptr;
233233

234234
public:
235-
virtual ~PhyDriver() = default;
235+
virtual ~PHYDriver() = default;
236236

237237
/// Set the MAC driver of this PHY. Will be called by CompositeEMAC before init().
238238
void setMAC(MACDriver * mac) { this->mac = mac; }
@@ -365,7 +365,7 @@ class CompositeEMAC : public EMAC
365365
emac_link_input_cb_t linkInputCallback{};
366366

367367
// Instances of each of the 4 component classes
368-
PhyDriver * phy = nullptr;
368+
PHYDriver * phy = nullptr;
369369
RxDMA & rxDMA;
370370
TxDMA & txDMA;
371371
MACDriver & mac;

connectivity/drivers/emac/include/GenericEthPhy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ namespace GenPhyRegs {
7878
* Passed a configuration which sets most attributes of the phy.
7979
* May be extended to handle chip-specific quirks.
8080
*/
81-
class GenericEthPhy : public mbed::CompositeEMAC::PhyDriver {
81+
class GenericEthPhy : public mbed::CompositeEMAC::PHYDriver {
8282
public:
8383
/// Configuration structure for a generic Ethernet PHY
8484
struct Config {

connectivity/drivers/emac/sources/CompositeEMAC.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static uint32_t THREAD_FLAG_SHUTDOWN = 1 << 3;
3333

3434
namespace mbed {
3535
// Defined in PhyDrivers.cpp
36-
CompositeEMAC::PhyDriver * mbed_get_eth_phy_driver();
36+
CompositeEMAC::PHYDriver * get_eth_phy_driver();
3737

3838
void CompositeEMAC::rxISR() {
3939
// Note: Not locking mutex here as this is an ISR and should be able to run while the MAC thread is executing.
@@ -198,9 +198,9 @@ namespace mbed {
198198
}
199199

200200
// Get phy
201-
phy = mbed_get_eth_phy_driver();
201+
phy = get_eth_phy_driver();
202202
if(phy == nullptr) {
203-
tr_err("power_up(): No Ethernet PHY driver configured! Either set nsapi.emac-phy-model or override mbed_get_eth_phy_driver().");
203+
tr_err("power_up(): No Ethernet PHY driver configured! Either set nsapi.emac-phy-model or override mbed::get_eth_phy_driver().");
204204
return false;
205205
}
206206

connectivity/drivers/emac/sources/PhyDrivers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Driver : public GenericEthPhy {
5353
*
5454
* @return Phy driver class instance, or nullptr if none is configured.
5555
*/
56-
MBED_WEAK CompositeEMAC::PhyDriver * mbed_get_eth_phy_driver()
56+
MBED_WEAK CompositeEMAC::PHYDriver * get_eth_phy_driver()
5757
{
5858
#ifdef MBED_CONF_NSAPI_EMAC_PHY_MODEL
5959
static GenericEthPhy::Config driverConfig = MBED_CONF_NSAPI_EMAC_PHY_MODEL::DefaultConfig;

0 commit comments

Comments
 (0)