Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions drivers/ethernet/Kconfig.stm32_hal
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ config ETH_STM32_HW_CHECKSUM
performances.
See reference manual for more information on this feature.

config ETH_STM32_HAL_TX_ASYNC
bool "Use TX async mode"
default n
depends on ETH_STM32_HAL_API_V2
help
Enable TX transmission asynchronous mode to enhance throughput
performances.

menuconfig PTP_CLOCK_STM32_HAL
bool "STM32 HAL PTP clock driver support"
default y
Expand Down
161 changes: 138 additions & 23 deletions drivers/ethernet/eth_stm32_hal_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,120 @@ static inline uint16_t allocate_tx_buffer(void)
}
}

#if defined(CONFIG_ETH_STM32_HAL_TX_ASYNC)
/* allocate a tx context and mark it as used, the first tx buffer is also allocated */
static struct eth_stm32_tx_context *allocate_tx_context_async(struct net_pkt *pkt)
{
int tx_index;

for (uint16_t index = 0; index < ETH_TX_DESC_CNT; index++) {
if (!dma_tx_context[index].used) {
dma_tx_context[index].used = true;
dma_tx_context[index].pkt = pkt;
tx_index = allocate_tx_buffer();
if (tx_index < 0) {
return NULL;
}
dma_tx_context[index].first_tx_buffer_index = tx_index;
return &dma_tx_context[index];
}
}
return NULL;
}

int eth_stm32_tx(const struct device *dev, struct net_pkt *pkt)
{
struct eth_stm32_hal_dev_data *dev_data = dev->data;
ETH_HandleTypeDef *heth = &dev_data->heth;
int res = 0;
size_t total_len;
size_t remaining_read;
struct eth_stm32_tx_context *ctx = NULL;
struct eth_stm32_tx_buffer_header *buf_header = NULL;
HAL_StatusTypeDef hal_ret = HAL_OK;

#if defined(CONFIG_PTP_CLOCK_STM32_HAL)
bool timestamped_frame;
#endif /* CONFIG_PTP_CLOCK_STM32_HAL */

__ASSERT_NO_MSG(pkt != NULL);
__ASSERT_NO_MSG(pkt->frags != NULL);

total_len = net_pkt_get_len(pkt);
if (total_len > (ETH_STM32_TX_BUF_SIZE * ETH_TXBUFNB)) {
LOG_ERR("PKT too big");
return -EIO;
}

k_mutex_lock(&dev_data->tx_mutex, K_FOREVER);

while (ctx == NULL) {
ctx = allocate_tx_context_async(pkt);
if (ctx == NULL) {
k_sem_take(&dev_data->tx_int_sem, K_MSEC(ETH_DMA_TX_TIMEOUT_MS));
hal_ret = HAL_ETH_ReleaseTxPacket(heth);
__ASSERT_NO_MSG(hal_ret == HAL_OK);
}
}
buf_header = &dma_tx_buffer_header[ctx->first_tx_buffer_index];

#if defined(CONFIG_PTP_CLOCK_STM32_HAL)
timestamped_frame = eth_stm32_is_ptp_pkt(net_pkt_iface(pkt), pkt) ||
net_pkt_is_tx_timestamping(pkt);
if (timestamped_frame) {
/* Enable transmit timestamp */
if (HAL_ETH_PTP_InsertTxTimestamp(heth) != HAL_OK) {
res = -EIO;
goto error;
}
}
#endif /* CONFIG_PTP_CLOCK_STM32_HAL */

remaining_read = total_len;
/* fill and allocate buffer until remaining data fits in one buffer */
while (remaining_read > ETH_STM32_TX_BUF_SIZE) {
res = net_pkt_read(pkt, buf_header->tx_buff.buffer, ETH_STM32_TX_BUF_SIZE);
if (res < 0) {
goto error;
}

const uint16_t next_buffer_id = allocate_tx_buffer();

buf_header->tx_buff.len = ETH_STM32_TX_BUF_SIZE;
/* append new buffer to the linked list */
buf_header->tx_buff.next = &dma_tx_buffer_header[next_buffer_id].tx_buff;
/* and adjust tail pointer */
buf_header = &dma_tx_buffer_header[next_buffer_id];
remaining_read -= ETH_STM32_TX_BUF_SIZE;
}
res = net_pkt_read(pkt, buf_header->tx_buff.buffer, remaining_read);
if (res < 0) {
goto error;
}
buf_header->tx_buff.len = remaining_read;
buf_header->tx_buff.next = NULL;

tx_config.Length = total_len;
tx_config.pData = ctx;
tx_config.TxBuffer = &dma_tx_buffer_header[ctx->first_tx_buffer_index].tx_buff;

if (HAL_ETH_Transmit_IT(heth, &tx_config) != HAL_OK) {
LOG_ERR("HAL_ETH_Transmit: failed!");
res = -EIO;
}

error:
if (res < 0 && ctx) {
/* We need to release the tx context and its buffers */
HAL_ETH_TxFreeCallback((uint32_t *)ctx);
}

k_mutex_unlock(&dev_data->tx_mutex);

return res;
}
#else

