1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/stm32/periph/eth_common.c
2024-08-02 09:55:25 +02:00

146 lines
3.8 KiB
C

/*
* Copyright (C) 2016 TriaGnoSys GmbH
* 2020 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_stm32
* @{
*
* @file
* @brief Common code for the ETH and PTP driver
*
* @author Víctor Ariño <victor.arino@triagnosys.com>
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* @}
*/
#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
# if defined(LED0_PORT_NUM) || defined(DOXYGEN)
/**
* @brief port to trace IRQs
*/
# define STM32_ETH_TRACING_IRQ_PORT LED0_PORT
# else
# define STM32_ETH_TRACING_IRQ_PORT GPIO_PORT_0
# endif
#endif
/** @} */
void stm32_eth_common_init(void)
{
/* enable APB2 clock */
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
/* select RMII if necessary */
if (eth_config.mode == RMII) {
SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
}
/* initialize GPIO */
for (int i = 0; i < (int) eth_config.mode; i++) {
gpio_init(eth_config.pins[i], GPIO_OUT);
gpio_init_af(eth_config.pins[i], GPIO_AF11);
}
/* enable all clocks */
RCC->AHB1ENR |= (RCC_AHB1ENR_ETHMACEN | RCC_AHB1ENR_ETHMACTXEN |
RCC_AHB1ENR_ETHMACRXEN | RCC_AHB1ENR_ETHMACPTPEN);
/* reset the peripheral */
RCC->AHB1RSTR |= RCC_AHB1RSTR_ETHMACRST;
RCC->AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST;
/* software reset */
ETH->DMABMR |= ETH_DMABMR_SR;
while (ETH->DMABMR & ETH_DMABMR_SR) {}
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_init(STM32_ETH_TRACING_IRQ_PORT,
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);
}
}
#if IS_USED(MODULE_STM32_ETH) || IS_USED(MODULE_PERIPH_PTP_TIMER)
void isr_eth(void)
{
DEBUG("[periph_eth_common] isr_eth()\n");
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_toggle(STM32_ETH_TRACING_IRQ_PORT,
(1U << STM32_ETH_TRACING_IRQ_PIN_NUM));
}
if (IS_USED(MODULE_PERIPH_PTP_TIMER)) {
if (ETH->MACSR & ETH_MACSR_TSTS) {
/* clear interrupt by reading PTPTSSR */
(void)ETH->PTPTSSR;
ptp_timer_cb();
}
}
if (IS_USED(MODULE_STM32_ETH)) {
extern netdev_t *stm32_eth_netdev;
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");
stm32_eth_netdev->event_callback(stm32_eth_netdev,
NETDEV_EVENT_TX_COMPLETE);
}
if ((tmp & ETH_DMASR_RS)) {
DEBUG("isr_eth: RX completed\n");
if (stm32_eth_netdev) {
netdev_trigger_event_isr(stm32_eth_netdev);
}
}
}
cortexm_isr_end();
}
#endif