204 lines
5.3 KiB
C
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 = ð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"));
|
|
}
|
|
}
|
|
}
|