Feature: Support for W5500 ethernet module (#1231)
adds support for w5500 Ethernet chip, present on OpenDTU Fusion PoE Ethernet hat in particular.
This commit is contained in:
parent
1fe8d3f513
commit
89d9a40296
2
.github/workflows/cpplint.yml
vendored
2
.github/workflows/cpplint.yml
vendored
@ -18,4 +18,4 @@ jobs:
|
|||||||
pip install cpplint
|
pip install cpplint
|
||||||
- name: Linting
|
- name: Linting
|
||||||
run: |
|
run: |
|
||||||
cpplint --repository=. --recursive --filter=-build/c++11,-runtime/references,-readability/braces,-whitespace,-legal,-build/include ./src ./include ./lib/Hoymiles ./lib/MqttSubscribeParser ./lib/TimeoutHelper ./lib/ResetReason
|
cpplint --repository=. --recursive --filter=-build/c++11,-runtime/references,-readability/braces,-whitespace,-legal,-build/include ./src ./include ./lib/Hoymiles ./lib/MqttSubscribeParser ./lib/TimeoutHelper ./lib/ResetReason ./lib/ETHSPI
|
||||||
|
|||||||
@ -186,5 +186,43 @@
|
|||||||
"data": 2,
|
"data": 2,
|
||||||
"clk": 1
|
"clk": 1
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "OpenDTU Fusion v2 with NRF24 and W5500 ethernet",
|
||||||
|
"nrf24": {
|
||||||
|
"miso": 48,
|
||||||
|
"mosi": 35,
|
||||||
|
"clk": 36,
|
||||||
|
"irq": 47,
|
||||||
|
"en": 38,
|
||||||
|
"cs": 37
|
||||||
|
},
|
||||||
|
"w5500": {
|
||||||
|
"sclk": 39,
|
||||||
|
"mosi": 40,
|
||||||
|
"miso": 41,
|
||||||
|
"cs": 42,
|
||||||
|
"rst": 43,
|
||||||
|
"int": 44
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "OpenDTU Fusion v2 with CMT2300A and W5500 ethernet",
|
||||||
|
"cmt": {
|
||||||
|
"clk": 6,
|
||||||
|
"cs": 4,
|
||||||
|
"fcs": 21,
|
||||||
|
"sdio": 5,
|
||||||
|
"gpio2": 3,
|
||||||
|
"gpio3": 8
|
||||||
|
},
|
||||||
|
"w5500": {
|
||||||
|
"sclk": 39,
|
||||||
|
"mosi": 40,
|
||||||
|
"miso": 41,
|
||||||
|
"cs": 42,
|
||||||
|
"rst": 43,
|
||||||
|
"int": 44
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -83,6 +83,7 @@ private:
|
|||||||
bool _ethConnected = false;
|
bool _ethConnected = false;
|
||||||
std::vector<NetworkEventCbList_t> _cbEventList;
|
std::vector<NetworkEventCbList_t> _cbEventList;
|
||||||
bool _lastMdnsEnabled = false;
|
bool _lastMdnsEnabled = false;
|
||||||
|
bool _spiEth = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NetworkSettingsClass NetworkSettings;
|
extern NetworkSettingsClass NetworkSettings;
|
||||||
@ -26,6 +26,13 @@ struct PinMapping_t {
|
|||||||
int8_t cmt_gpio3;
|
int8_t cmt_gpio3;
|
||||||
int8_t cmt_sdio;
|
int8_t cmt_sdio;
|
||||||
|
|
||||||
|
int8_t w5500_sclk;
|
||||||
|
int8_t w5500_mosi;
|
||||||
|
int8_t w5500_miso;
|
||||||
|
int8_t w5500_cs;
|
||||||
|
int8_t w5500_int;
|
||||||
|
int8_t w5500_rst;
|
||||||
|
|
||||||
int8_t eth_phy_addr;
|
int8_t eth_phy_addr;
|
||||||
bool eth_enabled;
|
bool eth_enabled;
|
||||||
int eth_power;
|
int eth_power;
|
||||||
@ -70,6 +77,7 @@ public:
|
|||||||
|
|
||||||
bool isValidNrf24Config() const;
|
bool isValidNrf24Config() const;
|
||||||
bool isValidCmt2300Config() const;
|
bool isValidCmt2300Config() const;
|
||||||
|
bool isValidW5500Config() const;
|
||||||
bool isValidEthConfig() const;
|
bool isValidEthConfig() const;
|
||||||
bool isValidHuaweiConfig() const;
|
bool isValidHuaweiConfig() const;
|
||||||
|
|
||||||
|
|||||||
127
lib/ETHSPI/src/ETHSPI.cpp
Normal file
127
lib/ETHSPI/src/ETHSPI.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 2024 Ahoy, https://ahoydtu.de
|
||||||
|
// adapted to OpenDTU-OnBattery
|
||||||
|
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "ETHSPI.h"
|
||||||
|
|
||||||
|
#include <driver/spi_master.h>
|
||||||
|
|
||||||
|
// Functions from WiFiGeneric
|
||||||
|
void tcpipInit();
|
||||||
|
void add_esp_interface_netif(esp_interface_t interface, esp_netif_t* esp_netif);
|
||||||
|
|
||||||
|
ETHSPIClass::ETHSPIClass() :
|
||||||
|
eth_handle(nullptr),
|
||||||
|
eth_netif(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ETHSPIClass::begin(int8_t pin_sclk, int8_t pin_mosi, int8_t pin_miso, int8_t pin_cs, int8_t pin_int, int8_t pin_rst, spi_host_device_t host_id)
|
||||||
|
{
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_rst));
|
||||||
|
gpio_set_direction(static_cast<gpio_num_t>(pin_rst), GPIO_MODE_OUTPUT);
|
||||||
|
gpio_set_level(static_cast<gpio_num_t>(pin_rst), 0);
|
||||||
|
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_sclk));
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_mosi));
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_miso));
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_cs));
|
||||||
|
gpio_set_pull_mode(static_cast<gpio_num_t>(pin_miso), GPIO_PULLUP_ONLY);
|
||||||
|
|
||||||
|
// Workaround, because calling gpio_install_isr_service directly causes issues with attachInterrupt later
|
||||||
|
attachInterrupt(digitalPinToInterrupt(pin_int), nullptr, CHANGE);
|
||||||
|
detachInterrupt(digitalPinToInterrupt(pin_int));
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_int));
|
||||||
|
gpio_set_pull_mode(static_cast<gpio_num_t>(pin_int), GPIO_PULLUP_ONLY);
|
||||||
|
|
||||||
|
spi_bus_config_t buscfg = {
|
||||||
|
.mosi_io_num = pin_mosi,
|
||||||
|
.miso_io_num = pin_miso,
|
||||||
|
.sclk_io_num = pin_sclk,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
.data4_io_num = -1,
|
||||||
|
.data5_io_num = -1,
|
||||||
|
.data6_io_num = -1,
|
||||||
|
.data7_io_num = -1,
|
||||||
|
.max_transfer_sz = 0, // uses default value internally
|
||||||
|
.flags = 0,
|
||||||
|
.intr_flags = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(spi_bus_initialize(host_id, &buscfg, SPI_DMA_CH_AUTO));
|
||||||
|
|
||||||
|
spi_device_interface_config_t devcfg = {
|
||||||
|
.command_bits = 16, // actually address phase
|
||||||
|
.address_bits = 8, // actually command phase
|
||||||
|
.dummy_bits = 0,
|
||||||
|
.mode = 0,
|
||||||
|
.duty_cycle_pos = 0,
|
||||||
|
.cs_ena_pretrans = 0, // only 0 supported
|
||||||
|
.cs_ena_posttrans = 0, // only 0 supported
|
||||||
|
.clock_speed_hz = 20000000, // stable with on OpenDTU Fusion Shield
|
||||||
|
.input_delay_ns = 0,
|
||||||
|
.spics_io_num = pin_cs,
|
||||||
|
.flags = 0,
|
||||||
|
.queue_size = 20,
|
||||||
|
.pre_cb = nullptr,
|
||||||
|
.post_cb = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
spi_device_handle_t spi;
|
||||||
|
ESP_ERROR_CHECK(spi_bus_add_device(host_id, &devcfg, &spi));
|
||||||
|
|
||||||
|
// Reset sequence
|
||||||
|
delayMicroseconds(500);
|
||||||
|
gpio_set_level(static_cast<gpio_num_t>(pin_rst), 1);
|
||||||
|
delayMicroseconds(1000);
|
||||||
|
|
||||||
|
// Arduino function to start networking stack if not already started
|
||||||
|
tcpipInit();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers()); // ?
|
||||||
|
|
||||||
|
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi);
|
||||||
|
w5500_config.int_gpio_num = pin_int;
|
||||||
|
|
||||||
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
|
mac_config.rx_task_stack_size = 4096;
|
||||||
|
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||||
|
|
||||||
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
|
phy_config.reset_gpio_num = -1;
|
||||||
|
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
|
||||||
|
|
||||||
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, ð_handle));
|
||||||
|
|
||||||
|
// Configure MAC address
|
||||||
|
uint8_t mac_addr[6];
|
||||||
|
ESP_ERROR_CHECK(esp_efuse_mac_get_default(mac_addr));
|
||||||
|
mac_addr[5] |= 0x03; // derive ethernet MAC address from base MAC address
|
||||||
|
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr));
|
||||||
|
|
||||||
|
esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH();
|
||||||
|
eth_netif = esp_netif_new(&netif_config);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
|
||||||
|
|
||||||
|
// Add to Arduino
|
||||||
|
add_esp_interface_netif(ESP_IF_ETH, eth_netif);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
String ETHSPIClass::macAddress()
|
||||||
|
{
|
||||||
|
uint8_t mac_addr[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
|
||||||
|
char mac_addr_str[24];
|
||||||
|
snprintf(mac_addr_str, sizeof(mac_addr_str), "%02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
|
return String(mac_addr_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
ETHSPIClass ETHSPI;
|
||||||
26
lib/ETHSPI/src/ETHSPI.h
Normal file
26
lib/ETHSPI/src/ETHSPI.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 2024 Ahoy, https://ahoydtu.de
|
||||||
|
// adapted to OpenDTU-OnBattery
|
||||||
|
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <esp_netif.h>
|
||||||
|
#include <driver/spi_master.h>
|
||||||
|
|
||||||
|
class ETHSPIClass
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
esp_eth_handle_t eth_handle;
|
||||||
|
esp_netif_t *eth_netif;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ETHSPIClass();
|
||||||
|
|
||||||
|
void begin(int8_t pin_sclk, int8_t pin_mosi, int8_t pin_miso, int8_t pin_cs, int8_t pin_int, int8_t pin_rst, spi_host_device_t host_id);
|
||||||
|
String macAddress();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ETHSPIClass ETHSPI;
|
||||||
@ -7,8 +7,10 @@
|
|||||||
#include "MessageOutput.h"
|
#include "MessageOutput.h"
|
||||||
#include "PinMapping.h"
|
#include "PinMapping.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
#include "SPIPortManager.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
|
#include <ETHSPI.h>
|
||||||
#include <ETH.h>
|
#include <ETH.h>
|
||||||
#include "__compiled_constants.h"
|
#include "__compiled_constants.h"
|
||||||
|
|
||||||
@ -30,6 +32,22 @@ void NetworkSettingsClass::init(Scheduler& scheduler)
|
|||||||
WiFi.disconnect(true, true);
|
WiFi.disconnect(true, true);
|
||||||
|
|
||||||
WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1));
|
WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1));
|
||||||
|
|
||||||
|
if (PinMapping.isValidEthConfig()) {
|
||||||
|
PinMapping_t& pin = PinMapping.get();
|
||||||
|
ETH.begin(pin.eth_phy_addr, pin.eth_power, pin.eth_mdc, pin.eth_mdio, pin.eth_type, pin.eth_clk_mode);
|
||||||
|
} else if (PinMapping.isValidW5500Config()) {
|
||||||
|
auto oSPInum = SPIPortManager.allocatePort("ETHSPI");
|
||||||
|
|
||||||
|
if (oSPInum) {
|
||||||
|
spi_host_device_t host_id = SPIPortManager.SPIhostNum(*oSPInum);
|
||||||
|
PinMapping_t& pin = PinMapping.get();
|
||||||
|
ETHSPI.begin(pin.w5500_sclk, pin.w5500_mosi, pin.w5500_miso, pin.w5500_cs, pin.w5500_int, pin.w5500_rst,
|
||||||
|
host_id);
|
||||||
|
_spiEth = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setupMode();
|
setupMode();
|
||||||
|
|
||||||
scheduler.addTask(_loopTask);
|
scheduler.addTask(_loopTask);
|
||||||
@ -167,11 +185,6 @@ void NetworkSettingsClass::setupMode()
|
|||||||
WiFi.mode(WIFI_MODE_NULL);
|
WiFi.mode(WIFI_MODE_NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PinMapping.isValidEthConfig()) {
|
|
||||||
PinMapping_t& pin = PinMapping.get();
|
|
||||||
ETH.begin(pin.eth_phy_addr, pin.eth_power, pin.eth_mdc, pin.eth_mdio, pin.eth_type, pin.eth_clk_mode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkSettingsClass::enableAdminMode()
|
void NetworkSettingsClass::enableAdminMode()
|
||||||
@ -399,6 +412,9 @@ String NetworkSettingsClass::macAddress() const
|
|||||||
{
|
{
|
||||||
switch (_networkMode) {
|
switch (_networkMode) {
|
||||||
case network_mode::Ethernet:
|
case network_mode::Ethernet:
|
||||||
|
if (_spiEth) {
|
||||||
|
return ETHSPI.macAddress();
|
||||||
|
}
|
||||||
return ETH.macAddress();
|
return ETH.macAddress();
|
||||||
break;
|
break;
|
||||||
case network_mode::WiFi:
|
case network_mode::WiFi:
|
||||||
|
|||||||
@ -170,6 +170,30 @@
|
|||||||
#define POWERMETER_PIN_DERE -1
|
#define POWERMETER_PIN_DERE -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef W5500_SCLK
|
||||||
|
#define W5500_SCLK -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef W5500_MOSI
|
||||||
|
#define W5500_MOSI -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef W5500_MISO
|
||||||
|
#define W5500_MISO -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef W5500_CS
|
||||||
|
#define W5500_CS -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef W5500_INT
|
||||||
|
#define W5500_INT -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef W5500_RST
|
||||||
|
#define W5500_RST -1
|
||||||
|
#endif
|
||||||
|
|
||||||
PinMappingClass PinMapping;
|
PinMappingClass PinMapping;
|
||||||
|
|
||||||
PinMappingClass::PinMappingClass()
|
PinMappingClass::PinMappingClass()
|
||||||
@ -189,6 +213,13 @@ PinMappingClass::PinMappingClass()
|
|||||||
_pinMapping.cmt_gpio3 = CMT_GPIO3;
|
_pinMapping.cmt_gpio3 = CMT_GPIO3;
|
||||||
_pinMapping.cmt_sdio = CMT_SDIO;
|
_pinMapping.cmt_sdio = CMT_SDIO;
|
||||||
|
|
||||||
|
_pinMapping.w5500_sclk = W5500_SCLK;
|
||||||
|
_pinMapping.w5500_mosi = W5500_MOSI;
|
||||||
|
_pinMapping.w5500_miso = W5500_MISO;
|
||||||
|
_pinMapping.w5500_cs = W5500_CS;
|
||||||
|
_pinMapping.w5500_int = W5500_INT;
|
||||||
|
_pinMapping.w5500_rst = W5500_RST;
|
||||||
|
|
||||||
#ifdef OPENDTU_ETHERNET
|
#ifdef OPENDTU_ETHERNET
|
||||||
_pinMapping.eth_enabled = true;
|
_pinMapping.eth_enabled = true;
|
||||||
#else
|
#else
|
||||||
@ -276,6 +307,13 @@ bool PinMappingClass::init(const String& deviceMapping)
|
|||||||
_pinMapping.cmt_gpio3 = doc[i]["cmt"]["gpio3"] | CMT_GPIO3;
|
_pinMapping.cmt_gpio3 = doc[i]["cmt"]["gpio3"] | CMT_GPIO3;
|
||||||
_pinMapping.cmt_sdio = doc[i]["cmt"]["sdio"] | CMT_SDIO;
|
_pinMapping.cmt_sdio = doc[i]["cmt"]["sdio"] | CMT_SDIO;
|
||||||
|
|
||||||
|
_pinMapping.w5500_sclk = doc[i]["w5500"]["sclk"] | W5500_SCLK;
|
||||||
|
_pinMapping.w5500_mosi = doc[i]["w5500"]["mosi"] | W5500_MOSI;
|
||||||
|
_pinMapping.w5500_miso = doc[i]["w5500"]["miso"] | W5500_MISO;
|
||||||
|
_pinMapping.w5500_cs = doc[i]["w5500"]["cs"] | W5500_CS;
|
||||||
|
_pinMapping.w5500_int = doc[i]["w5500"]["int"] | W5500_INT;
|
||||||
|
_pinMapping.w5500_rst = doc[i]["w5500"]["rst"] | W5500_RST;
|
||||||
|
|
||||||
#ifdef OPENDTU_ETHERNET
|
#ifdef OPENDTU_ETHERNET
|
||||||
_pinMapping.eth_enabled = doc[i]["eth"]["enabled"] | true;
|
_pinMapping.eth_enabled = doc[i]["eth"]["enabled"] | true;
|
||||||
#else
|
#else
|
||||||
@ -347,6 +385,16 @@ bool PinMappingClass::isValidCmt2300Config() const
|
|||||||
&& _pinMapping.cmt_sdio >= 0;
|
&& _pinMapping.cmt_sdio >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PinMappingClass::isValidW5500Config() const
|
||||||
|
{
|
||||||
|
return _pinMapping.w5500_sclk >= 0
|
||||||
|
&& _pinMapping.w5500_mosi >= 0
|
||||||
|
&& _pinMapping.w5500_miso >= 0
|
||||||
|
&& _pinMapping.w5500_cs >= 0
|
||||||
|
&& _pinMapping.w5500_int >= 0
|
||||||
|
&& _pinMapping.w5500_rst >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool PinMappingClass::isValidEthConfig() const
|
bool PinMappingClass::isValidEthConfig() const
|
||||||
{
|
{
|
||||||
return _pinMapping.eth_enabled;
|
return _pinMapping.eth_enabled;
|
||||||
|
|||||||
@ -50,6 +50,14 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
||||||
cmtPinObj["gpio3"] = pin.cmt_gpio3;
|
cmtPinObj["gpio3"] = pin.cmt_gpio3;
|
||||||
|
|
||||||
|
auto w5500PinObj = curPin["w5500"].to<JsonObject>();
|
||||||
|
w5500PinObj["sclk"] = pin.w5500_sclk;
|
||||||
|
w5500PinObj["mosi"] = pin.w5500_mosi;
|
||||||
|
w5500PinObj["miso"] = pin.w5500_miso;
|
||||||
|
w5500PinObj["cs"] = pin.w5500_cs;
|
||||||
|
w5500PinObj["int"] = pin.w5500_int;
|
||||||
|
w5500PinObj["rst"] = pin.w5500_rst;
|
||||||
|
|
||||||
auto ethPinObj = curPin["eth"].to<JsonObject>();
|
auto ethPinObj = curPin["eth"].to<JsonObject>();
|
||||||
ethPinObj["enabled"] = pin.eth_enabled;
|
ethPinObj["enabled"] = pin.eth_enabled;
|
||||||
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user