1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

Merge pull request #18418 from maribu/cpu/stm32/periph/stm32_eth_tracing

cpu/stm32/periph_eth: Add stm32_eth_tracing
This commit is contained in:
Marian Buschsieweke 2022-09-18 22:19:34 +02:00 committed by GitHub
commit e402f1d885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 158 additions and 5 deletions

View File

@ -16,6 +16,10 @@ ifneq (,$(filter stm32_eth_%,$(USEMODULE)))
USEMODULE += stm32_eth
endif
ifneq (,$(filter stm32_eth_tracing,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio_ll
endif
ifneq (,$(filter stm32_eth_auto,$(USEMODULE)))
USEMODULE += stm32_eth_link_up
endif

View File

@ -25,6 +25,7 @@
#include <string.h>
#include "bitarithm.h"
#include "board.h"
#include "iolist.h"
#include "mii.h"
#include "mutex.h"
@ -32,6 +33,7 @@
#include "net/eui_provider.h"
#include "net/netdev/eth.h"
#include "periph/gpio.h"
#include "periph/gpio_ll.h"
#include "timex.h"
#define ENABLE_DEBUG 0
@ -91,6 +93,58 @@ static ztimer_t _link_status_timer;
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
/**
* @name GPIOs to use for tracing STM32 Ethernet state via module
* `stm32_eth_tracing`
* @{
*/
#ifndef STM32_ETH_TRACING_TX_PIN_NUM
# if defined(LED1_PIN_NUM) || defined(DOXYGEN)
/**
* @brief pin to trace TX events
*
* This pin will be set when TX starts and cleared when the corresponding
*/
# define STM32_ETH_TRACING_TX_PIN_NUM LED1_PIN_NUM
# else
# define STM32_ETH_TRACING_TX_PIN_NUM 0
# endif
#endif
#ifndef STM32_ETH_TRACING_TX_PORT_NUM
# if defined(LED1_PORT_NUM) || defined(DOXYGEN)
/**
* @brief port to trace TX events
*/
# define STM32_ETH_TRACING_TX_PORT_NUM LED1_PORT_NUM
# else
# define STM32_ETH_TRACING_TX_PORT_NUM 0
# endif
#endif
#ifndef STM32_ETH_TRACING_RX_PIN_NUM
# if defined(LED2_PIN_NUM) || defined(DOXYGEN)
/**
* @brief pin to trace RX events
*/
# define STM32_ETH_TRACING_RX_PIN_NUM LED2_PIN_NUM
# else
# define STM32_ETH_TRACING_RX_PIN_NUM 0
# endif
#endif
#ifndef STM32_ETH_TRACING_RX_PORT_NUM
# if defined(LED2_PORT_NUM) || defined(DOXYGEN)
/**
* @brief port to trace RX events
*/
# define STM32_ETH_TRACING_RX_PORT_NUM LED2_PORT_NUM
# else
# define STM32_ETH_TRACING_RX_PORT_NUM 0
# endif
#endif
/** @} */
/* Synchronization between IRQ and thread context */
mutex_t stm32_eth_tx_completed = MUTEX_INIT_LOCKED;
@ -115,8 +169,17 @@ static void _debug_tx_descriptor_info(unsigned line)
DEBUG("[stm32_eth:%u] TX descriptors:\n", line);
for (unsigned i = 0; i < ETH_TX_DESCRIPTOR_COUNT; i++) {
uint32_t status = tx_desc[i].status;
char next_valid;
if (i < ETH_TX_DESCRIPTOR_COUNT - 1) {
next_valid = (tx_desc[i].desc_next == &tx_desc[i + 1])
? '1' : '0';
}
else {
next_valid = (tx_desc[i].desc_next == &tx_desc[0])
? '1' : '0';
}
DEBUG(" %s %u: OWN=%c, ES=%c, UF=%c, EC=%c, NC=%c, FS=%c, "
"LS=%c\n",
"LS=%c, next valid=%c\n",
(tx_curr == tx_desc + i) ? "-->" : " ",
i,
(status & TX_DESC_STAT_OWN) ? '1' : '0',
@ -125,7 +188,8 @@ static void _debug_tx_descriptor_info(unsigned line)
(status & TX_DESC_STAT_EC) ? '1' : '0',
(status & TX_DESC_STAT_NC) ? '1' : '0',
(status & TX_DESC_STAT_FS) ? '1' : '0',
(status & TX_DESC_STAT_LS) ? '1' : '0');
(status & TX_DESC_STAT_LS) ? '1' : '0',
next_valid);
}
}
}
@ -142,7 +206,17 @@ static void _debug_rx_descriptor_info(unsigned line)
DEBUG("[stm32_eth:%u] RX descriptors:\n", line);
for (unsigned i = 0; i < ETH_RX_DESCRIPTOR_COUNT; i++) {
uint32_t status = rx_desc[i].status;
DEBUG(" %s %u: OWN=%c, FS=%c, LS=%c, ES=%c, DE=%c, FL=%" PRIu32 "\n",
char next_valid;
if (i < ETH_RX_DESCRIPTOR_COUNT - 1) {
next_valid = (rx_desc[i].desc_next == &rx_desc[i + 1])
? '1' : '0';
}
else {
next_valid = (rx_desc[i].desc_next == &rx_desc[0])
? '1' : '0';
}
DEBUG(" %s %u: OWN=%c, FS=%c, LS=%c, ES=%c, DE=%c, FL=%" PRIu32
", next valid=%c\n",
(rx_curr == rx_desc + i) ? "-->" : " ",
i,
(status & RX_DESC_STAT_OWN) ? '1' : '0',
@ -150,7 +224,8 @@ static void _debug_rx_descriptor_info(unsigned line)
(status & RX_DESC_STAT_LS) ? '1' : '0',
(status & RX_DESC_STAT_ES) ? '1' : '0',
(status & RX_DESC_STAT_DE) ? '1' : '0',
_len_from_rx_desc_status(status));
_len_from_rx_desc_status(status),
next_valid);
}
}
}
@ -249,6 +324,8 @@ static void _init_dma_descriptors(void)
ETH->DMARDLAR = (uintptr_t)rx_curr;
ETH->DMATDLAR = (uintptr_t)tx_curr;
_debug_rx_descriptor_info(__LINE__);
_debug_tx_descriptor_info(__LINE__);
}
static void _reset_eth_dma(void)
@ -408,6 +485,14 @@ static void _setup_phy(void)
static int stm32_eth_init(netdev_t *netdev)
{
(void)netdev;
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_init(GPIO_PORT(STM32_ETH_TRACING_TX_PORT_NUM),
STM32_ETH_TRACING_TX_PIN_NUM,
&gpio_ll_out);
gpio_ll_init(GPIO_PORT(STM32_ETH_TRACING_RX_PORT_NUM),
STM32_ETH_TRACING_RX_PIN_NUM,
&gpio_ll_out);
}
if (IS_USED(MODULE_STM32_ETH_LINK_UP)) {
_link_status_timer.callback = _timer_cb;
_link_status_timer.arg = netdev;
@ -480,6 +565,7 @@ static int stm32_eth_send(netdev_t *netdev, const struct iolist *iolist)
/* We cannot send more chunks than allocated descriptors */
assert(iolist_count(iolist) <= ETH_TX_DESCRIPTOR_COUNT);
_debug_tx_descriptor_info(__LINE__);
edma_desc_t *dma_iter = tx_curr;
for (unsigned i = 0; iolist; iolist = iolist->iol_next, i++) {
dma_iter->control = iolist->iol_len;
@ -498,6 +584,10 @@ static int stm32_eth_send(netdev_t *netdev, const struct iolist *iolist)
dma_iter = dma_iter->desc_next;
}
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_set(GPIO_PORT(STM32_ETH_TRACING_TX_PORT_NUM),
(1U << STM32_ETH_TRACING_TX_PIN_NUM));
}
/* start TX */
ETH->DMATPDR = 0;
/* await completion */
@ -505,12 +595,15 @@ static int stm32_eth_send(netdev_t *netdev, const struct iolist *iolist)
DEBUG("[stm32_eth] Started to send %u B via DMA\n", bytes_to_send);
}
mutex_lock(&stm32_eth_tx_completed);
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_clear(GPIO_PORT(STM32_ETH_TRACING_TX_PORT_NUM),
(1U << STM32_ETH_TRACING_TX_PIN_NUM));
}
if (IS_ACTIVE(ENABLE_DEBUG_VERBOSE)) {
DEBUG("[stm32_eth] TX completed\n");
}
/* Error check */
_debug_tx_descriptor_info(__LINE__);
int error = 0;
while (1) {
uint32_t status = tx_curr->status;
@ -540,6 +633,8 @@ static int stm32_eth_send(netdev_t *netdev, const struct iolist *iolist)
}
}
_debug_tx_descriptor_info(__LINE__);
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
if (error) {
return error;
@ -673,6 +768,11 @@ static int stm32_eth_recv(netdev_t *netdev, void *_buf, size_t max_len,
rx_curr = rx_curr->desc_next;
}
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_clear(GPIO_PORT(STM32_ETH_TRACING_RX_PORT_NUM),
(1U << STM32_ETH_TRACING_RX_PIN_NUM));
}
_debug_rx_descriptor_info(__LINE__);
handle_lost_rx_irqs();
return size;
@ -706,6 +806,10 @@ static void stm32_eth_isr(netdev_t *netdev)
}
}
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_set(GPIO_PORT(STM32_ETH_TRACING_RX_PORT_NUM),
(1U << STM32_ETH_TRACING_RX_PIN_NUM));
}
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
}

