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:
parent
efc307455e
commit
44b62e879d
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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_%
|
||||
|
Loading…
Reference in New Issue
Block a user