/* * ethernetif.c - STM32F407VET6 平台的 LwIP 以太网接口实现 * * 连接 LwIP 与 STM32 HAL 以太网驱动 */ #include "lwip/opt.h" #include "lwip/def.h" #include "lwip/mem.h" #include "lwip/pbuf.h" #include "lwip/netif.h" #include "lwip/etharp.h" #include "lwip/prot/ethernet.h" #include "netif/ethernet.h" #include "bsp_eth.h" #include "stm32f4xx_hal.h" #include /* 以太网接口状态结构 */ struct ethernetif { struct eth_addr *ethaddr; /* 其他私有数据 */ }; /* 全局以太网接口结构 */ static struct netif gnetif; static struct ethernetif ethernetif; /* 以太网接收回调函数 */ static void ethernetif_input(void *arg) { struct netif *netif = (struct netif *)arg; struct pbuf *p = NULL; uint8_t buffer[1520]; uint16_t length; int ret; /* 从以太网驱动接收数据包 */ ret = hal_eth_receive(HAL_ETH_INSTANCE_1, buffer, &length); if (ret == HAL_RET_OK && length > 0) { /* 为接收到的数据分配 pbuf */ p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); if (p != NULL) { /* 复制数据到 pbuf */ memcpy(p->payload, buffer, length); /* 处理接收到的数据包 */ if (netif->input(p, netif) != ERR_OK) { pbuf_free(p); p = NULL; } } } } /* 以太网发送函数 */ static err_t ethernetif_output(struct netif *netif, struct pbuf *p) { struct pbuf *q; uint8_t buffer[1520]; uint16_t length = 0; int ret; /* 检查参数 */ if (netif == NULL || p == NULL) { return ERR_ARG; } /* 复制 pbuf 链中的数据到发送缓冲区 */ for (q = p; q != NULL; q = q->next) { if (length + q->len <= sizeof(buffer)) { memcpy(buffer + length, q->payload, q->len); length += q->len; } else { return ERR_MEM; } } /* 发送数据包 */ ret = hal_eth_transmit(HAL_ETH_INSTANCE_1, buffer, length); if (ret != HAL_RET_OK) { return ERR_IF; } return ERR_OK; } /* 以太网接口初始化函数 */ static err_t ethernetif_init(struct netif *netif) { struct ethernetif *ethernetif = netif->state; bsp_eth_config_t eth_config; hal_ret_t ret; LWIP_ASSERT("netif != NULL", (netif != NULL)); /* 设置网络接口参数 */ netif->name[0] = 'e'; netif->name[1] = 'n'; netif->output = etharp_output; netif->linkoutput = ethernetif_output; netif->state = ðernetif; netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; /* 设置 MAC 地址 */ hal_eth_mac_addr_t mac_addr; ret = bsp_eth_get_mac_addr(&mac_addr); if (ret == HAL_RET_OK) { netif->hwaddr[0] = mac_addr.byte[0]; netif->hwaddr[1] = mac_addr.byte[1]; netif->hwaddr[2] = mac_addr.byte[2]; netif->hwaddr[3] = mac_addr.byte[3]; netif->hwaddr[4] = mac_addr.byte[4]; netif->hwaddr[5] = mac_addr.byte[5]; netif->hwaddr_len = ETH_HWADDR_LEN; } /* 初始化以太网硬件 */ eth_config.enable = 1; eth_config.instance = HAL_ETH_INSTANCE_1; eth_config.mode = HAL_ETH_MODE_FULLDUPLEX; eth_config.speed = HAL_ETH_SPEED_100MBPS; eth_config.phy_addr = LAN8720_PHY_ADDRESS; eth_config.auto_negotiation = 1; eth_config.interrupt_enable = 1; ret = bsp_eth_init(ð_config); if (ret != HAL_RET_OK) { return ERR_IF; } LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: STM32F407VET6 Ethernet initialized\n")); return ERR_OK; } /* 初始化以太网接口 */ void ethernetif_create(void) { ip4_addr_t ipaddr, netmask, gw; /* 初始化 LwIP 核心 */ lwip_init(); /* 设置 IP 地址 */ IP4_ADDR(&ipaddr, 192, 168, 1, 100); IP4_ADDR(&netmask, 255, 255, 255, 0); IP4_ADDR(&gw, 192, 168, 1, 1); /* 添加网络接口 */ #if NO_SYS /* 无操作系统环境:使用以太网输入函数 */ netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input); #else /* 有操作系统环境:使用 TCP/IP 输入函数 */ netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input); #endif /* 设置默认网络接口 */ netif_set_default(&gnetif); /* 启用网络接口 */ netif_set_up(&gnetif); LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_create: Network interface created\n")); } /* 以太网中断处理函数 */ void ETH_IRQHandler(void) { /* 处理以太网中断 */ hal_eth_irq_handler(HAL_ETH_INSTANCE_1); /* 触发数据包处理 */ ethernetif_input(&gnetif); } /* 获取网络接口 */ struct netif *ethernetif_get_netif(void) { return &gnetif; } /* 网络接口状态检查 */ void ethernetif_check_link(void) { uint8_t link_up; hal_ret_t ret; ret = bsp_eth_check_link(&link_up); if (ret == HAL_RET_OK) { if (link_up && !(gnetif.flags & NETIF_FLAG_LINK_UP)) { /* 链接已建立 */ netif_set_link_up(&gnetif); LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_check_link: Link up\n")); } else if (!link_up && (gnetif.flags & NETIF_FLAG_LINK_UP)) { /* 链接已断开 */ netif_set_link_down(&gnetif); LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_check_link: Link down\n")); } } }