Skip to content

Commit

Permalink
cpu/stm32/periph_eth: add stm32_eth_tracing
Browse files Browse the repository at this point in the history
Add tracing support via GPIOs to trace the basic state of the Ethernet
peripheral. The following signals are provided:

- One GPIO pin is toggled on entry of the Ethernet ISR
- On TX start an GPIO is set, on TX completion it is cleared
- On RX complete an GPIO is set, once this is passed to the upper layer
  the GPIO is cleared again

In order to reduce the overhead, GPIO LL is used. By default the
on-board LEDs are used as tracing GPIOs. This makes it easy to debug
when the state machine gets stuck without the need to attach a scope or
logic analyzer.
  • Loading branch information
maribu committed Sep 14, 2022
1 parent efc3074 commit 44b62e8
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cpu/stm32/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
79 changes: 79 additions & 0 deletions cpu/stm32/periph/eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@
#include <string.h>

#include "bitarithm.h"
#include "board.h"
#include "iolist.h"
#include "mii.h"
#include "mutex.h"
#include "net/ethernet.h"
#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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -431,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;
Expand Down Expand Up @@ -517,13 +579,21 @@ 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 */
if (IS_ACTIVE(ENABLE_DEBUG_VERBOSE)) {
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");
}
Expand Down Expand Up @@ -693,6 +763,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;
Expand Down Expand Up @@ -726,6 +801,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);
}

Expand Down
43 changes: 43 additions & 0 deletions cpu/stm32/periph/eth_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,49 @@
*/
#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"

#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 */
Expand Down Expand Up @@ -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);
}
Expand All @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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_%
Expand Down

0 comments on commit 44b62e8

Please sign in to comment.