/* allocate a tx context and mark it as used, the first tx buffer is also allocated */
static inline struct eth_stm32_tx_context *allocate_tx_context(struct net_pkt *pkt)
{
Expand All @@ -132,28 +246,6 @@ static inline struct eth_stm32_tx_context *allocate_tx_context(struct net_pkt *p
}
}

void eth_stm32_setup_mac_filter(ETH_HandleTypeDef *heth)
{
ETH_MACFilterConfigTypeDef MACFilterConf;
HAL_StatusTypeDef __maybe_unused hal_ret;

__ASSERT_NO_MSG(heth != NULL);

hal_ret = HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf);
__ASSERT_NO_MSG(hal_ret == HAL_OK);

MACFilterConf.HashMulticast =
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? ENABLE : DISABLE;
MACFilterConf.PassAllMulticast =
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? DISABLE : ENABLE;
MACFilterConf.HachOrPerfectFilter = DISABLE;

hal_ret = HAL_ETH_SetMACFilterConfig(heth, &MACFilterConf);
__ASSERT_NO_MSG(hal_ret == HAL_OK);

k_sleep(K_MSEC(1));
}

int eth_stm32_tx(const struct device *dev, struct net_pkt *pkt)
{
struct eth_stm32_hal_dev_data *dev_data = dev->data;
Expand Down Expand Up @@ -294,6 +386,7 @@ int eth_stm32_tx(const struct device *dev, struct net_pkt *pkt)

return res;
}
#endif /* ETH_STM32_HAL_TX_ASYNC */

struct net_pkt *eth_stm32_rx(const struct device *dev)
{
Expand Down Expand Up @@ -512,7 +605,7 @@ int eth_stm32_hal_init(const struct device *dev)
/* Initialize semaphores */
k_mutex_init(&dev_data->tx_mutex);
k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
k_sem_init(&dev_data->tx_int_sem, 0, K_SEM_MAX_LIMIT);
k_sem_init(&dev_data->tx_int_sem, 0, 1);

/* Tx config init: */
memset(&tx_config, 0, sizeof(ETH_TxPacketConfig));
Expand Down Expand Up @@ -559,6 +652,28 @@ void eth_stm32_set_mac_config(const struct device *dev, struct phy_link_state *s
}
}

void eth_stm32_setup_mac_filter(ETH_HandleTypeDef *heth)
{
ETH_MACFilterConfigTypeDef MACFilterConf;
HAL_StatusTypeDef __maybe_unused hal_ret;

__ASSERT_NO_MSG(heth != NULL);

hal_ret = HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf);
__ASSERT_NO_MSG(hal_ret == HAL_OK);

MACFilterConf.HashMulticast =
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? ENABLE : DISABLE;
MACFilterConf.PassAllMulticast =
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? DISABLE : ENABLE;
MACFilterConf.HachOrPerfectFilter = DISABLE;

hal_ret = HAL_ETH_SetMACFilterConfig(heth, &MACFilterConf);
__ASSERT_NO_MSG(hal_ret == HAL_OK);

k_sleep(K_MSEC(1));
}

int eth_stm32_hal_start(const struct device *dev)
{
struct eth_stm32_hal_dev_data *dev_data = dev->data;
Expand Down
1 change: 1 addition & 0 deletions samples/net/zperf/boards/nucleo_h743zi.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_ETH_STM32_HAL_TX_ASYNC=y
4 changes: 4 additions & 0 deletions samples/net/zperf/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ tests:
platform_allow: qemu_x86
extra_configs:
- CONFIG_NET_ZPERF_SERVER=n
sample.net.zperf.async_tx.stm32:
filter: dt_compat_enabled("st,stm32-ethernet")
extra_configs:
- CONFIG_ETH_STM32_HAL_TX_ASYNC=y
sample.net.zperf_st:
harness: console
harness_config:
Expand Down