summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCYFS <[email protected]>2026-09-03 00:02:41 +0800
committerRbb666 <[email protected]>2026-09-15 22:59:08 +0800
commitf165a0f80473ef66c5cc0c5daf2ccf33acf89de3 (patch)
treefb2a5e0e15b00e8488f4d57d8143a0269a3e063a
parente81494f881526b257165207cf716df1043f1bb2a (diff)
[BSP][STM32] Adapt Ethernet driver to new HAL API
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/SConscript6
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/drv_eth.c1116
-rw-r--r--bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h4
-rw-r--r--bsp/stm32/stm32f407-atk-explorer/board/Kconfig6
-rw-r--r--bsp/stm32/stm32h750-artpi/board/CubeMX_Config/Core/Inc/stm32h7xx_hal_conf.h4
-rw-r--r--bsp/stm32/stm32h750-artpi/board/Kconfig5
-rw-r--r--bsp/stm32/stm32h750-artpi/board/port/SConscript3
-rw-r--r--bsp/stm32/stm32h750-artpi/board/port/drv_eth.c577
8 files changed, 754 insertions, 967 deletions
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript
index 9f07d9db01..0a9ceb24da 100644
--- a/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/SConscript
@@ -40,7 +40,11 @@ if GetDepend(['RT_USING_I2C']):
if GetDepend('BSP_USING_HARD_I2C1') or GetDepend('BSP_USING_HARD_I2C2') or GetDepend('BSP_USING_HARD_I2C3') or GetDepend('BSP_USING_HARD_I2C4'):
src += ['drv_hard_i2c.c']
-if GetDepend(['BSP_USING_ETH', 'RT_USING_LWIP']) and not GetDepend(['SOC_STM32H750_ARTPI']):
+eth_new_hal_soc = (GetDepend(['SOC_SERIES_STM32F4']) or
+ GetDepend(['SOC_SERIES_STM32F7']) or
+ GetDepend(['SOC_SERIES_STM32H7']))
+if (eth_new_hal_soc and GetDepend(['RT_USING_LWIP']) and
+ (GetDepend(['BSP_USING_ETH']) or GetDepend(['BSP_USING_ETH_H750']))):
src += ['drv_eth.c']
if GetDepend(['RT_USING_ADC']) and not GetDepend(['RT_USING_ADC_V2']):
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_eth.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_eth.c
index 7710ef2d33..afbb79c298 100644
--- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_eth.c
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_eth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2026, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -9,6 +9,9 @@
* 2018-12-25 zylx fix some bugs
* 2019-06-10 SummerGift optimize PHY state detection process
* 2019-09-03 xiaofan optimize link change detection process
+ * 2020-07-17 wanghaijing support h7
+ * 2020-11-30 wanghaijing add phy reset
+ * 2026-08-30 CYFS merge H750 driver and use the new HAL ETH API
*/
#include "drv_config.h"
@@ -17,50 +20,104 @@
#include <lwipopts.h>
/*
-* Emac driver uses CubeMX tool to generate emac and phy's configuration,
-* the configuration files can be found in CubeMX_Config folder.
-*/
+ * Emac driver uses CubeMX tool to generate emac and PHY configuration.
+ * The configuration files can be found in the CubeMX_Config folder.
+ */
/* debug option */
-//#define ETH_RX_DUMP
-//#define ETH_TX_DUMP
-//#define DRV_DEBUG
+/* #define ETH_RX_DUMP */
+/* #define ETH_TX_DUMP */
+/* #define DRV_DEBUG */
#define LOG_TAG "drv.emac"
#include <drv_log.h>
-#define MAX_ADDR_LEN 6
+#define MAX_ADDR_LEN 6U
+#define ETH_RX_BUFFER_CNT (ETH_RX_DESC_CNT * 2U)
+#define ETH_CACHE_LINE_SIZE 32U
+#define PHY_INVALID_ADDR 0xFFU
+#define PHY_STATE_UNKNOWN 0xFFU
-#undef PHY_FULL_DUPLEX
-#define PHY_LINK (1 << 0)
-#define PHY_100M (1 << 1)
-#define PHY_FULL_DUPLEX (1 << 2)
+#if defined(ETH_DMACSR_AIS)
+#define ETH_DMA_ABNORMAL_SUMMARY_FLAG ETH_DMACSR_AIS
+#elif defined(ETH_DMASR_AIS)
+#define ETH_DMA_ABNORMAL_SUMMARY_FLAG ETH_DMASR_AIS
+#else
+#define ETH_DMA_ABNORMAL_SUMMARY_FLAG 0U
+#endif
struct rt_stm32_eth
{
/* inherit from ethernet device */
struct eth_device parent;
-#ifndef PHY_USING_INTERRUPT_MODE
- rt_timer_t poll_link_timer;
-#endif
+ struct rt_mutex mac_lock;
/* interface address info, hw address */
- rt_uint8_t dev_addr[MAX_ADDR_LEN];
+ rt_uint8_t dev_addr[MAX_ADDR_LEN];
/* ETH_Speed */
- rt_uint32_t ETH_Speed;
+ rt_uint32_t ETH_Speed;
/* ETH_Duplex_Mode */
- rt_uint32_t ETH_Mode;
+ rt_uint32_t ETH_Mode;
+ rt_uint8_t phy_state;
+ rt_bool_t mac_started;
+};
+
+struct rt_stm32_eth_rx_buffer
+{
+ rt_uint16_t length;
+ rt_bool_t allocated;
+ struct rt_stm32_eth_rx_buffer *next;
};
-static ETH_DMADescTypeDef *DMARxDscrTab, *DMATxDscrTab;
-static rt_uint8_t *Rx_Buff, *Tx_Buff;
-static ETH_HandleTypeDef EthHandle;
+static ETH_HandleTypeDef EthHandle;
+static ETH_TxPacketConfigTypeDef TxConfig;
static struct rt_stm32_eth stm32_eth_device;
+static struct rt_stm32_eth_rx_buffer Rx_Buff_Info[ETH_RX_BUFFER_CNT];
+static ETH_DMADescTypeDef *DMARxDscrTab;
+static ETH_DMADescTypeDef *DMATxDscrTab;
+static rt_uint8_t *Rx_Buff;
+static rt_uint32_t rx_alloc_index;
+static rt_uint8_t phy_addr = PHY_INVALID_ADDR;
+
+#ifdef PHY_USING_INTERRUPT_MODE
+static struct rt_semaphore phy_link_sem;
+#endif
+
+#ifdef ETH_RESET_PIN
+static rt_base_t reset_pin = -1;
+#endif
+
+/* ART-Pi places all ETH DMA-owned memory in its non-cacheable D2 SRAM region. */
+#ifdef BSP_USING_ETH_H750
+#if defined(__ICCARM__)
+#pragma location=0x30040000
+static ETH_DMADescTypeDef DMARxDscrTab_Storage[ETH_RX_DESC_CNT];
+#pragma location=0x30040060
+static ETH_DMADescTypeDef DMATxDscrTab_Storage[ETH_TX_DESC_CNT];
+#pragma location=0x30040200
+static rt_uint8_t Rx_Buff_Storage[ETH_RX_BUFFER_CNT * ETH_MAX_PACKET_SIZE];
+#elif defined(__CC_ARM)
+static __attribute__((at(0x30040000))) ETH_DMADescTypeDef DMARxDscrTab_Storage[ETH_RX_DESC_CNT];
+static __attribute__((at(0x30040060))) ETH_DMADescTypeDef DMATxDscrTab_Storage[ETH_TX_DESC_CNT];
+static __attribute__((at(0x30040200))) rt_uint8_t Rx_Buff_Storage[ETH_RX_BUFFER_CNT * ETH_MAX_PACKET_SIZE];
+#elif defined(__GNUC__)
+static ETH_DMADescTypeDef DMARxDscrTab_Storage[ETH_RX_DESC_CNT]
+ __attribute__((section(".RxDecripSection"), aligned(32)));
+static ETH_DMADescTypeDef DMATxDscrTab_Storage[ETH_TX_DESC_CNT]
+ __attribute__((section(".TxDecripSection"), aligned(32)));
+static rt_uint8_t Rx_Buff_Storage[ETH_RX_BUFFER_CNT * ETH_MAX_PACKET_SIZE]
+ __attribute__((section(".RxArraySection"), aligned(32)));
+#else
+static ETH_DMADescTypeDef DMARxDscrTab_Storage[ETH_RX_DESC_CNT] __ALIGNED(32);
+static ETH_DMADescTypeDef DMATxDscrTab_Storage[ETH_TX_DESC_CNT] __ALIGNED(32);
+static rt_uint8_t Rx_Buff_Storage[ETH_RX_BUFFER_CNT * ETH_MAX_PACKET_SIZE] __ALIGNED(32);
+#endif
+#endif /* BSP_USING_ETH_H750 */
#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
-#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
+#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127U - ' ')
static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
{
- unsigned char *buf = (unsigned char *)ptr;
+ const unsigned char *buf = (const unsigned char *)ptr;
int i, j;
for (i = 0; i < buflen; i += 16)
@@ -68,113 +125,385 @@ static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
rt_kprintf("%08X: ", i);
for (j = 0; j < 16; j++)
+ {
if (i + j < buflen)
+ {
rt_kprintf("%02X ", buf[i + j]);
+ }
else
+ {
rt_kprintf(" ");
+ }
+ }
+
rt_kprintf(" ");
for (j = 0; j < 16; j++)
+ {
if (i + j < buflen)
+ {
rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
+ }
+ }
+
rt_kprintf("\n");
}
}
#endif
-extern void phy_reset(void);
-/* EMAC initialization function */
-static rt_err_t rt_stm32_eth_init(rt_device_t dev)
+rt_weak void phy_reset(void)
{
- __HAL_RCC_ETH_CLK_ENABLE();
+}
+
+static void phy_hardware_reset(void)
+{
+#ifdef ETH_RESET_PIN
+ if (reset_pin >= 0)
+ {
+ rt_pin_write(reset_pin, PIN_LOW);
+ rt_thread_mdelay(50);
+ rt_pin_write(reset_pin, PIN_HIGH);
+ return;
+ }
+#endif
phy_reset();
+}
- /* ETHERNET Configuration */
- EthHandle.Instance = ETH;
- EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
- EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
- EthHandle.Init.Speed = ETH_SPEED_100M;
- EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
- EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
- EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
-#ifdef RT_LWIP_USING_HW_CHECKSUM
- EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+static rt_uint8_t *eth_rx_buffer_at(rt_uint32_t index)
+{
+ return Rx_Buff + (index * ETH_MAX_PACKET_SIZE);
+}
+
+void HAL_ETH_RxAllocateCallback(uint8_t **buff)
+{
+ rt_uint32_t index;
+
+ *buff = RT_NULL;
+
+ for (index = 0; index < ETH_RX_BUFFER_CNT; index++)
+ {
+ rt_uint32_t current = (rx_alloc_index + index) % ETH_RX_BUFFER_CNT;
+
+ if (Rx_Buff_Info[current].allocated == RT_FALSE)
+ {
+ Rx_Buff_Info[current].allocated = RT_TRUE;
+ Rx_Buff_Info[current].length = 0;
+ Rx_Buff_Info[current].next = RT_NULL;
+ rx_alloc_index = (current + 1U) % ETH_RX_BUFFER_CNT;
+ *buff = eth_rx_buffer_at(current);
+ break;
+ }
+ }
+}
+
+void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t length)
+{
+ struct rt_stm32_eth_rx_buffer *rx_buffer = RT_NULL;
+ rt_uint32_t index;
+
+ for (index = 0; index < ETH_RX_BUFFER_CNT; index++)
+ {
+ if (buff == eth_rx_buffer_at(index))
+ {
+ rx_buffer = &Rx_Buff_Info[index];
+ break;
+ }
+ }
+
+ if (rx_buffer == RT_NULL)
+ {
+ return;
+ }
+
+ rx_buffer->length = length;
+ rx_buffer->next = RT_NULL;
+
+ if (*pStart == RT_NULL)
+ {
+ *pStart = rx_buffer;
+ }
+ else
+ {
+ ((struct rt_stm32_eth_rx_buffer *)(*pEnd))->next = rx_buffer;
+ }
+
+ *pEnd = rx_buffer;
+}
+
+static void eth_rx_release_buffers(struct rt_stm32_eth_rx_buffer *rx_buffer)
+{
+ while (rx_buffer != RT_NULL)
+ {
+ struct rt_stm32_eth_rx_buffer *next = rx_buffer->next;
+
+ rx_buffer->length = 0;
+ rx_buffer->next = RT_NULL;
+ rx_buffer->allocated = RT_FALSE;
+ rx_buffer = next;
+ }
+}
+
+static rt_err_t eth_rx_copy(struct pbuf *p, struct rt_stm32_eth_rx_buffer *rx_buffer)
+{
+ struct pbuf *q = p;
+ rt_size_t q_offset = 0;
+
+ while (rx_buffer != RT_NULL)
+ {
+ rt_uint32_t index = (rt_uint32_t)(rx_buffer - Rx_Buff_Info);
+ rt_size_t rx_offset = 0;
+
+ while (rx_offset < rx_buffer->length)
+ {
+ rt_size_t copy_length;
+ rt_size_t rx_remaining;
+ rt_size_t q_remaining;
+
+ while ((q != RT_NULL) && (q_offset == q->len))
+ {
+ q = q->next;
+ q_offset = 0;
+ }
+
+ if (q == RT_NULL)
+ {
+ return -RT_ERROR;
+ }
+
+ rx_remaining = (rt_size_t)rx_buffer->length - rx_offset;
+ q_remaining = (rt_size_t)q->len - q_offset;
+ copy_length = rx_remaining < q_remaining ? rx_remaining : q_remaining;
+ rt_memcpy((rt_uint8_t *)q->payload + q_offset,
+ eth_rx_buffer_at(index) + rx_offset, copy_length);
+ rx_offset += copy_length;
+ q_offset += copy_length;
+ }
+
+ rx_buffer = rx_buffer->next;
+ }
+
+ return RT_EOK;
+}
+
+static void eth_clean_cache(const void *buffer, rt_size_t length)
+{
+#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ rt_uintptr_t start;
+ rt_uintptr_t end;
+
+ if ((SCB->CCR & SCB_CCR_DC_Msk) == 0U)
+ {
+ return;
+ }
+
+ start = RT_ALIGN_DOWN((rt_uintptr_t)buffer, ETH_CACHE_LINE_SIZE);
+ end = RT_ALIGN((rt_uintptr_t)buffer + length, ETH_CACHE_LINE_SIZE);
+ SCB_CleanDCache_by_Addr((uint32_t *)start, (int32_t)(end - start));
#else
- EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
+ RT_UNUSED(buffer);
+ RT_UNUSED(length);
#endif
+}
- HAL_ETH_DeInit(&EthHandle);
+static void eth_invalidate_cache(const void *buffer, rt_size_t length)
+{
+#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ rt_uintptr_t start;
+ rt_uintptr_t end;
- /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
- if (HAL_ETH_Init(&EthHandle) != HAL_OK)
+ if ((SCB->CCR & SCB_CCR_DC_Msk) == 0U)
{
- LOG_E("eth hardware init failed");
+ return;
}
- else
+
+ start = RT_ALIGN_DOWN((rt_uintptr_t)buffer, ETH_CACHE_LINE_SIZE);
+ end = RT_ALIGN((rt_uintptr_t)buffer + length, ETH_CACHE_LINE_SIZE);
+ SCB_InvalidateDCache_by_Addr((uint32_t *)start, (int32_t)(end - start));
+#else
+ RT_UNUSED(buffer);
+ RT_UNUSED(length);
+#endif
+}
+
+static rt_err_t phy_find(void)
+{
+ uint32_t address;
+
+ for (address = 0; address <= 0x1FU; address++)
+ {
+ uint32_t id = 0xFFFFU;
+
+ if (HAL_ETH_ReadPHYRegister(&EthHandle, address, PHY_ID1_REG, &id) != HAL_OK)
+ {
+ continue;
+ }
+
+#ifdef PHY_USING_YT8512C
+ if (id != 0xFFFFU)
+#else
+ if ((id != 0xFFFFU) && (id != 0x0000U))
+#endif
+ {
+ phy_addr = (rt_uint8_t)address;
+ LOG_D("Found a phy, address:0x%02X", phy_addr);
+ return RT_EOK;
+ }
+ }
+
+ LOG_E("No PHY device was detected, please check hardware!");
+ return -RT_ERROR;
+}
+
+static rt_err_t phy_start_auto_negotiation(void)
+{
+ uint32_t control;
+ uint32_t timeout;
+
+ if (HAL_ETH_WritePHYRegister(&EthHandle, phy_addr, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK) != HAL_OK)
{
- LOG_D("eth hardware init success");
+ return -RT_ERROR;
}
- /* Initialize Tx Descriptors list: Chain Mode */
- HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, Tx_Buff, ETH_TXBUFNB);
+ for (timeout = 0; timeout < 500U; timeout++)
+ {
+ if (HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, PHY_BASIC_CONTROL_REG, &control) != HAL_OK)
+ {
+ return -RT_ERROR;
+ }
- /* Initialize Rx Descriptors list: Chain Mode */
- HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, Rx_Buff, ETH_RXBUFNB);
+ if ((control & PHY_RESET_MASK) == 0U)
+ {
+ break;
+ }
- /* ETH interrupt Init */
- HAL_NVIC_SetPriority(ETH_IRQn, 0x07, 0);
- HAL_NVIC_EnableIRQ(ETH_IRQn);
+ rt_thread_mdelay(1);
+ }
- /* Enable MAC and DMA transmission and reception */
- if (HAL_ETH_Start(&EthHandle) == HAL_OK)
+ if (timeout == 500U)
{
- LOG_D("emac hardware start");
+ return -RT_ETIMEOUT;
}
- else
+
+ control |= PHY_AUTO_NEGOTIATION_MASK;
+ if (HAL_ETH_WritePHYRegister(&EthHandle, phy_addr, PHY_BASIC_CONTROL_REG, control) != HAL_OK)
{
- LOG_E("emac hardware start faild");
return -RT_ERROR;
}
+ rt_thread_mdelay(2000);
+ return RT_EOK;
+}
+
+/* EMAC initialization function */
+static rt_err_t rt_stm32_eth_init(rt_device_t dev)
+{
+ rt_err_t status;
+
+ RT_UNUSED(dev);
+
+#ifdef BSP_USING_ETH_H750
+ __HAL_RCC_D2SRAM3_CLK_ENABLE();
+#endif
+
+ phy_hardware_reset();
+
+ EthHandle.Instance = ETH;
+ EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
+ EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
+ EthHandle.Init.TxDesc = DMATxDscrTab;
+ EthHandle.Init.RxDesc = DMARxDscrTab;
+ EthHandle.Init.RxBuffLen = ETH_MAX_PACKET_SIZE;
+
+ HAL_ETH_DeInit(&EthHandle);
+ rt_memset(Rx_Buff_Info, 0, sizeof(Rx_Buff_Info));
+ rx_alloc_index = 0;
+ phy_addr = PHY_INVALID_ADDR;
+ stm32_eth_device.phy_state = PHY_STATE_UNKNOWN;
+ stm32_eth_device.mac_started = RT_FALSE;
+
+ if (HAL_ETH_Init(&EthHandle) != HAL_OK)
+ {
+ LOG_E("eth hardware init failed");
+ return -RT_ERROR;
+ }
+
+ rt_memset(&TxConfig, 0, sizeof(TxConfig));
+ TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD;
+ TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
+#ifdef RT_LWIP_USING_HW_CHECKSUM
+ TxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM;
+ TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
+#else
+ TxConfig.ChecksumCtrl = ETH_CHECKSUM_DISABLE;
+#endif
+
+ HAL_ETH_SetMDIOClockRange(&EthHandle);
+
+ status = phy_find();
+ if (status != RT_EOK)
+ {
+ return status;
+ }
+
+ status = phy_start_auto_negotiation();
+ if (status != RT_EOK)
+ {
+ LOG_E("PHY auto negotiation failed: %d", status);
+ return status;
+ }
+
+ HAL_NVIC_EnableIRQ(ETH_IRQn);
+
+ LOG_D("eth hardware init success");
return RT_EOK;
}
static rt_err_t rt_stm32_eth_open(rt_device_t dev, rt_uint16_t oflag)
{
+ RT_UNUSED(dev);
+ RT_UNUSED(oflag);
LOG_D("emac open");
return RT_EOK;
}
static rt_err_t rt_stm32_eth_close(rt_device_t dev)
{
+ RT_UNUSED(dev);
LOG_D("emac close");
return RT_EOK;
}
static rt_ssize_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
- LOG_D("emac read");
+ RT_UNUSED(dev);
+ RT_UNUSED(pos);
+ RT_UNUSED(buffer);
+ RT_UNUSED(size);
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_ssize_t rt_stm32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
- LOG_D("emac write");
+ RT_UNUSED(dev);
+ RT_UNUSED(pos);
+ RT_UNUSED(buffer);
+ RT_UNUSED(size);
rt_set_errno(-RT_ENOSYS);
return 0;
}
static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
{
+ RT_UNUSED(dev);
+
switch (cmd)
{
case NIOCTL_GADDR:
- /* get mac address */
- if (args)
+ if (args != RT_NULL)
{
- SMEMCPY(args, stm32_eth_device.dev_addr, 6);
+ rt_memcpy(args, stm32_eth_device.dev_addr, MAX_ADDR_LEN);
}
else
{
@@ -182,7 +511,7 @@ static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
}
break;
- default :
+ default:
break;
}
@@ -190,210 +519,147 @@ static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
}
/* ethernet device interface */
-/* transmit data*/
+/* transmit data */
rt_err_t rt_stm32_eth_tx(rt_device_t dev, struct pbuf *p)
{
- rt_err_t ret = -RT_ERROR;
HAL_StatusTypeDef state;
+ ETH_BufferTypeDef tx_buffer[ETH_TX_DESC_CNT];
struct pbuf *q;
- uint8_t *buffer = (uint8_t *)(EthHandle.TxDesc->Buffer1Addr);
- __IO ETH_DMADescTypeDef *DmaTxDesc;
- uint32_t framelength = 0;
- uint32_t bufferoffset = 0;
- uint32_t byteslefttocopy = 0;
- uint32_t payloadoffset = 0;
+ rt_uint32_t index = 0;
+ rt_uint32_t frame_length = 0;
- DmaTxDesc = EthHandle.TxDesc;
- bufferoffset = 0;
+ RT_UNUSED(dev);
- /* copy frame from pbufs to driver buffers */
- for (q = p; q != NULL; q = q->next)
+ if (!stm32_eth_device.parent.link_status)
{
- /* Is this buffer available? If not, goto error */
- if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
- {
- LOG_D("buffer not valid");
- ret = ERR_USE;
- goto error;
- }
+ LOG_D("skip transmit: link down");
+ return ERR_IF;
+ }
- /* Get bytes in current lwIP buffer */
- byteslefttocopy = q->len;
- payloadoffset = 0;
+ rt_memset(tx_buffer, 0, sizeof(tx_buffer));
- /* Check if the length of data to copy is bigger than Tx buffer size*/
- while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE)
+ for (q = p; q != RT_NULL; q = q->next)
+ {
+ if (index >= ETH_TX_DESC_CNT)
{
- /* Copy data to Tx buffer*/
- SMEMCPY((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
-
- /* Point to next descriptor */
- DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
-
- /* Check if the buffer is available */
- if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
- {
- LOG_E("dma tx desc buffer is not valid");
- ret = ERR_USE;
- goto error;
- }
+ return ERR_IF;
+ }
- buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
+ tx_buffer[index].buffer = q->payload;
+ tx_buffer[index].len = q->len;
+ frame_length += q->len;
- byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
- payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
- framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
- bufferoffset = 0;
+ if (index > 0U)
+ {
+ tx_buffer[index - 1U].next = &tx_buffer[index];
}
- /* Copy the remaining bytes */
- SMEMCPY((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy);
- bufferoffset = bufferoffset + byteslefttocopy;
- framelength = framelength + byteslefttocopy;
+ eth_clean_cache(q->payload, q->len);
+ index++;
}
#ifdef ETH_TX_DUMP
- dump_hex(buffer, p->tot_len);
+ for (q = p; q != RT_NULL; q = q->next)
+ {
+ dump_hex(q->payload, q->len);
+ }
#endif
- /* Prepare transmit descriptors to give to DMA */
- /* TODO Optimize data send speed*/
- LOG_D("transmit frame length :%d", framelength);
-
- /* wait for unlocked */
- while (EthHandle.Lock == HAL_LOCKED);
-
- state = HAL_ETH_TransmitFrame(&EthHandle, framelength);
- if (state != HAL_OK)
+ if (rt_mutex_take(&stm32_eth_device.mac_lock, RT_WAITING_FOREVER) != RT_EOK)
{
- LOG_E("eth transmit frame faild: %d", state);
+ return ERR_IF;
}
- ret = ERR_OK;
+ if (!stm32_eth_device.parent.link_status || !stm32_eth_device.mac_started)
+ {
+ rt_mutex_release(&stm32_eth_device.mac_lock);
+ return ERR_IF;
+ }
-error:
+ TxConfig.Length = frame_length;
+ TxConfig.TxBuffer = tx_buffer;
+ state = HAL_ETH_Transmit(&EthHandle, &TxConfig, 1000);
+ rt_mutex_release(&stm32_eth_device.mac_lock);
- /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
- if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET)
+ if (state != HAL_OK)
{
- /* Clear TUS ETHERNET DMA flag */
- EthHandle.Instance->DMASR = ETH_DMASR_TUS;
-
- /* Resume DMA transmission*/
- EthHandle.Instance->DMATPDR = 0;
+ LOG_W("eth transmit frame failed: 0x%08X", EthHandle.ErrorCode);
+ return ERR_IF;
}
- return ret;
+ return ERR_OK;
}
-/* receive data*/
+/* receive data */
struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
{
-
- struct pbuf *p = NULL;
- struct pbuf *q = NULL;
HAL_StatusTypeDef state;
- uint16_t len = 0;
- uint8_t *buffer;
- __IO ETH_DMADescTypeDef *dmarxdesc;
- uint32_t bufferoffset = 0;
- uint32_t payloadoffset = 0;
- uint32_t byteslefttocopy = 0;
- uint32_t i = 0;
+ rt_uint32_t frame_length = 0;
+ struct pbuf *p = RT_NULL;
+ struct rt_stm32_eth_rx_buffer *rx_buffer = RT_NULL;
+ struct rt_stm32_eth_rx_buffer *current;
- /* Get received frame */
- state = HAL_ETH_GetReceivedFrame_IT(&EthHandle);
- if (state != HAL_OK)
+ RT_UNUSED(dev);
+
+ if (rt_mutex_take(&stm32_eth_device.mac_lock, RT_WAITING_FOREVER) != RT_EOK)
{
- LOG_D("receive frame faild");
- return NULL;
+ return RT_NULL;
}
- /* Obtain the size of the packet and put it into the "len" variable. */
- len = EthHandle.RxFrameInfos.length;
- buffer = (uint8_t *)EthHandle.RxFrameInfos.buffer;
-
- LOG_D("receive frame len : %d", len);
-
- if (len > 0)
+ if (!stm32_eth_device.mac_started)
{
- /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
- p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ rt_mutex_release(&stm32_eth_device.mac_lock);
+ return RT_NULL;
}
-#ifdef ETH_RX_DUMP
- dump_hex(buffer, p->tot_len);
-#endif
+ state = HAL_ETH_ReadData(&EthHandle, (void **)&rx_buffer);
+ rt_mutex_release(&stm32_eth_device.mac_lock);
- if (p != NULL)
+ if (state != HAL_OK)
{
- dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
- bufferoffset = 0;
- for (q = p; q != NULL; q = q->next)
- {
- byteslefttocopy = q->len;
- payloadoffset = 0;
-
- /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
- while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE)
- {
- /* Copy data to pbuf */
- SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
+ return RT_NULL;
+ }
- /* Point to next descriptor */
- dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
- buffer = (uint8_t *)(dmarxdesc->Buffer1Addr);
+ for (current = rx_buffer; current != RT_NULL; current = current->next)
+ {
+ rt_uint32_t index = (rt_uint32_t)(current - Rx_Buff_Info);
- byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
- payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
- bufferoffset = 0;
- }
- /* Copy remaining data in pbuf */
- SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy);
- bufferoffset = bufferoffset + byteslefttocopy;
- }
+ frame_length += current->length;
+ eth_invalidate_cache(eth_rx_buffer_at(index), current->length);
}
- /* Release descriptors to DMA */
- /* Point to first descriptor */
- dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
- /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
- for (i = 0; i < EthHandle.RxFrameInfos.SegCount; i++)
+#ifdef ETH_RX_DUMP
+ for (current = rx_buffer; current != RT_NULL; current = current->next)
{
- dmarxdesc->Status |= ETH_DMARXDESC_OWN;
- dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
+ rt_uint32_t index = (rt_uint32_t)(current - Rx_Buff_Info);
+ dump_hex(eth_rx_buffer_at(index), current->length);
}
+#endif
- /* Clear Segment_Count */
- EthHandle.RxFrameInfos.SegCount = 0;
-
- /* When Rx Buffer unavailable flag is set: clear it and resume reception */
- if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET)
+ p = pbuf_alloc(PBUF_RAW, frame_length, PBUF_RAM);
+ if ((p != RT_NULL) && (eth_rx_copy(p, rx_buffer) != RT_EOK))
{
- /* Clear RBUS ETHERNET DMA flag */
- EthHandle.Instance->DMASR = ETH_DMASR_RBUS;
- /* Resume DMA reception */
- EthHandle.Instance->DMARPDR = 0;
+ pbuf_free(p);
+ p = RT_NULL;
}
+ eth_rx_release_buffers(rx_buffer);
return p;
}
/* interrupt service routine */
void ETH_IRQHandler(void)
{
- /* enter interrupt */
rt_interrupt_enter();
-
HAL_ETH_IRQHandler(&EthHandle);
-
- /* leave interrupt */
rt_interrupt_leave();
}
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
rt_err_t result;
+
+ RT_UNUSED(heth);
result = eth_device_ready(&(stm32_eth_device.parent));
if (result != RT_EOK)
{
@@ -403,267 +669,369 @@ void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
{
- LOG_E("eth err");
+ uint32_t error = HAL_ETH_GetError(heth);
+ uint32_t dma_error = HAL_ETH_GetDMAError(heth);
+ uint32_t mac_error = HAL_ETH_GetMACError(heth);
+
+ if ((dma_error & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG) != 0U)
+ {
+ /* HAL_ETH_ReadData() replenishes the descriptors and resumes Rx DMA. */
+ (void)eth_device_ready(&(stm32_eth_device.parent));
+ dma_error &= ~(ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG | ETH_DMA_ABNORMAL_SUMMARY_FLAG);
+ }
+
+ dma_error &= ~ETH_DMA_EARLY_TX_IT_FLAG;
+#if defined(ETH_DMACSR_ETI)
+ /* H7 reports ETI separately from the generic early transmit flag. */
+ dma_error &= ~ETH_DMACSR_ETI;
+#endif
+
+ if ((dma_error != 0U) || ((error & HAL_ETH_ERROR_MAC) != 0U))
+ {
+ LOG_E("eth error: code=0x%08X dma=0x%08X mac=0x%08X",
+ error, dma_error, mac_error);
+ }
}
-static void phy_linkchange()
+enum
{
- static rt_uint8_t phy_speed = 0;
- rt_uint8_t phy_speed_new = 0;
- rt_uint32_t status;
+ PHY_LINK = (1 << 0),
+ PHY_100M = (1 << 1),
+ PHY_FULL_DUPLEX = (1 << 2),
+};
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status);
- LOG_D("phy basic status reg is 0x%X", status);
+static rt_err_t eth_mac_stop(void)
+{
+ rt_err_t result = RT_EOK;
- if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
+ if (rt_mutex_take(&stm32_eth_device.mac_lock, RT_WAITING_FOREVER) != RT_EOK)
{
- rt_uint32_t SR = 0;
+ return -RT_ERROR;
+ }
- phy_speed_new |= PHY_LINK;
+ if (stm32_eth_device.mac_started)
+ {
+ if (HAL_ETH_Stop_IT(&EthHandle) == HAL_OK)
+ {
+ stm32_eth_device.mac_started = RT_FALSE;
+ }
+ else
+ {
+ result = -RT_ERROR;
+ }
+ }
+
+ rt_mutex_release(&stm32_eth_device.mac_lock);
+ return result;
+}
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_Status_REG, (uint32_t *)&SR);
- LOG_D("phy control status reg is 0x%X", SR);
+static rt_err_t eth_mac_configure_and_start(rt_uint32_t speed, rt_uint32_t duplex)
+{
+ ETH_MACConfigTypeDef mac_config;
+ rt_err_t result = -RT_ERROR;
+
+ if (rt_mutex_take(&stm32_eth_device.mac_lock, RT_WAITING_FOREVER) != RT_EOK)
+ {
+ return -RT_ERROR;
+ }
- if (PHY_Status_SPEED_100M(SR))
+ if (stm32_eth_device.mac_started)
+ {
+ if (HAL_ETH_Stop_IT(&EthHandle) != HAL_OK)
{
- phy_speed_new |= PHY_100M;
+ goto __exit;
}
+ stm32_eth_device.mac_started = RT_FALSE;
+ }
- if (PHY_Status_FULL_DUPLEX(SR))
+ if (HAL_ETH_GetMACConfig(&EthHandle, &mac_config) != HAL_OK)
+ {
+ goto __exit;
+ }
+
+ mac_config.Speed = speed;
+ mac_config.DuplexMode = duplex;
+ if (HAL_ETH_SetMACConfig(&EthHandle, &mac_config) != HAL_OK)
+ {
+ goto __exit;
+ }
+
+ if (HAL_ETH_Start_IT(&EthHandle) != HAL_OK)
+ {
+ goto __exit;
+ }
+
+ stm32_eth_device.mac_started = RT_TRUE;
+ result = RT_EOK;
+
+__exit:
+ rt_mutex_release(&stm32_eth_device.mac_lock);
+ return result;
+}
+
+static void phy_linkchange(void)
+{
+ rt_uint8_t phy_state_new = 0;
+ uint32_t status = 0;
+
+ if (phy_addr == PHY_INVALID_ADDR)
+ {
+ return;
+ }
+
+ /* Read twice because the link bit in BMSR can be latched low. */
+ (void)HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, PHY_BASIC_STATUS_REG, &status);
+ if (HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, PHY_BASIC_STATUS_REG, &status) != HAL_OK)
+ {
+ return;
+ }
+
+ LOG_D("phy basic status reg is 0x%X", status);
+ if ((status & PHY_LINKED_STATUS_MASK) != 0U)
+ {
+ uint32_t phy_status = 0;
+
+ if ((status & PHY_AUTONEGO_COMPLETE_MASK) == 0U)
{
- phy_speed_new |= PHY_FULL_DUPLEX;
+ return;
}
+
+ if (HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, PHY_Status_REG, &phy_status) != HAL_OK)
+ {
+ return;
+ }
+
+ LOG_D("phy control status reg is 0x%X", phy_status);
+ phy_state_new |= PHY_LINK;
+ if (PHY_Status_SPEED_100M(phy_status))
+ {
+ phy_state_new |= PHY_100M;
+ }
+
+ if (PHY_Status_FULL_DUPLEX(phy_status))
+ {
+ phy_state_new |= PHY_FULL_DUPLEX;
+ }
+ }
+
+ if (stm32_eth_device.phy_state == phy_state_new)
+ {
+ return;
}
- if (phy_speed != phy_speed_new)
+ if ((phy_state_new & PHY_LINK) != 0U)
{
- phy_speed = phy_speed_new;
- if (phy_speed & PHY_LINK)
+ rt_uint32_t speed;
+ rt_uint32_t duplex;
+
+ if ((phy_state_new & PHY_100M) != 0U)
{
- LOG_D("link up");
- if (phy_speed & PHY_100M)
- {
- LOG_D("100Mbps");
- stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
- }
- else
- {
- stm32_eth_device.ETH_Speed = ETH_SPEED_10M;
- LOG_D("10Mbps");
- }
+ speed = ETH_SPEED_100M;
+ }
+ else
+ {
+ speed = ETH_SPEED_10M;
+ }
- if (phy_speed & PHY_FULL_DUPLEX)
- {
- LOG_D("full-duplex");
- stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
- }
- else
+ if ((phy_state_new & PHY_FULL_DUPLEX) != 0U)
+ {
+ duplex = ETH_FULLDUPLEX_MODE;
+ }
+ else
+ {
+ duplex = ETH_HALFDUPLEX_MODE;
+ }
+
+ if (eth_mac_configure_and_start(speed, duplex) != RT_EOK)
+ {
+ stm32_eth_device.phy_state = PHY_STATE_UNKNOWN;
+ if (stm32_eth_device.parent.link_status)
{
- LOG_D("half-duplex");
- stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
+ eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
}
+ LOG_E("configure and start MAC failed");
+ return;
+ }
+
+ stm32_eth_device.ETH_Speed = speed;
+ stm32_eth_device.ETH_Mode = duplex;
+ stm32_eth_device.phy_state = phy_state_new;
+ LOG_I("link up, %sMbps, %s-duplex",
+ speed == ETH_SPEED_100M ? "100" : "10",
+ duplex == ETH_FULLDUPLEX_MODE ? "full" : "half");
- /* send link up. */
+ if (!stm32_eth_device.parent.link_status)
+ {
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
}
- else
+ }
+ else
+ {
+ if (stm32_eth_device.parent.link_status)
{
- LOG_I("link down");
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
}
+
+ if (eth_mac_stop() != RT_EOK)
+ {
+ stm32_eth_device.phy_state = PHY_STATE_UNKNOWN;
+ LOG_E("stop MAC failed");
+ return;
+ }
+
+ stm32_eth_device.phy_state = phy_state_new;
+ LOG_I("link down");
}
}
#ifdef PHY_USING_INTERRUPT_MODE
static void eth_phy_isr(void *args)
{
- rt_uint32_t status = 0;
-
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_INTERRUPT_FLAG_REG, (uint32_t *)&status);
- LOG_D("phy interrupt status reg is 0x%X", status);
-
- phy_linkchange();
+ RT_UNUSED(args);
+ rt_sem_release(&phy_link_sem);
}
#endif /* PHY_USING_INTERRUPT_MODE */
static void phy_monitor_thread_entry(void *parameter)
{
- uint8_t phy_addr = 0xFF;
- uint8_t detected_count = 0;
-
- while(phy_addr == 0xFF)
- {
- /* phy search */
- rt_uint32_t i, temp;
- for (i = 0; i <= 0x1F; i++)
- {
- EthHandle.Init.PhyAddress = i;
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ID1_REG, (uint32_t *)&temp);
+ RT_UNUSED(parameter);
-#ifdef PHY_USING_YT8512C
- if (temp != 0xFFFF)
-#else
- if (temp != 0xFFFF && temp != 0x00)
-#endif /* PHY_USING_YT8512C */
- {
- phy_addr = i;
- break;
- }
- }
-
- detected_count++;
- rt_thread_mdelay(1000);
+#ifdef PHY_USING_INTERRUPT_MODE
+ uint32_t status = 0;
- if (detected_count > 10)
- {
- LOG_E("No PHY device was detected, please check hardware!");
- }
+ if (rt_sem_init(&phy_link_sem, "phyirq", 0, RT_IPC_FLAG_FIFO) != RT_EOK)
+ {
+ LOG_E("initialize PHY interrupt semaphore failed");
+ return;
}
- LOG_D("Found a phy, address:0x%02X", phy_addr);
-
- /* RESET PHY */
- LOG_D("RESET PHY!");
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
- rt_thread_mdelay(2000);
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);
-
- phy_linkchange();
-#ifdef PHY_USING_INTERRUPT_MODE
- /* configuration intterrupt pin */
rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
- rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
- rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);
+ rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, RT_NULL);
- /* enable phy interrupt */
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
+ (void)HAL_ETH_WritePHYRegister(&EthHandle, phy_addr, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
#if defined(PHY_INTERRUPT_CTRL_REG)
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
+ (void)HAL_ETH_WritePHYRegister(&EthHandle, phy_addr, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
#endif
-#else /* PHY_USING_INTERRUPT_MODE */
- stm32_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange,
- NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
- if (!stm32_eth_device.poll_link_timer || rt_timer_start(stm32_eth_device.poll_link_timer) != RT_EOK)
+ (void)HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, PHY_INTERRUPT_FLAG_REG, &status);
+ rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);
+
+ phy_linkchange();
+ while (1)
{
- LOG_E("Start link change detection timer failed");
+ if (rt_sem_take(&phy_link_sem, RT_WAITING_FOREVER) == RT_EOK)
+ {
+ (void)HAL_ETH_ReadPHYRegister(&EthHandle, phy_addr, PHY_INTERRUPT_FLAG_REG, &status);
+ LOG_D("phy interrupt status reg is 0x%X", status);
+ phy_linkchange();
+ }
+ }
+#else
+ while (1)
+ {
+ phy_linkchange();
+ rt_thread_mdelay(1000);
}
#endif /* PHY_USING_INTERRUPT_MODE */
}
-/* Register the EMAC device */
-static int rt_hw_stm32_eth_init(void)
+static rt_err_t eth_allocate_dma_memory(void)
{
- rt_err_t state = RT_EOK;
+#ifdef BSP_USING_ETH_H750
+ DMARxDscrTab = DMARxDscrTab_Storage;
+ DMATxDscrTab = DMATxDscrTab_Storage;
+ Rx_Buff = Rx_Buff_Storage;
+#else
+ DMARxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_RX_DESC_CNT, sizeof(ETH_DMADescTypeDef));
+ DMATxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_TX_DESC_CNT, sizeof(ETH_DMADescTypeDef));
+ Rx_Buff = (rt_uint8_t *)rt_calloc(ETH_RX_BUFFER_CNT, ETH_MAX_PACKET_SIZE);
- /* Prepare receive and send buffers */
- Rx_Buff = (rt_uint8_t *)rt_calloc(ETH_RXBUFNB, ETH_MAX_PACKET_SIZE);
- if (Rx_Buff == RT_NULL)
+ if ((DMARxDscrTab == RT_NULL) || (DMATxDscrTab == RT_NULL) || (Rx_Buff == RT_NULL))
{
- LOG_E("No memory");
- state = -RT_ENOMEM;
- goto __exit;
+ rt_free(DMARxDscrTab);
+ rt_free(DMATxDscrTab);
+ rt_free(Rx_Buff);
+ DMARxDscrTab = RT_NULL;
+ DMATxDscrTab = RT_NULL;
+ Rx_Buff = RT_NULL;
+ return -RT_ENOMEM;
}
+#endif
- Tx_Buff = (rt_uint8_t *)rt_calloc(ETH_TXBUFNB, ETH_MAX_PACKET_SIZE);
- if (Tx_Buff == RT_NULL)
+ return RT_EOK;
+}
+
+/* Register the EMAC device */
+static int rt_hw_stm32_eth_init(void)
+{
+ rt_err_t state;
+ rt_thread_t tid;
+
+#ifdef ETH_RESET_PIN
+ reset_pin = rt_pin_get(ETH_RESET_PIN);
+ if (reset_pin < 0)
{
- LOG_E("No memory");
- state = -RT_ENOMEM;
- goto __exit;
+ LOG_E("invalid ETH reset pin: %s", ETH_RESET_PIN);
+ return -RT_ERROR;
}
+ rt_pin_mode(reset_pin, PIN_MODE_OUTPUT);
+ rt_pin_write(reset_pin, PIN_HIGH);
+#endif
- DMARxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_RXBUFNB, sizeof(ETH_DMADescTypeDef));
- if (DMARxDscrTab == RT_NULL)
+ state = eth_allocate_dma_memory();
+ if (state != RT_EOK)
{
- LOG_E("No memory");
- state = -RT_ENOMEM;
- goto __exit;
+ LOG_E("No memory for ETH DMA");
+ return state;
}
- DMATxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_TXBUFNB, sizeof(ETH_DMADescTypeDef));
- if (DMATxDscrTab == RT_NULL)
+ state = rt_mutex_init(&stm32_eth_device.mac_lock, "ethmac", RT_IPC_FLAG_PRIO);
+ if (state != RT_EOK)
{
- LOG_E("No memory");
- state = -RT_ENOMEM;
- goto __exit;
+ LOG_E("initialize MAC mutex failed: %d", state);
+ return state;
}
stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
- stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
+ stm32_eth_device.ETH_Mode = ETH_FULLDUPLEX_MODE;
/* OUI 00-80-E1 STMICROELECTRONICS. */
stm32_eth_device.dev_addr[0] = 0x00;
stm32_eth_device.dev_addr[1] = 0x80;
stm32_eth_device.dev_addr[2] = 0xE1;
- /* generate MAC addr from 96bit unique ID (only for test). */
+ /* Generate MAC addr from 96-bit unique ID (only for test). */
stm32_eth_device.dev_addr[3] = *(rt_uint8_t *)(UID_BASE + 4);
stm32_eth_device.dev_addr[4] = *(rt_uint8_t *)(UID_BASE + 2);
stm32_eth_device.dev_addr[5] = *(rt_uint8_t *)(UID_BASE + 0);
- stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
- stm32_eth_device.parent.parent.open = rt_stm32_eth_open;
- stm32_eth_device.parent.parent.close = rt_stm32_eth_close;
- stm32_eth_device.parent.parent.read = rt_stm32_eth_read;
- stm32_eth_device.parent.parent.write = rt_stm32_eth_write;
- stm32_eth_device.parent.parent.control = rt_stm32_eth_control;
- stm32_eth_device.parent.parent.user_data = RT_NULL;
-
- stm32_eth_device.parent.eth_rx = rt_stm32_eth_rx;
- stm32_eth_device.parent.eth_tx = rt_stm32_eth_tx;
+ stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
+ stm32_eth_device.parent.parent.open = rt_stm32_eth_open;
+ stm32_eth_device.parent.parent.close = rt_stm32_eth_close;
+ stm32_eth_device.parent.parent.read = rt_stm32_eth_read;
+ stm32_eth_device.parent.parent.write = rt_stm32_eth_write;
+ stm32_eth_device.parent.parent.control = rt_stm32_eth_control;
+ stm32_eth_device.parent.parent.user_data = RT_NULL;
+ stm32_eth_device.parent.eth_rx = rt_stm32_eth_rx;
+ stm32_eth_device.parent.eth_tx = rt_stm32_eth_tx;
- /* register eth device */
state = eth_device_init(&(stm32_eth_device.parent), "e0");
- if (RT_EOK == state)
- {
- LOG_D("emac device init success");
- }
- else
+ if (state != RT_EOK)
{
- LOG_E("emac device init faild: %d", state);
- state = -RT_ERROR;
- goto __exit;
+ LOG_E("emac device init failed: %d", state);
+ return -RT_ERROR;
}
- /* start phy monitor */
- rt_thread_t tid;
tid = rt_thread_create("phy",
phy_monitor_thread_entry,
RT_NULL,
1024,
RT_THREAD_PRIORITY_MAX - 2,
2);
- if (tid != RT_NULL)
- {
- rt_thread_startup(tid);
- }
- else
- {
- state = -RT_ERROR;
- }
-__exit:
- if (state != RT_EOK)
+ if (tid == RT_NULL)
{
- if (Rx_Buff)
- {
- rt_free(Rx_Buff);
- }
-
- if (Tx_Buff)
- {
- rt_free(Tx_Buff);
- }
-
- if (DMARxDscrTab)
- {
- rt_free(DMARxDscrTab);
- }
-
- if (DMATxDscrTab)
- {
- rt_free(DMATxDscrTab);
- }
+ return -RT_ERROR;
}
- return state;
+ rt_thread_startup(tid);
+ return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_stm32_eth_init);
diff --git a/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h b/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h
index 2f72974d35..89ac508226 100644
--- a/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h
+++ b/bsp/stm32/stm32f407-atk-explorer/board/CubeMX_Config/Inc/stm32f4xx_hal_conf.h
@@ -45,8 +45,8 @@
#define HAL_DAC_MODULE_ENABLED
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
-/* #define HAL_ETH_MODULE_ENABLED */
-#define HAL_ETH_LEGACY_MODULE_ENABLED
+#define HAL_ETH_MODULE_ENABLED
+/* #define HAL_ETH_LEGACY_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_PCCARD_MODULE_ENABLED */
diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig
index f34bdeca0f..ddbb2fcfdc 100644
--- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig
+++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig
@@ -108,10 +108,6 @@ menu "Onboard Peripheral Drivers"
select BSP_USING_SOFT_I2C1
default n
- config BSP_ETH_LEGACY_MODULE_ENABLED
- bool
- default n
-
config BSP_USING_ETH
bool "Enable Ethernet"
default n
@@ -119,8 +115,6 @@ menu "Onboard Peripheral Drivers"
select RT_LWIP_USING_HW_CHECKSUM
select RT_USING_POSIX_FS
select RT_USING_POSIX_SOCKET
- select BSP_ETH_LEGACY_MODULE_ENABLED
-
config PHY_USING_LAN8720A
bool
depends on BSP_USING_ETH
diff --git a/bsp/stm32/stm32h750-artpi/board/CubeMX_Config/Core/Inc/stm32h7xx_hal_conf.h b/bsp/stm32/stm32h750-artpi/board/CubeMX_Config/Core/Inc/stm32h7xx_hal_conf.h
index ef887ffb98..8b5e53e80f 100644
--- a/bsp/stm32/stm32h750-artpi/board/CubeMX_Config/Core/Inc/stm32h7xx_hal_conf.h
+++ b/bsp/stm32/stm32h750-artpi/board/CubeMX_Config/Core/Inc/stm32h7xx_hal_conf.h
@@ -45,8 +45,8 @@
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
-/* #define HAL_ETH_MODULE_ENABLED */
-#define HAL_ETH_LEGACY_MODULE_ENABLED
+#define HAL_ETH_MODULE_ENABLED
+/* #define HAL_ETH_LEGACY_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_OTFDEC_MODULE_ENABLED */
diff --git a/bsp/stm32/stm32h750-artpi/board/Kconfig b/bsp/stm32/stm32h750-artpi/board/Kconfig
index 390c745ab3..0d658fbf7a 100644
--- a/bsp/stm32/stm32h750-artpi/board/Kconfig
+++ b/bsp/stm32/stm32h750-artpi/board/Kconfig
@@ -1,8 +1,8 @@
menu "Hardware Drivers Config"
config SOC_STM32H750_ARTPI
- bool
+ bool
default y
-
+
menu "Board extended module"
menuconfig ART_PI_USING_MEDIA_IO
@@ -61,6 +61,7 @@ menu "Board extended module"
config INDUSTRY_IO_USING_ETH
select BSP_USING_ETH
select PHY_USING_LAN8720A
+ select BSP_USING_ETH_H750
bool "Enable Ethernet"
default y
endif
diff --git a/bsp/stm32/stm32h750-artpi/board/port/SConscript b/bsp/stm32/stm32h750-artpi/board/port/SConscript
index f3c6bc9a54..b25f3e8218 100644
--- a/bsp/stm32/stm32h750-artpi/board/port/SConscript
+++ b/bsp/stm32/stm32h750-artpi/board/port/SConscript
@@ -30,9 +30,6 @@ if GetDepend(['BSP_USING_WIFI']):
src += Glob('wifi_config.c')
src += Glob('drv_wlan.c')
-if GetDepend(['BSP_USING_ETH_H750']):
- src += Glob('drv_eth.c')
-
if GetDepend(['PKG_USING_EASYFLASH']):
src += Glob('ef_fal_port.c')
diff --git a/bsp/stm32/stm32h750-artpi/board/port/drv_eth.c b/bsp/stm32/stm32h750-artpi/board/port/drv_eth.c
deleted file mode 100644
index 2b09a65cfd..0000000000
--- a/bsp/stm32/stm32h750-artpi/board/port/drv_eth.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Copyright (c) 2006-2025 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2018-11-19 SummerGift first version
- * 2018-12-25 zylx fix some bugs
- * 2019-06-10 SummerGift optimize PHY state detection process
- * 2019-09-03 xiaofan optimize link change detection process
- * 2020-07-17 wanghaijing support h7
- * 2020-11-30 wanghaijing add phy reset
- */
-
-#include<rtthread.h>
-#include<rtdevice.h>
-#include "board.h"
-#include "drv_config.h"
-
-#ifdef BSP_USING_ETH_H750
-
-#include <netif/ethernetif.h>
-#include "lwipopts.h"
-#include "drv_eth.h"
-
-/*
-* Emac driver uses CubeMX tool to generate emac and phy's configuration,
-* the configuration files can be found in CubeMX_Config folder.
-*/
-
-/* debug option */
-#define LOG_TAG "drv.emac"
-#include <drv_log.h>
-
-#define MAX_ADDR_LEN 6
-
-struct rt_stm32_eth
-{
- /* inherit from ethernet device */
- struct eth_device parent;
- #ifndef PHY_USING_INTERRUPT_MODE
- rt_timer_t poll_link_timer;
- #endif
-
- /* interface address info, hw address */
- rt_uint8_t dev_addr[MAX_ADDR_LEN];
- /* ETH_Speed */
- uint32_t ETH_Speed;
- /* ETH_Duplex_Mode */
- uint32_t ETH_Mode;
-};
-
-static ETH_HandleTypeDef EthHandle;
-static ETH_TxPacketConfig TxConfig;
-static struct rt_stm32_eth stm32_eth_device;
-static uint8_t PHY_ADDR = 0x1F;
-static rt_uint32_t reset_pin = 0;
-
-#if defined ( __ICCARM__ ) /*!< IAR Compiler */
- #pragma location=0x30040000
- ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
- #pragma location=0x30040060
- ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
- #pragma location=0x30040200
- uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffers */
-
-#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
- __attribute__((at(0x30040000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
- __attribute__((at(0x30040060))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
- __attribute__((at(0x30040200))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffer */
-
-#elif defined ( __GNUC__ ) /* GNU Compiler */
- ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
- ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */
- uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
-#endif
-
-#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
-#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
-static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
-{
- unsigned char *buf = (unsigned char *)ptr;
- int i, j;
-
- for (i = 0; i < buflen; i += 16)
- {
- rt_kprintf("%08X: ", i);
-
- for (j = 0; j < 16; j++)
- if (i + j < buflen)
- rt_kprintf("%02X ", buf[i + j]);
- else
- rt_kprintf(" ");
-
- rt_kprintf(" ");
-
- for (j = 0; j < 16; j++)
- if (i + j < buflen)
- rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
-
- rt_kprintf("\n");
- }
-}
-#endif
-
-static void phy_reset(void)
-{
- rt_pin_write(reset_pin, PIN_LOW);
- rt_thread_mdelay(50);
- rt_pin_write(reset_pin, PIN_HIGH);
-}
-
-
-/* EMAC initialization function */
-static rt_err_t rt_stm32_eth_init(rt_device_t dev)
-{
- ETH_MACConfigTypeDef MACConf;
- uint32_t regvalue = 0;
- rt_err_t status = RT_EOK;
-
- __HAL_RCC_D2SRAM3_CLK_ENABLE();
-
- phy_reset();
-
- /* ETHERNET Configuration */
- EthHandle.Instance = ETH;
- EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
- EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
- EthHandle.Init.TxDesc = DMATxDscrTab;
- EthHandle.Init.RxDesc = DMARxDscrTab;
- EthHandle.Init.RxBuffLen = ETH_MAX_PACKET_SIZE;
-
- SCB_InvalidateDCache();
-
- HAL_ETH_DeInit(&EthHandle);
-
- /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
- if (HAL_ETH_Init(&EthHandle) != HAL_OK)
- {
- LOG_E("eth hardware init failed");
- }
- else
- {
- LOG_D("eth hardware init success");
- }
-
- rt_memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig));
- TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
- TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
- TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
-
- for (int idx = 0; idx < ETH_RX_DESC_CNT; idx++)
- {
- HAL_ETH_DescAssignMemory(&EthHandle, idx, &Rx_Buff[idx][0], NULL);
- }
-
- HAL_ETH_SetMDIOClockRange(&EthHandle);
-
- for(int i = 0; i <= PHY_ADDR; i ++)
- {
- if(HAL_ETH_ReadPHYRegister(&EthHandle, i, PHY_SPECIAL_MODES_REG, &regvalue) != HAL_OK)
- {
- status = -RT_ERROR;
- /* Can't read from this device address continue with next address */
- continue;
- }
-
- if((regvalue & PHY_BASIC_STATUS_REG) == i)
- {
- PHY_ADDR = i;
- status = RT_EOK;
- LOG_D("Found a phy, address:0x%02X", PHY_ADDR);
- break;
- }
- }
-
- if(HAL_ETH_WritePHYRegister(&EthHandle, PHY_ADDR, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK) == HAL_OK)
- {
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDR, PHY_SPECIAL_MODES_REG, &regvalue);
-
- uint32_t tickstart = rt_tick_get();
-
- /* wait until software reset is done or timeout occured */
- while(regvalue & PHY_RESET_MASK)
- {
- if((rt_tick_get() - tickstart) <= 500)
- {
- if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDR, PHY_BASIC_CONTROL_REG, &regvalue) != HAL_OK)
- {
- status = -RT_ERROR;
- break;
- }
- }
- else
- {
- status = -RT_ETIMEOUT;
- }
- }
- }
-
- rt_thread_delay(2000);
-
- if(HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDR, PHY_BASIC_CONTROL_REG, &regvalue) == HAL_OK)
- {
- regvalue |= PHY_AUTO_NEGOTIATION_MASK;
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_ADDR, PHY_BASIC_CONTROL_REG, regvalue);
-
- eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
- HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
- MACConf.DuplexMode = ETH_FULLDUPLEX_MODE;
- MACConf.Speed = ETH_SPEED_100M;
- HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
-
- HAL_ETH_Start_IT(&EthHandle);
- }
- else
- {
- status = -RT_ERROR;
- }
-
- return status;
-}
-
-static rt_err_t rt_stm32_eth_open(rt_device_t dev, rt_uint16_t oflag)
-{
- LOG_D("emac open");
- return RT_EOK;
-}
-
-static rt_err_t rt_stm32_eth_close(rt_device_t dev)
-{
- LOG_D("emac close");
- return RT_EOK;
-}
-
-static rt_ssize_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
-{
- LOG_D("emac read");
- rt_set_errno(-RT_ENOSYS);
- return 0;
-}
-
-static rt_ssize_t rt_stm32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
-{
- LOG_D("emac write");
- rt_set_errno(-RT_ENOSYS);
- return 0;
-}
-
-static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
-{
- switch (cmd)
- {
- case NIOCTL_GADDR:
-
- /* get mac address */
- if (args) rt_memcpy(args, stm32_eth_device.dev_addr, 6);
- else return -RT_ERROR;
-
- break;
-
- default :
- break;
- }
-
- return RT_EOK;
-}
-
-/* ethernet device interface */
-/* transmit data*/
-rt_err_t rt_stm32_eth_tx(rt_device_t dev, struct pbuf *p)
-{
- rt_err_t ret = -RT_ERROR;
- HAL_StatusTypeDef state;
- uint32_t i = 0, framelen = 0;
- struct pbuf *q;
- ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
-
- rt_memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));
-
- for (q = p; q != NULL; q = q->next)
- {
- if (i >= ETH_TX_DESC_CNT)
- return ERR_IF;
-
- Txbuffer[i].buffer = q->payload;
- Txbuffer[i].len = q->len;
- framelen += q->len;
-
- if (i > 0)
- {
- Txbuffer[i - 1].next = &Txbuffer[i];
- }
-
- if (q->next == NULL)
- {
- Txbuffer[i].next = NULL;
- }
-
- i++;
- }
-
- TxConfig.Length = framelen;
- TxConfig.TxBuffer = Txbuffer;
-
- #ifdef ETH_TX_DUMP
- rt_kprintf("Tx dump, len= %d\r\n", framelen);
- dump_hex(&Txbuffer[0]);
- #endif
-
- if (stm32_eth_device.parent.link_status)
- {
- SCB_CleanInvalidateDCache();
- state = HAL_ETH_Transmit(&EthHandle, &TxConfig, 1000);
-
- if (state != HAL_OK)
- {
- LOG_W("eth transmit frame faild: %d", EthHandle.ErrorCode);
- EthHandle.ErrorCode = HAL_ETH_STATE_READY;
- EthHandle.gState = HAL_ETH_STATE_READY;
- }
- }
- else
- {
- LOG_E("eth transmit frame faild, netif not up");
- }
-
- ret = ERR_OK;
-
- return ret;
-}
-
-/* receive data*/
-struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
-{
- uint32_t framelength = 0;
- rt_uint16_t l;
- struct pbuf *p = RT_NULL, *q;
- ETH_BufferTypeDef RxBuff;
- uint32_t alignedAddr;
-
- if(HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff) == HAL_OK)
- {
- HAL_ETH_GetRxDataLength(&EthHandle, &framelength);
-
- /* Build Rx descriptor to be ready for next data reception */
- HAL_ETH_BuildRxDescriptors(&EthHandle);
-
- /* Invalidate data cache for ETH Rx Buffers */
- alignedAddr = (uint32_t)RxBuff.buffer & ~0x1F;
- SCB_InvalidateDCache_by_Addr((uint32_t *)alignedAddr, (uint32_t)RxBuff.buffer - alignedAddr + framelength);
-
- p = pbuf_alloc(PBUF_RAW, framelength, PBUF_RAM);
-
- if (p != NULL)
- {
- for (q = p, l = 0; q != NULL; q = q->next)
- {
- rt_memcpy((rt_uint8_t *)q->payload, (rt_uint8_t *)&RxBuff.buffer[l], q->len);
- l = l + q->len;
- }
- }
- }
-
- return p;
-}
-
-/* interrupt service routine */
-void ETH_IRQHandler(void)
-{
- /* enter interrupt */
- rt_interrupt_enter();
-
- HAL_ETH_IRQHandler(&EthHandle);
-
- /* leave interrupt */
- rt_interrupt_leave();
-}
-
-void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
-{
- rt_err_t result;
- result = eth_device_ready(&(stm32_eth_device.parent));
-
- if (result != RT_EOK)
- LOG_I("RxCpltCallback err = %d", result);
-}
-
-void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
-{
- LOG_E("eth err");
-}
-
-enum
-{
- PHY_LINK = (1 << 0),
- PHY_100M = (1 << 1),
- PHY_FULL_DUPLEX = (1 << 2),
-};
-
-static void phy_linkchange()
-{
- static rt_uint8_t phy_speed = 0;
- rt_uint8_t phy_speed_new = 0;
- rt_uint32_t status;
-
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDR, PHY_BASIC_STATUS_REG, (uint32_t *)&status);
- LOG_D("phy basic status reg is 0x%X", status);
-
- if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
- {
- rt_uint32_t SR = 0;
-
- phy_speed_new |= PHY_LINK;
-
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDR, PHY_Status_REG, (uint32_t *)&SR);
- LOG_D("phy control status reg is 0x%X", SR);
-
- if (PHY_Status_SPEED_100M(SR))
- {
- phy_speed_new |= PHY_100M;
- }
-
- if (PHY_Status_FULL_DUPLEX(SR))
- {
- phy_speed_new |= PHY_FULL_DUPLEX;
- }
- }
-
- if (phy_speed != phy_speed_new)
- {
- phy_speed = phy_speed_new;
-
- if (phy_speed & PHY_LINK)
- {
- LOG_D("link up");
-
- if (phy_speed & PHY_100M)
- {
- LOG_D("100Mbps");
- stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
- }
- else
- {
- stm32_eth_device.ETH_Speed = ETH_SPEED_10M;
- LOG_D("10Mbps");
- }
-
- if (phy_speed & PHY_FULL_DUPLEX)
- {
- LOG_D("full-duplex");
- stm32_eth_device.ETH_Mode = ETH_FULLDUPLEX_MODE;
- }
- else
- {
- LOG_D("half-duplex");
- stm32_eth_device.ETH_Mode = ETH_HALFDUPLEX_MODE;
- }
-
- /* send link up. */
- eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
- }
- else
- {
- LOG_I("link down");
- eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
- }
- }
-}
-
-#ifdef PHY_USING_INTERRUPT_MODE
-static void eth_phy_isr(void *args)
-{
- rt_uint32_t status = 0;
-
- HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ADDR, PHY_INTERRUPT_FLAG_REG, (uint32_t *)&status);
- LOG_D("phy interrupt status reg is 0x%X", status);
-
- phy_linkchange();
-}
-#endif /* PHY_USING_INTERRUPT_MODE */
-
-static void phy_monitor_thread_entry(void *parameter)
-{
- phy_linkchange();
- #ifdef PHY_USING_INTERRUPT_MODE
- /* configuration intterrupt pin */
- rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
- rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
- rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);
-
- /* enable phy interrupt */
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_ADDR, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
- #if defined(PHY_INTERRUPT_CTRL_REG)
- HAL_ETH_WritePHYRegister(&EthHandle, PHY_ADDR, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
- #endif
- #else /* PHY_USING_INTERRUPT_MODE */
- stm32_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange,
- NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
-
- if (!stm32_eth_device.poll_link_timer || rt_timer_start(stm32_eth_device.poll_link_timer) != RT_EOK)
- {
- LOG_E("Start link change detection timer failed");
- }
-
- #endif /* PHY_USING_INTERRUPT_MODE */
-}
-
-/* Register the EMAC device */
-static int rt_hw_stm32_eth_init(void)
-{
- rt_err_t state = RT_EOK;
- reset_pin = rt_pin_get(ETH_RESET_PIN);
-
- rt_pin_mode(reset_pin, PIN_MODE_OUTPUT);
- rt_pin_write(reset_pin, PIN_HIGH);
-
- stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
- stm32_eth_device.ETH_Mode = ETH_FULLDUPLEX_MODE;
-
- /* OUI 00-80-E1 STMICROELECTRONICS. */
- stm32_eth_device.dev_addr[0] = 0x00;
- stm32_eth_device.dev_addr[1] = 0x80;
- stm32_eth_device.dev_addr[2] = 0xE1;
- /* generate MAC addr from 96bit unique ID (only for test). */
- stm32_eth_device.dev_addr[3] = *(rt_uint8_t *)(UID_BASE + 4);
- stm32_eth_device.dev_addr[4] = *(rt_uint8_t *)(UID_BASE + 2);
- stm32_eth_device.dev_addr[5] = *(rt_uint8_t *)(UID_BASE + 0);
-
- stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
- stm32_eth_device.parent.parent.open = rt_stm32_eth_open;
- stm32_eth_device.parent.parent.close = rt_stm32_eth_close;
- stm32_eth_device.parent.parent.read = rt_stm32_eth_read;
- stm32_eth_device.parent.parent.write = rt_stm32_eth_write;
- stm32_eth_device.parent.parent.control = rt_stm32_eth_control;
- stm32_eth_device.parent.parent.user_data = RT_NULL;
-
- stm32_eth_device.parent.eth_rx = rt_stm32_eth_rx;
- stm32_eth_device.parent.eth_tx = rt_stm32_eth_tx;
-
- /* register eth device */
- state = eth_device_init(&(stm32_eth_device.parent), "e0");
-
- if (RT_EOK == state)
- {
- LOG_D("emac device init success");
- }
- else
- {
- LOG_E("emac device init faild: %d", state);
- state = -RT_ERROR;
- }
-
- /* start phy monitor */
- rt_thread_t tid;
- tid = rt_thread_create("phy",
- phy_monitor_thread_entry,
- RT_NULL,
- 1024,
- RT_THREAD_PRIORITY_MAX - 2,
- 2);
-
- if (tid != RT_NULL)
- {
- rt_thread_startup(tid);
- }
- else
- {
- state = -RT_ERROR;
- }
-
- return state;
-}
-INIT_DEVICE_EXPORT(rt_hw_stm32_eth_init);
-
-#endif /* BSP_USING_ETH_ARTPI */