Merge branch 'feature/eth_ioctl_speed_duplex' into 'master'
esp_eth: esp_eth_ioctl update Closes IDF-1240 and IDF-4060 See merge request espressif/esp-idf!15607
This commit is contained in:
@@ -14,27 +14,27 @@ If you have a more complicated application to go (for example, connect to some I
|
||||
### Hardware Required
|
||||
|
||||
To run this example, you need to prepare following hardwares:
|
||||
* [ESP32 board](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html) (e.g. ESP32-PICO, ESP32 DevKitC, etc)
|
||||
* ENC28J60 module (the latest revision should be 6)
|
||||
* [ESP32 dev board](https://www.espressif.com/en/products/devkits?id=ESP32) (e.g. ESP32-PICO, ESP32 DevKitC, etc)
|
||||
* ENC28J60 Ethernet module (the latest revision should be 6)
|
||||
* **!! IMPORTANT !!** Proper input power source since ENC28J60 is quite power consuming device (it consumes more than 200 mA in peaks when transmitting). If improper power source is used, input voltage may drop and ENC28J60 may either provide nonsense response to host controller via SPI (fail to read registers properly) or it may enter to some strange state in the worst case. There are several options how to resolve it:
|
||||
* Power ESP32 board from `USB 3.0`, if board is used as source of power to ENC board.
|
||||
* Power ESP32 board from external 5V power supply with current limit at least 1 A, if board is used as source of power to ENC board.
|
||||
* Power ENC28J60 from external 3.3V power supply with common GND to ESP32 board. Note that there might be some ENC28J60 boards with integrated voltage regulator on market and so powered by 5 V. Please consult documentation of your board for details.
|
||||
* Power ESP32 dev board from `USB 3.0`, if the dev board is used as source of power to the ENC28J60 module.
|
||||
* Power ESP32 dev board from external 5 V power supply with current limit at least 1 A, if the dev board is used as source of power to the ENC28J60 module.
|
||||
* Power ENC28J60 from external 3.3 V power supply with common GND to ESP32 dev board. Note that there might be some ENC28J60 modules with integrated voltage regulator on market and so powered by 5 V. Please consult documentation of your board for details.
|
||||
|
||||
If a ESP32 board is used as source of power to ENC board, ensure that that particular board is assembled with voltage regulator capable to deliver current up to 1 A. This is a case of ESP32 DevKitC or ESP-WROVER-KIT, for example. Such setup was tested and works as expected. Other boards may use different voltage regulators and may perform differently.
|
||||
**WARNING:** Always consult documentation/schematics associated with particular ENC28J60 and ESP32 boards used in your use-case first.
|
||||
If an ESP32 dev board is used as the source of power to the ENC28J60 module, ensure that that the particular dev board is assembled with a voltage regulator capable to deliver current of 1 A. This is a case of ESP32-DevKitC or ESP-WROVER-KIT, for example. Such setup was tested and works as expected. Other dev boards may use different voltage regulators and may perform differently.
|
||||
**WARNING:** Always consult documentation/schematics associated with particular ENC28J60 and ESP32 dev boards used in your use-case first.
|
||||
|
||||
#### Pin Assignment
|
||||
|
||||
* ENC28J60 Ethernet module consumes one SPI interface plus an interrupt GPIO. By default they're connected as follows:
|
||||
* ENC28J60 Ethernet module consumes one SPI interface plus an interrupt GPIO. By default they're connected as follows, in case of ESP32 dev boards:
|
||||
|
||||
| GPIO | ENC28J60 |
|
||||
| ------ | ----------- |
|
||||
| GPIO19 | SPI_CLK |
|
||||
| GPIO23 | SPI_MOSI |
|
||||
| GPIO25 | SPI_MISO |
|
||||
| GPIO22 | SPI_CS |
|
||||
| GPIO4 | Interrupt |
|
||||
| ESP32 GPIO | ENC28J60 |
|
||||
| ---------- | ----------- |
|
||||
| GPIO14 | SPI_CLK |
|
||||
| GPIO13 | SPI_MOSI |
|
||||
| GPIO12 | SPI_MISO |
|
||||
| GPIO15 | SPI_CS |
|
||||
| GPIO4 | Interrupt |
|
||||
|
||||
### Configure the project
|
||||
|
||||
@@ -92,7 +92,7 @@ Now you can ping your ESP32 in the terminal by entering `ping 192.168.2.34` (it
|
||||
sudo ethtool -s YOUR_INTERFACE_NAME speed 10 duplex full autoneg off
|
||||
```
|
||||
* On Windows, go to `Network Connections` -> `Change adapter options` -> open `Properties` of selected network card -> `Configure` -> `Advanced` -> `Link Speed & Duplex` -> select `10 Mbps Full Duplex in dropdown menu`.
|
||||
3. Ensure that your wiring between ESP32 board and the ENC28J60 board is realized by short wires with the same length and no wire crossings.
|
||||
3. Ensure that your wiring between ESP32 dev board and the ENC28J60 module is realized by short wires with the same length and no wire crossings.
|
||||
4. CS Hold Time needs to be configured to be at least 210 ns to properly read MAC and MII registers as defined by ENC28J60 Data Sheet. This is automatically configured in the example based on selected SPI clock frequency by computing amount of SPI bit-cycles the CS should stay active after the transmission. However, if your PCB design/wiring requires different value, please update `cs_ena_posttrans` member of `devcfg` structure per your actual needs.
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -98,19 +90,6 @@ esp_eth_mac_t *esp_eth_mac_new_enc28j60(const eth_enc28j60_config_t *enc28j60_co
|
||||
*/
|
||||
esp_eth_phy_t *esp_eth_phy_new_enc28j60(const eth_phy_config_t *config);
|
||||
|
||||
// todo: the below functions should be accessed through ioctl in the future
|
||||
/**
|
||||
* @brief Set ENC28J60 Duplex mode. It sets Duplex mode first to the PHY and then
|
||||
* MAC is set based on what PHY indicates.
|
||||
*
|
||||
* @param phy ENC28J60 PHY Handle
|
||||
* @param duplex Duplex mode
|
||||
*
|
||||
* @return esp_err_t
|
||||
* - ESP_OK when PHY registers were correctly written.
|
||||
*/
|
||||
esp_err_t enc28j60_set_phy_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex);
|
||||
|
||||
/**
|
||||
* @brief Get ENC28J60 silicon revision ID
|
||||
*
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
@@ -190,7 +182,7 @@ static esp_err_t enc28j60_reset_hw(esp_eth_phy_t *phy)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t enc28j60_negotiate(esp_eth_phy_t *phy)
|
||||
static esp_err_t enc28j60_autonego_ctrl(esp_eth_phy_t *phy, eth_phy_autoneg_cmd_t cmd, bool *autoneg_en_stat)
|
||||
{
|
||||
/**
|
||||
* ENC28J60 does not support automatic duplex negotiation.
|
||||
@@ -199,20 +191,46 @@ static esp_err_t enc28j60_negotiate(esp_eth_phy_t *phy)
|
||||
* To communicate in Full-Duplex mode, ENC28J60 and the remote node
|
||||
* must be manually configured for full-duplex operation.
|
||||
*/
|
||||
phy_enc28j60_t *enc28j60 = __containerof(phy, phy_enc28j60_t, parent);
|
||||
/* Updata information about link, speed, duplex */
|
||||
PHY_CHECK(enc28j60_update_link_duplex_speed(enc28j60) == ESP_OK, "update link duplex speed failed", err);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case ESP_ETH_PHY_AUTONEGO_RESTART:
|
||||
/* Fallthrough */
|
||||
case ESP_ETH_PHY_AUTONEGO_EN:
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
case ESP_ETH_PHY_AUTONEGO_DIS:
|
||||
/* Fallthrough */
|
||||
case ESP_ETH_PHY_AUTONEGO_G_STAT:
|
||||
*autoneg_en_stat = false;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t enc28j60_set_phy_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
||||
esp_err_t enc28j60_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
||||
{
|
||||
/* ENC28J60 supports only 10Mbps */
|
||||
if (speed == ETH_SPEED_10M) {
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t enc28j60_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
||||
{
|
||||
phy_enc28j60_t *enc28j60 = __containerof(phy, phy_enc28j60_t, parent);
|
||||
esp_eth_mediator_t *eth = enc28j60->eth;
|
||||
phcon1_reg_t phcon1;
|
||||
|
||||
if (enc28j60->link_status == ETH_LINK_UP) {
|
||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
||||
enc28j60->link_status = ETH_LINK_DOWN;
|
||||
/* Indicate to upper stream apps the link is cosidered down */
|
||||
PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)enc28j60->link_status), "change link failed", err);
|
||||
}
|
||||
|
||||
PHY_CHECK(eth->phy_reg_read(eth, enc28j60->addr, 0, &phcon1.val) == ESP_OK,
|
||||
"read PHCON1 failed", err);
|
||||
switch (duplex) {
|
||||
@@ -230,7 +248,6 @@ esp_err_t enc28j60_set_phy_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
||||
PHY_CHECK(eth->phy_reg_write(eth, enc28j60->addr, 0, phcon1.val) == ESP_OK,
|
||||
"write PHCON1 failed", err);
|
||||
|
||||
PHY_CHECK(enc28j60_update_link_duplex_speed(enc28j60) == ESP_OK, "update link duplex speed failed", err);
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ESP_FAIL;
|
||||
@@ -340,11 +357,13 @@ esp_eth_phy_t *esp_eth_phy_new_enc28j60(const eth_phy_config_t *config)
|
||||
enc28j60->parent.init = enc28j60_init;
|
||||
enc28j60->parent.deinit = enc28j60_deinit;
|
||||
enc28j60->parent.set_mediator = enc28j60_set_mediator;
|
||||
enc28j60->parent.negotiate = enc28j60_negotiate;
|
||||
enc28j60->parent.autonego_ctrl = enc28j60_autonego_ctrl;
|
||||
enc28j60->parent.get_link = enc28j60_get_link;
|
||||
enc28j60->parent.pwrctl = enc28j60_pwrctl;
|
||||
enc28j60->parent.get_addr = enc28j60_get_addr;
|
||||
enc28j60->parent.set_addr = enc28j60_set_addr;
|
||||
enc28j60->parent.set_speed = enc28j60_set_speed;
|
||||
enc28j60->parent.set_duplex = enc28j60_set_duplex;
|
||||
enc28j60->parent.del = enc28j60_del;
|
||||
return &(enc28j60->parent);
|
||||
err:
|
||||
|
||||
@@ -132,12 +132,13 @@ void app_main(void)
|
||||
// Register user defined event handers
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
||||
/* start Ethernet driver state machine */
|
||||
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||
|
||||
/* It is recommended to use ENC28J60 in Full Duplex mode since multiple errata exist to the Half Duplex mode */
|
||||
#if CONFIG_EXAMPLE_ENC28J60_DUPLEX_FULL
|
||||
/* Set duplex needs to be called after esp_eth_start since the driver is started with auto-negotiation by default */
|
||||
enc28j60_set_phy_duplex(phy, ETH_DUPLEX_FULL);
|
||||
eth_duplex_t duplex = ETH_DUPLEX_FULL;
|
||||
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex));
|
||||
#endif
|
||||
|
||||
/* start Ethernet driver state machine */
|
||||
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user