ethernet: better control start/stop/uninstall/install
This commit is contained in:
parent
e07023b9c7
commit
63dae58176
1 changed files with 29 additions and 15 deletions
|
@ -34,7 +34,10 @@ static const char *TAG = "esp_eth";
|
|||
|
||||
ESP_EVENT_DEFINE_BASE(ETH_EVENT);
|
||||
|
||||
#define ESP_ETH_FLAGS_STARTED (1<<0)
|
||||
typedef enum {
|
||||
ESP_ETH_FSM_STOP,
|
||||
ESP_ETH_FSM_START
|
||||
} esp_eth_fsm_t;
|
||||
|
||||
/**
|
||||
* @brief The Ethernet driver mainly consists of PHY, MAC and
|
||||
|
@ -56,7 +59,7 @@ typedef struct {
|
|||
eth_link_t link;
|
||||
atomic_int ref_count;
|
||||
void *priv;
|
||||
uint32_t flags;
|
||||
_Atomic esp_eth_fsm_t fsm;
|
||||
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);
|
||||
|
@ -175,6 +178,7 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_
|
|||
esp_eth_driver_t *eth_driver = heap_caps_calloc(1, sizeof(esp_eth_driver_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ETH_CHECK(eth_driver, "request memory for eth_driver failed", err, ESP_ERR_NO_MEM);
|
||||
atomic_init(ð_driver->ref_count, 1);
|
||||
atomic_init(ð_driver->fsm, ESP_ETH_FSM_STOP);
|
||||
eth_driver->mac = mac;
|
||||
eth_driver->phy = phy;
|
||||
eth_driver->link = ETH_LINK_DOWN;
|
||||
|
@ -221,9 +225,20 @@ 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;
|
||||
ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG);
|
||||
// check if driver has started
|
||||
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;
|
||||
}
|
||||
// don't uninstall driver unless there's only one reference
|
||||
ETH_CHECK(atomic_load(ð_driver->ref_count) == 1,
|
||||
"more than one reference to ethernet driver", err, ESP_ERR_INVALID_STATE);
|
||||
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_eth_mac_t *mac = eth_driver->mac;
|
||||
esp_eth_phy_t *phy = eth_driver->phy;
|
||||
ETH_CHECK(xTimerDelete(eth_driver->check_link_timer, 0) == pdPASS, "delete eth_link_timer failed", err, ESP_FAIL);
|
||||
|
@ -241,12 +256,12 @@ esp_err_t esp_eth_start(esp_eth_handle_t hdl)
|
|||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG);
|
||||
// check if driver has started
|
||||
if (eth_driver->flags & ESP_ETH_FLAGS_STARTED) {
|
||||
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;
|
||||
}
|
||||
eth_driver->flags |= ESP_ETH_FLAGS_STARTED;
|
||||
ETH_CHECK(eth_driver->phy->reset(eth_driver->phy) == ESP_OK, "reset phy failed", err, ESP_FAIL);
|
||||
ETH_CHECK(xTimerStart(eth_driver->check_link_timer, 0) == pdPASS,
|
||||
"start eth_link_timer failed", err, ESP_FAIL);
|
||||
|
@ -265,19 +280,18 @@ esp_err_t esp_eth_stop(esp_eth_handle_t hdl)
|
|||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||
ETH_CHECK(eth_driver, "ethernet driver handle can't be null", err, ESP_ERR_INVALID_ARG);
|
||||
// check if driver has started
|
||||
if (eth_driver->flags & ESP_ETH_FLAGS_STARTED) {
|
||||
eth_driver->flags &= ~ESP_ETH_FLAGS_STARTED;
|
||||
esp_eth_mac_t *mac = eth_driver->mac;
|
||||
ETH_CHECK(mac->stop(mac) == ESP_OK, "stop mac failed", err, ESP_FAIL);
|
||||
ETH_CHECK(xTimerStop(eth_driver->check_link_timer, 0) == pdPASS,
|
||||
"stop eth_link_timer failed", err, ESP_FAIL);
|
||||
ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(eth_driver), 0) == ESP_OK,
|
||||
"send ETHERNET_EVENT_STOP event failed", err, ESP_FAIL);
|
||||
} else {
|
||||
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;
|
||||
ETH_CHECK(mac->stop(mac) == ESP_OK, "stop mac failed", err, ESP_FAIL);
|
||||
ETH_CHECK(xTimerStop(eth_driver->check_link_timer, 0) == pdPASS,
|
||||
"stop eth_link_timer failed", err, ESP_FAIL);
|
||||
ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(eth_driver), 0) == ESP_OK,
|
||||
"send ETHERNET_EVENT_STOP event failed", err, ESP_FAIL);
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
|
|
Loading…
Reference in a new issue