drivers: ethernet: stm32: Add carrier state detection

This patch adds carrier state detection to the STM32 Ethernet driver.

Fixes #16097

Signed-off-by: Markus Fuchs <markus.fuchs@de.sauter-bc.com>
This commit is contained in:
Markus Fuchs 2019-09-15 11:33:38 +02:00 committed by Maureen Helm
parent 1911a7599c
commit f08caaf677
3 changed files with 46 additions and 10 deletions

View file

@ -88,4 +88,12 @@ config ETH_STM32_HAL_MII
help
Use the MII physical interface instead of RMII.
config ETH_STM32_CARRIER_CHECK_RX_IDLE_TIMEOUT_MS
int "Carrier check timeout period (ms)"
default 500
range 100 30000
help
Set the RX idle timeout period in milliseconds after which the
PHY's carrier status is re-evaluated.
endif # ETH_STM32_HAL

View file

@ -230,6 +230,7 @@ static void rx_thread(void *arg1, void *unused1, void *unused2)
struct eth_stm32_hal_dev_data *dev_data;
struct net_pkt *pkt;
int res;
u32_t status;
__ASSERT_NO_MSG(arg1 != NULL);
ARG_UNUSED(unused1);
@ -241,16 +242,39 @@ static void rx_thread(void *arg1, void *unused1, void *unused2)
__ASSERT_NO_MSG(dev_data != NULL);
while (1) {
k_sem_take(&dev_data->rx_int_sem, K_FOREVER);
while ((pkt = eth_rx(dev)) != NULL) {
net_pkt_print_frags(pkt);
res = net_recv_data(dev_data->iface, pkt);
if (res < 0) {
eth_stats_update_errors_rx(dev_data->iface);
LOG_ERR("Failed to enqueue frame "
"into RX queue: %d", res);
net_pkt_unref(pkt);
res = k_sem_take(&dev_data->rx_int_sem,
K_MSEC(CONFIG_ETH_STM32_CARRIER_CHECK_RX_IDLE_TIMEOUT_MS));
if (res == 0) {
/* semaphore taken, update link status and receive packets */
if (dev_data->link_up != true) {
dev_data->link_up = true;
net_eth_carrier_on(dev_data->iface);
}
while ((pkt = eth_rx(dev)) != NULL) {
net_pkt_print_frags(pkt);
res = net_recv_data(dev_data->iface, pkt);
if (res < 0) {
eth_stats_update_errors_rx(dev_data->iface);
LOG_ERR("Failed to enqueue frame "
"into RX queue: %d", res);
net_pkt_unref(pkt);
}
}
} else if (res == -EAGAIN) {
/* semaphore timeout period expired, check link status */
if (HAL_ETH_ReadPHYRegister(&dev_data->heth, PHY_BSR,
(uint32_t *) &status) == HAL_OK) {
if ((status & PHY_LINKED_STATUS) == PHY_LINKED_STATUS) {
if (dev_data->link_up != true) {
dev_data->link_up = true;
net_eth_carrier_on(dev_data->iface);
}
} else {
if (dev_data->link_up != false) {
dev_data->link_up = false;
net_eth_carrier_off(dev_data->iface);
}
}
}
}
}
@ -382,6 +406,8 @@ static void eth_iface_init(struct net_if *iface)
return;
}
dev_data->link_up = false;
/* Initialize semaphores */
k_mutex_init(&dev_data->tx_mutex);
k_sem_init(&dev_data->rx_int_sem, 0, UINT_MAX);
@ -417,6 +443,7 @@ static void eth_iface_init(struct net_if *iface)
NET_LINK_ETHERNET);
ethernet_init(iface);
net_if_flag_set(iface, NET_IF_NO_AUTO_START);
}
static enum ethernet_hw_caps eth_stm32_hal_get_capabilities(struct device *dev)

View file

@ -37,6 +37,7 @@ struct eth_stm32_hal_dev_data {
K_THREAD_STACK_MEMBER(rx_thread_stack,
CONFIG_ETH_STM32_HAL_RX_THREAD_STACK_SIZE);
struct k_thread rx_thread;
bool link_up;
};
#define DEV_CFG(dev) \