1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/stm32/periph_eth: add stm32_eth_tracing

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.
This commit is contained in:
Marian Buschsieweke 2022-08-08 13:20:21 +02:00
parent efc307455e
commit 44b62e879d
No known key found for this signature in database
GPG Key ID: CB8E3238CE715A94
4 changed files with 127 additions and 0 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;
@ -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;
@ -517,6 +579,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 */
@ -524,6 +590,10 @@ 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");
}
@ -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;
@ -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);
}

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) {

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_%