Files
stm32f407ve_black/ThirdParty/lwip-2.2.1/port/ethernetif.c
2026-01-29 17:26:04 +08:00

204 lines
5.3 KiB
C

/*
* 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 <string.h>
/* 以太网接口状态结构 */
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 = &ethernetif;
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(&eth_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"));
}
}
}