View File

@ -21,9 +21,11 @@
*/
#include <string.h>
#include "board.h"
#include "mutex.h"
#include "net/netdev/eth.h"
#include "periph/gpio.h"
#include "periph/gpio_ll.h"
#include "periph/ptp.h"
#include "periph_conf.h"
#include "periph_cpu.h"
@ -31,6 +33,37 @@
#define ENABLE_DEBUG 0
#include "debug.h"
/**
* @name GPIOs to use for tracing STM32 Ethernet state via module
* `stm32_eth_tracing`
* @{
*/
#ifndef STM32_ETH_TRACING_IRQ_PIN_NUM
# if defined(LED0_PIN_NUM) || defined(DOXYGEN)
/**
* @brief pin to trace IRQs
*
* This GPIO pin will be toggled every time the Ethernet ISR is executed
* (upon entry of the ISR).
*/
# define STM32_ETH_TRACING_IRQ_PIN_NUM LED0_PIN_NUM
# else
# define STM32_ETH_TRACING_IRQ_PIN_NUM 0
# endif
#endif
#ifndef STM32_ETH_TRACING_IRQ_PORT_NUM
# if defined(LED0_PORT_NUM) || defined(DOXYGEN)
/**
* @brief port to trace IRQs
*/
# define STM32_ETH_TRACING_IRQ_PORT_NUM LED0_PORT_NUM
# else
# define STM32_ETH_TRACING_IRQ_PORT_NUM 0
# endif
#endif
/** @} */
void stm32_eth_common_init(void)
{
/* enable APB2 clock */
@ -59,6 +92,12 @@ void stm32_eth_common_init(void)
ETH->DMABMR |= ETH_DMABMR_SR;
while (ETH->DMABMR & ETH_DMABMR_SR) {}
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_init(GPIO_PORT(STM32_ETH_TRACING_IRQ_PORT_NUM),
STM32_ETH_TRACING_IRQ_PIN_NUM,
&gpio_ll_out);
}
if (IS_USED(MODULE_PERIPH_ETH) || IS_USED(MODULE_PERIPH_PTP_TIMER)) {
NVIC_EnableIRQ(ETH_IRQn);
}
@ -68,6 +107,10 @@ void stm32_eth_common_init(void)
void isr_eth(void)
{
DEBUG("[periph_eth_common] isr_eth()\n");
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_toggle(GPIO_PORT(STM32_ETH_TRACING_IRQ_PORT_NUM),
(1U << STM32_ETH_TRACING_IRQ_PIN_NUM));
}
if (IS_USED(MODULE_PERIPH_PTP_TIMER)) {
if (ETH->MACSR & ETH_MACSR_TSTS) {
@ -82,6 +125,7 @@ void isr_eth(void)
extern mutex_t stm32_eth_tx_completed;
unsigned tmp = ETH->DMASR;
ETH->DMASR = ETH_DMASR_NIS | ETH_DMASR_TS | ETH_DMASR_RS;
DEBUG("[periph_eth_common] DMASR = 0x%x\n", tmp);
if ((tmp & ETH_DMASR_TS)) {
DEBUG("isr_eth: TX completed\n");

View File

@ -236,6 +236,7 @@ PSEUDOMODULES += stdio_telnet
PSEUDOMODULES += stm32_eth
PSEUDOMODULES += stm32_eth_auto
PSEUDOMODULES += stm32_eth_link_up
PSEUDOMODULES += stm32_eth_tracing
PSEUDOMODULES += stm32mp1_eng_mode
PSEUDOMODULES += suit_transport_%
PSEUDOMODULES += suit_storage_%