mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/ethernet_link_check_esp_timer' into 'master'
esp_eth: using esp_timer to check link status Closes IDFGH-4953 See merge request espressif/esp-idf!13155
This commit is contained in:
commit
7f34657013
@ -1,119 +0,0 @@
|
||||
// Copyright 2015-2016 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.
|
||||
|
||||
#ifndef __ESP_SSC_H__
|
||||
#define __ESP_SSC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CMD_T_ASYNC 0x01
|
||||
#define CMD_T_SYNC 0x02
|
||||
|
||||
typedef struct cmd_s {
|
||||
char *cmd_str;
|
||||
uint8_t flag;
|
||||
uint8_t id;
|
||||
void (* cmd_func)(void);
|
||||
void (* cmd_callback)(void *arg);
|
||||
} ssc_cmd_t;
|
||||
|
||||
#define MAX_LINE_N 127
|
||||
|
||||
typedef enum {
|
||||
SSC_BR_9600 = 9600,
|
||||
SSC_BR_19200 = 19200,
|
||||
SSC_BR_38400 = 38400,
|
||||
SSC_BR_57600 = 57600,
|
||||
SSC_BR_74880 = 74880,
|
||||
SSC_BR_115200 = 115200,
|
||||
SSC_BR_230400 = 230400,
|
||||
SSC_BR_460800 = 460800,
|
||||
SSC_BR_921600 = 921600
|
||||
} SscBaudRate;
|
||||
|
||||
/** \defgroup SSC_APIs SSC APIs
|
||||
* @brief SSC APIs
|
||||
*
|
||||
* SSC means simple serial command.
|
||||
* SSC APIs allows users to define their own command, users can refer to spiffs_test/test_main.c.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @addtogroup SSC_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initial the ssc function.
|
||||
*
|
||||
* @attention param is no use, just compatible with ESP8266, default bandrate is 115200
|
||||
*
|
||||
* @param SscBaudRate bandrate : baud rate
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void ssc_attach(SscBaudRate bandrate);
|
||||
|
||||
/**
|
||||
* @brief Get the length of the simple serial command.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return length of the command.
|
||||
*/
|
||||
int ssc_param_len(void);
|
||||
|
||||
/**
|
||||
* @brief Get the simple serial command string.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
char *ssc_param_str(void);
|
||||
|
||||
/**
|
||||
* @brief Parse the simple serial command (ssc).
|
||||
*
|
||||
* @param char *pLine : [input] the ssc string
|
||||
* @param char *argv[] : [output] parameters of the ssc
|
||||
*
|
||||
* @return the number of parameters.
|
||||
*/
|
||||
int ssc_parse_param(char *pLine, char *argv[]);
|
||||
|
||||
/**
|
||||
* @brief Register the user-defined simple serial command (ssc) set.
|
||||
*
|
||||
* @param ssc_cmd_t *cmdset : the ssc set
|
||||
* @param uint8 cmdnum : number of commands
|
||||
* @param void (* help)(void) : callback of user-guide
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void ssc_register(ssc_cmd_t *cmdset, uint8_t cmdnum, void (* help)(void));
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_SSC_H__ */
|
@ -1,119 +0,0 @@
|
||||
// Copyright 2015-2016 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.
|
||||
|
||||
#ifndef __ESP_SSC_H__
|
||||
#define __ESP_SSC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CMD_T_ASYNC 0x01
|
||||
#define CMD_T_SYNC 0x02
|
||||
|
||||
typedef struct cmd_s {
|
||||
char *cmd_str;
|
||||
uint8_t flag;
|
||||
uint8_t id;
|
||||
void (* cmd_func)(void);
|
||||
void (* cmd_callback)(void *arg);
|
||||
} ssc_cmd_t;
|
||||
|
||||
#define MAX_LINE_N 127
|
||||
|
||||
typedef enum {
|
||||
SSC_BR_9600 = 9600,
|
||||
SSC_BR_19200 = 19200,
|
||||
SSC_BR_38400 = 38400,
|
||||
SSC_BR_57600 = 57600,
|
||||
SSC_BR_74880 = 74880,
|
||||
SSC_BR_115200 = 115200,
|
||||
SSC_BR_230400 = 230400,
|
||||
SSC_BR_460800 = 460800,
|
||||
SSC_BR_921600 = 921600
|
||||
} SscBaudRate;
|
||||
|
||||
/** \defgroup SSC_APIs SSC APIs
|
||||
* @brief SSC APIs
|
||||
*
|
||||
* SSC means simple serial command.
|
||||
* SSC APIs allows users to define their own command, users can refer to spiffs_test/test_main.c.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @addtogroup SSC_APIs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initial the ssc function.
|
||||
*
|
||||
* @attention param is no use, just compatible with ESP8266, default bandrate is 115200
|
||||
*
|
||||
* @param SscBaudRate bandrate : baud rate
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void ssc_attach(SscBaudRate bandrate);
|
||||
|
||||
/**
|
||||
* @brief Get the length of the simple serial command.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return length of the command.
|
||||
*/
|
||||
int ssc_param_len(void);
|
||||
|
||||
/**
|
||||
* @brief Get the simple serial command string.
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
char *ssc_param_str(void);
|
||||
|
||||
/**
|
||||
* @brief Parse the simple serial command (ssc).
|
||||
*
|
||||
* @param char *pLine : [input] the ssc string
|
||||
* @param char *argv[] : [output] parameters of the ssc
|
||||
*
|
||||
* @return the number of parameters.
|
||||
*/
|
||||
int ssc_parse_param(char *pLine, char *argv[]);
|
||||
|
||||
/**
|
||||
* @brief Register the user-defined simple serial command (ssc) set.
|
||||
*
|
||||
* @param ssc_cmd_t *cmdset : the ssc set
|
||||
* @param uint8 cmdnum : number of commands
|
||||
* @param void (* help)(void) : callback of user-guide
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
void ssc_register(ssc_cmd_t *cmdset, uint8_t cmdnum, void (* help)(void));
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_SSC_H__ */
|
@ -8,7 +8,7 @@ set(priv_requires)
|
||||
if(CONFIG_ETH_ENABLED)
|
||||
set(srcs "src/esp_eth.c" "src/esp_eth_phy.c")
|
||||
set(include "include")
|
||||
set(priv_requires "driver" "log") # require "driver" for using some GPIO APIs
|
||||
set(priv_requires "driver" "log" "esp_timer") # require "driver" for using some GPIO APIs
|
||||
|
||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
# esp_netif related
|
||||
|
@ -86,6 +86,47 @@ typedef struct {
|
||||
*/
|
||||
esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle);
|
||||
|
||||
/**
|
||||
* @brief Read PHY register
|
||||
*
|
||||
* @note Usually the PHY register read/write function is provided by MAC (SMI interface),
|
||||
* but if the PHY device is managed by other interface (e.g. I2C), then user needs to
|
||||
* implement the corresponding read/write.
|
||||
* Setting this to NULL means your PHY device is managed by MAC's SMI interface.
|
||||
*
|
||||
* @param[in] eth_handle: handle of Ethernet driver
|
||||
* @param[in] phy_addr: PHY chip address (0~31)
|
||||
* @param[in] phy_reg: PHY register index code
|
||||
* @param[out] reg_value: PHY register value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: read PHY register successfully
|
||||
* - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument
|
||||
* - ESP_ERR_TIMEOUT: read PHY register failed because of timeout
|
||||
* - ESP_FAIL: read PHY register failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*read_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value);
|
||||
|
||||
/**
|
||||
* @brief Write PHY register
|
||||
*
|
||||
* @note Usually the PHY register read/write function is provided by MAC (SMI interface),
|
||||
* but if the PHY device is managed by other interface (e.g. I2C), then user needs to
|
||||
* implement the corresponding read/write.
|
||||
* Setting this to NULL means your PHY device is managed by MAC's SMI interface.
|
||||
*
|
||||
* @param[in] eth_handle: handle of Ethernet driver
|
||||
* @param[in] phy_addr: PHY chip address (0~31)
|
||||
* @param[in] phy_reg: PHY register index code
|
||||
* @param[in] reg_value: PHY register value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: write PHY register successfully
|
||||
* - ESP_ERR_INVALID_ARG: read PHY register failed because of invalid argument
|
||||
* - ESP_ERR_TIMEOUT: write PHY register failed because of timeout
|
||||
* - ESP_FAIL: write PHY register failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*write_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value);
|
||||
} esp_eth_config_t;
|
||||
|
||||
/**
|
||||
@ -100,6 +141,8 @@ typedef struct {
|
||||
.stack_input = NULL, \
|
||||
.on_lowlevel_init_done = NULL, \
|
||||
.on_lowlevel_deinit_done = NULL, \
|
||||
.read_phy_reg = NULL, \
|
||||
.write_phy_reg = NULL, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2019-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.
|
||||
@ -11,16 +11,17 @@
|
||||
// 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.
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <stdatomic.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_eth.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
static const char *TAG = "esp_eth";
|
||||
|
||||
@ -45,7 +46,8 @@ typedef struct {
|
||||
esp_eth_mediator_t mediator;
|
||||
esp_eth_phy_t *phy;
|
||||
esp_eth_mac_t *mac;
|
||||
TimerHandle_t check_link_timer;
|
||||
esp_timer_handle_t check_link_timer;
|
||||
uint32_t check_link_period_ms;
|
||||
eth_speed_t speed;
|
||||
eth_duplex_t duplex;
|
||||
eth_link_t link;
|
||||
@ -55,6 +57,8 @@ typedef struct {
|
||||
esp_err_t (*stack_input)(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv);
|
||||
esp_err_t (*on_lowlevel_init_done)(esp_eth_handle_t eth_handle);
|
||||
esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle);
|
||||
esp_err_t (*customized_read_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value);
|
||||
esp_err_t (*customized_write_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value);
|
||||
} esp_eth_driver_t;
|
||||
|
||||
////////////////////////////////Mediator Functions////////////////////////////////////////////
|
||||
@ -69,6 +73,11 @@ typedef struct {
|
||||
static esp_err_t eth_phy_reg_read(esp_eth_mediator_t *eth, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)
|
||||
{
|
||||
esp_eth_driver_t *eth_driver = __containerof(eth, esp_eth_driver_t, mediator);
|
||||
// invoking user customized PHY IO function if necessary
|
||||
if (eth_driver->customized_read_phy_reg) {
|
||||
return eth_driver->customized_read_phy_reg(eth_driver, phy_addr, phy_reg, reg_value);
|
||||
}
|
||||
// by default, PHY device is managed by MAC's SMI interface
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
return mac->read_phy_reg(mac, phy_addr, phy_reg, reg_value);
|
||||
}
|
||||
@ -76,6 +85,11 @@ static esp_err_t eth_phy_reg_read(esp_eth_mediator_t *eth, uint32_t phy_addr, ui
|
||||
static esp_err_t eth_phy_reg_write(esp_eth_mediator_t *eth, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)
|
||||
{
|
||||
esp_eth_driver_t *eth_driver = __containerof(eth, esp_eth_driver_t, mediator);
|
||||
// invoking user customized PHY IO function if necessary
|
||||
if (eth_driver->customized_write_phy_reg) {
|
||||
return eth_driver->customized_write_phy_reg(eth_driver, phy_addr, phy_reg, reg_value);
|
||||
}
|
||||
// by default, PHY device is managed by MAC's SMI interface
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
return mac->write_phy_reg(mac, phy_addr, phy_reg, reg_value);
|
||||
}
|
||||
@ -85,10 +99,10 @@ static esp_err_t eth_stack_input(esp_eth_mediator_t *eth, uint8_t *buffer, uint3
|
||||
esp_eth_driver_t *eth_driver = __containerof(eth, esp_eth_driver_t, mediator);
|
||||
if (eth_driver->stack_input) {
|
||||
return eth_driver->stack_input((esp_eth_handle_t)eth_driver, buffer, length, eth_driver->priv);
|
||||
} else {
|
||||
free(buffer);
|
||||
return ESP_OK;
|
||||
}
|
||||
// No stack input path has been installed, just drop the incoming packets
|
||||
free(buffer);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t eth_on_state_changed(esp_eth_mediator_t *eth, esp_eth_state_t state, void *args)
|
||||
@ -143,18 +157,15 @@ static esp_err_t eth_on_state_changed(esp_eth_mediator_t *eth, esp_eth_state_t s
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown ethernet state: %d", state);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void eth_check_link_timer_cb(TimerHandle_t xTimer)
|
||||
static void eth_check_link_timer_cb(void *args)
|
||||
{
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)pvTimerGetTimerID(xTimer);
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)args;
|
||||
esp_eth_phy_t *phy = eth_driver->phy;
|
||||
esp_eth_increase_reference(eth_driver);
|
||||
phy->get_link(phy);
|
||||
esp_eth_decrease_reference(eth_driver);
|
||||
}
|
||||
|
||||
////////////////////////////////User face APIs////////////////////////////////////////////////
|
||||
@ -166,14 +177,23 @@ static void eth_check_link_timer_cb(TimerHandle_t xTimer)
|
||||
esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_t *out_hdl)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_GOTO_ON_FALSE(config, ESP_ERR_INVALID_ARG, err, TAG, "eth config can't be null");
|
||||
ESP_GOTO_ON_FALSE(out_hdl, ESP_ERR_INVALID_ARG, err, TAG, "eth handle can't be null");
|
||||
esp_eth_mac_t *mac = config->mac;
|
||||
esp_eth_phy_t *phy = config->phy;
|
||||
esp_eth_mac_t *mac = NULL;
|
||||
esp_eth_phy_t *phy = NULL;
|
||||
esp_eth_driver_t *eth_driver = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && out_hdl, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
mac = config->mac;
|
||||
phy = config->phy;
|
||||
ESP_GOTO_ON_FALSE(mac && phy, ESP_ERR_INVALID_ARG, err, TAG, "can't set eth->mac or eth->phy to null");
|
||||
// eth_driver contains an atomic variable, which should not be put in PSRAM
|
||||
esp_eth_driver_t *eth_driver = heap_caps_calloc(1, sizeof(esp_eth_driver_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_NO_MEM, err, TAG, "request memory for eth_driver failed");
|
||||
eth_driver = heap_caps_calloc(1, sizeof(esp_eth_driver_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_NO_MEM, err, TAG, "no mem for eth_driver");
|
||||
const esp_timer_create_args_t check_link_timer_args = {
|
||||
.callback = eth_check_link_timer_cb,
|
||||
.name = "eth_link_timer",
|
||||
.arg = eth_driver,
|
||||
.skip_unhandled_events = true
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(esp_timer_create(&check_link_timer_args, ð_driver->check_link_timer), err, TAG, "create link timer failed");
|
||||
atomic_init(ð_driver->ref_count, 1);
|
||||
atomic_init(ð_driver->fsm, ESP_ETH_FSM_STOP);
|
||||
eth_driver->mac = mac;
|
||||
@ -184,20 +204,24 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_
|
||||
eth_driver->stack_input = config->stack_input;
|
||||
eth_driver->on_lowlevel_init_done = config->on_lowlevel_init_done;
|
||||
eth_driver->on_lowlevel_deinit_done = config->on_lowlevel_deinit_done;
|
||||
eth_driver->check_link_period_ms = config->check_link_period_ms;
|
||||
eth_driver->customized_read_phy_reg = config->read_phy_reg;
|
||||
eth_driver->customized_write_phy_reg = config->write_phy_reg;
|
||||
eth_driver->mediator.phy_reg_read = eth_phy_reg_read;
|
||||
eth_driver->mediator.phy_reg_write = eth_phy_reg_write;
|
||||
eth_driver->mediator.stack_input = eth_stack_input;
|
||||
eth_driver->mediator.on_state_changed = eth_on_state_changed;
|
||||
/* some PHY can't output RMII clock if in reset state, so hardware reset PHY chip firstly */
|
||||
// set mediator for both mac and phy object, so that mac and phy are connected to each other via mediator
|
||||
mac->set_mediator(mac, ð_driver->mediator);
|
||||
phy->set_mediator(phy, ð_driver->mediator);
|
||||
// for PHY whose internal PLL has been configured to generate RMII clock, but is put in reset state during power up,
|
||||
// we need to deasseert the reset GPIO of PHY device first, ensure the RMII is clocked out from PHY
|
||||
phy->reset_hw(phy);
|
||||
ESP_GOTO_ON_ERROR(mac->set_mediator(mac, ð_driver->mediator), err_mediator, TAG, "set mediator for mac failed");
|
||||
ESP_GOTO_ON_ERROR(phy->set_mediator(phy, ð_driver->mediator), err_mediator, TAG, "set mediator for phy failed");
|
||||
ESP_GOTO_ON_ERROR(mac->init(mac), err_init_mac, TAG, "init mac failed");
|
||||
ESP_GOTO_ON_ERROR(phy->init(phy), err_init_phy, TAG, "init phy failed");
|
||||
eth_driver->check_link_timer = xTimerCreate("eth_link_timer", pdMS_TO_TICKS(config->check_link_period_ms), pdTRUE,
|
||||
eth_driver, eth_check_link_timer_cb);
|
||||
ESP_GOTO_ON_FALSE(eth_driver->check_link_timer, ESP_FAIL, err_create_timer, TAG, "create eth_link_timer failed");
|
||||
*out_hdl = (esp_eth_handle_t)eth_driver;
|
||||
// init MAC first, so that MAC can generate the correct SMI signals
|
||||
ESP_GOTO_ON_ERROR(mac->init(mac), err, TAG, "init mac failed");
|
||||
ESP_GOTO_ON_ERROR(phy->init(phy), err, TAG, "init phy failed");
|
||||
ESP_LOGD(TAG, "new ethernet driver @%p", eth_driver);
|
||||
*out_hdl = eth_driver;
|
||||
|
||||
// for backward compatible to 4.0, and will get removed in 5.0
|
||||
#if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
|
||||
@ -206,14 +230,13 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
err_create_timer:
|
||||
phy->deinit(phy);
|
||||
err_init_phy:
|
||||
mac->deinit(mac);
|
||||
err_init_mac:
|
||||
err_mediator:
|
||||
free(eth_driver);
|
||||
err:
|
||||
if (eth_driver) {
|
||||
if (eth_driver->check_link_timer) {
|
||||
esp_timer_delete(eth_driver->check_link_timer);
|
||||
}
|
||||
free(eth_driver);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -221,28 +244,21 @@ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
// check if driver has started
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
// check if driver has stopped
|
||||
esp_eth_fsm_t expected_fsm = ESP_ETH_FSM_STOP;
|
||||
if (!atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_STOP)) {
|
||||
ESP_LOGW(TAG, "driver not stopped yet");
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto err;
|
||||
}
|
||||
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_STOP),
|
||||
ESP_ERR_INVALID_STATE, err, TAG, "driver not stopped yet");
|
||||
// don't uninstall driver unless there's only one reference
|
||||
int expected_ref_count = 1;
|
||||
if (!atomic_compare_exchange_strong(ð_driver->ref_count, &expected_ref_count, 0)) {
|
||||
ESP_LOGE(TAG, "%d ethernet reference in use", expected_ref_count);
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto err;
|
||||
}
|
||||
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->ref_count, &expected_ref_count, 0),
|
||||
ESP_ERR_INVALID_STATE, err, TAG, "%d ethernet reference in use", expected_ref_count);
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
esp_eth_phy_t *phy = eth_driver->phy;
|
||||
ESP_GOTO_ON_FALSE(xTimerDelete(eth_driver->check_link_timer, 0) == pdPASS, ESP_FAIL, err, TAG, "delete eth_link_timer failed");
|
||||
ESP_GOTO_ON_ERROR(esp_timer_delete(eth_driver->check_link_timer), err, TAG, "delete link timer failed");
|
||||
ESP_GOTO_ON_ERROR(phy->deinit(phy), err, TAG, "deinit phy failed");
|
||||
ESP_GOTO_ON_ERROR(mac->deinit(mac), err, TAG, "deinit mac failed");
|
||||
free(eth_driver);
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -252,19 +268,17 @@ esp_err_t esp_eth_start(esp_eth_handle_t hdl)
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
// check if driver has started
|
||||
esp_eth_phy_t *phy = eth_driver->phy;
|
||||
// check if driver has stopped
|
||||
esp_eth_fsm_t expected_fsm = ESP_ETH_FSM_STOP;
|
||||
if (!atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_START)) {
|
||||
ESP_LOGW(TAG, "driver started already");
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto err;
|
||||
}
|
||||
ESP_GOTO_ON_ERROR(eth_driver->phy->reset(eth_driver->phy), err, TAG, "reset phy failed");
|
||||
ESP_GOTO_ON_FALSE(xTimerStart(eth_driver->check_link_timer, 0), ESP_FAIL, err, TAG, "start eth_link_timer failed");
|
||||
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(esp_eth_driver_t *), 0), err_event, TAG, "send ETHERNET_EVENT_START event failed");
|
||||
return ESP_OK;
|
||||
err_event:
|
||||
xTimerStop(eth_driver->check_link_timer, 0);
|
||||
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_START),
|
||||
ESP_ERR_INVALID_STATE, err, TAG, "driver started already");
|
||||
// reset PHY device, to put it back to LINK_DOWN state
|
||||
ESP_GOTO_ON_ERROR(phy->reset(phy), err, TAG, "reset phy failed");
|
||||
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(esp_eth_driver_t *), 0),
|
||||
err, TAG, "send ETHERNET_EVENT_START event failed");
|
||||
ESP_GOTO_ON_ERROR(esp_timer_start_periodic(eth_driver->check_link_timer, eth_driver->check_link_period_ms * 1000),
|
||||
err, TAG, "start link timer failed");
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -274,18 +288,15 @@ esp_err_t esp_eth_stop(esp_eth_handle_t hdl)
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
// check if driver has started
|
||||
esp_eth_fsm_t expected_fsm = ESP_ETH_FSM_START;
|
||||
if (!atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_STOP)) {
|
||||
ESP_LOGW(TAG, "driver not started yet");
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto err;
|
||||
}
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_STOP),
|
||||
ESP_ERR_INVALID_STATE, err, TAG, "driver not started yet");
|
||||
ESP_GOTO_ON_ERROR(esp_timer_stop(eth_driver->check_link_timer), err, TAG, "stop link timer failed");
|
||||
ESP_GOTO_ON_ERROR(mac->stop(mac), err, TAG, "stop mac failed");
|
||||
ESP_GOTO_ON_FALSE(xTimerStop(eth_driver->check_link_timer, 0), ESP_FAIL, err, TAG, "stop eth_link_timer failed");
|
||||
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(esp_eth_driver_t *), 0), err, TAG, "send ETHERNET_EVENT_STOP event failed");
|
||||
return ESP_OK;
|
||||
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(esp_eth_driver_t *), 0),
|
||||
err, TAG, "send ETHERNET_EVENT_STOP event failed");
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -300,7 +311,6 @@ esp_err_t esp_eth_update_input_path(
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
eth_driver->priv = priv;
|
||||
eth_driver->stack_input = stack_input;
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -313,7 +323,7 @@ esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length)
|
||||
ESP_GOTO_ON_FALSE(length, ESP_ERR_INVALID_ARG, err, TAG, "buf length can't be zero");
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
return mac->transmit(mac, buf, length);
|
||||
ret = mac->transmit(mac, buf, length);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -326,7 +336,7 @@ esp_err_t esp_eth_receive(esp_eth_handle_t hdl, uint8_t *buf, uint32_t *length)
|
||||
ESP_GOTO_ON_FALSE(*length > 60, ESP_ERR_INVALID_ARG, err, TAG, "length can't be less than 60");
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
return mac->receive(mac, buf, length);
|
||||
ret = mac->receive(mac, buf, length);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -374,7 +384,6 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data)
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown io command: %d", cmd);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -385,7 +394,6 @@ esp_err_t esp_eth_increase_reference(esp_eth_handle_t hdl)
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
atomic_fetch_add(ð_driver->ref_count, 1);
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@ -396,7 +404,6 @@ esp_err_t esp_eth_decrease_reference(esp_eth_handle_t hdl)
|
||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null");
|
||||
atomic_fetch_sub(ð_driver->ref_count, 1);
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user