STM32H563 LWIP裸机移植 (包含源代码 一文搞定 )
本博客使用的是STM32H563型号MUC。该型号在CubeMX中目前还不支持直接生成LWIP协议(2024.7.20),所以,需要在官网找到LWIP中间件及驱动(LAN8720A)手动移植。
PHY芯片型号: LAN8720A
目录
STM32H563 移植LWIP
CubeMX ETH配置
下载LWIP移植文件
移植LWIP 源文件
移植头文件
移植完成后的问题:
STM32H563 移植LWIP
配置ETH外设(以太网(Ethernet)接口)
CubeMX创建STM32H563工程步骤省略......
CubeMX ETH配置
首先根据自己的需求配置:调试器接口以及时钟
使能ETH(选择的RMII模式)
配置ETH引脚复用
复位引脚设置(查看原理图 LAN8720ANRST引脚接了MCU哪个引脚):
根据自己需求配置时钟
生成项目
下载LWIP移植文件
打开网站 点击Download(下载)按钮
lwIP - A Lightweight TCP/IP stack - Summary [Savannah] (nongnu.org)
下载文件
将文件解压 移植之前先要了解文件中的内容
打开lwip文件
src源码文件
打开contrib文件
移植LWIP 源文件
现在开始移植
lwip文件
将lwip源码(src文件夹)添加到文件中
工程文件
添加工程分组
创建分组存放lwip源码
每个分组中都添加对应的源文件
对应源码 (src文件夹文件)添加到对应工程分组中
lwip/api文件
lwip/core文件
再点击ipv4文件夹 将文件夹下的所有文件添加
lwip/netif分组 (ppp文件夹内文件不需要添加)
注意:这里没有选中slipif.c文件
添加工程中所需要的头文件路径
移植头文件
我们的工程基本就添加完成了,但想要lwip跑起来,还需要一些头文件的支持(lwip的配置文件 )
在源文件(src)文件夹中 创建arch文件夹
打开contrib文件夹
将\contrib-2.1.0\examples\example_app路径下的lwipopts.h文件拷贝到.\src\arch文件夹中
再将.\contrib-2.1.0\ports\unix\port\include\arch路径下的cc.h及perf.h文件拷贝到.\src\arch文件夹下
.\src\arch文件夹下文件
再将.\src\arch文件夹下的所有文件添加到组
打开lwipopts.h 并在文件内 根据自己需求配置
下列源代码中没有配置的参数在opt.h中有默认配置 如需改变默认配置参数 在该文件中使用宏定义直接配置即可
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__/*** SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain* critical regions during buffer allocation, deallocation and memory* allocation and deallocation.*/
#define SYS_LIGHTWEIGHT_PROT 0/*** NO_SYS==1: Provides VERY minimal functionality. Otherwise,* use lwIP facilities.*/
#define NO_SYS 1/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for whichlwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 4/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE (14*1024)/* Relocate the LwIP RAM heap pointer */
#define LWIP_RAM_HEAP_POINTER (0x20084000)/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCPconnections. */
#define MEMP_NUM_TCP_PCB 10/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCPsegments. */
#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN/* ---------- Pbuf options ---------- *//* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool */
#define PBUF_POOL_BUFSIZE 1536/* LWIP_SUPPORT_CUSTOM_PBUF == 1: to pass directly MAC Rx buffers to the stack no copy is needed */
#define LWIP_SUPPORT_CUSTOM_PBUF 1/*---------------------------------------------------------- Network Interfaces options ----------------------------------------------------------
*/
#define LWIP_NETIF_LINK_CALLBACK 1/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255/* TCP Maximum segment size. */
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) *//* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (4*TCP_MSS)/* TCP receive window. */
#define TCP_WND (4*TCP_MSS)/* ---------- ICMP options ---------- */
#define LWIP_ICMP 1/* ---------- DHCP options ---------- */
#define LWIP_DHCP 0/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define UDP_TTL 255/* ---------- Statistics options ---------- */
#define LWIP_STATS 0/*------------------------------------------------ Checksum options ------------------------------------------------
*//*
The STM32H7xx allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:- To use this feature let the following define uncommented.- To disable it and process by CPU comment the the checksum.
*/
#define CHECKSUM_BY_HARDWARE #ifdef CHECKSUM_BY_HARDWARE/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/#define CHECKSUM_GEN_IP 0/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/#define CHECKSUM_GEN_UDP 0/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/#define CHECKSUM_GEN_TCP 0 /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/#define CHECKSUM_CHECK_IP 0/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/#define CHECKSUM_CHECK_UDP 0/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/#define CHECKSUM_CHECK_TCP 0/* CHECKSUM_GEN_ICMP==1: Check checksums by hardware for outgoing ICMP packets.*//* Hardware TCP/UDP checksum insertion not supported when packet is an IPv4 fragment*/#define CHECKSUM_GEN_ICMP 1/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/#define CHECKSUM_CHECK_ICMP 0
#else/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/#define CHECKSUM_GEN_IP 1/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/#define CHECKSUM_GEN_UDP 1/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/#define CHECKSUM_GEN_TCP 1/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/#define CHECKSUM_CHECK_IP 1/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/#define CHECKSUM_CHECK_UDP 1/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/#define CHECKSUM_CHECK_TCP 1/* CHECKSUM_GEN_ICMP==1: Check checksums by hardware for outgoing ICMP packets.*/#define CHECKSUM_GEN_ICMP 1/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/#define CHECKSUM_CHECK_ICMP 1
#endif/*-------------------------------------------------------- Sequential layer options --------------------------------------------------------
*/
/*** LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)*/
#define LWIP_NETCONN 0/*---------------------------------------------- Socket options ----------------------------------------------
*/
/*** LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)*/
#define LWIP_SOCKET 0#endif /* __LWIPOPTS_H__ */
NO_SYS 表示无操作系统模拟层,这个宏非常重要, 因为无操作系统与有操作系统的移植和编写是完全不一样的, 我们现在是无操作系统移植,所以将这个宏定义为1。
MEM_ALIGNMENT 内存对齐,按照4字节对齐。
MEM_SIZE 堆内存的大小。PBUF_POOL_BUFSIZE PBUF_POOL内存池中每个内存块大小。
TCP_MSS TCP协议报文最大长度。
TCP_WND TCP接收窗口大小。
LWIP_SOCKET 因为现在是无操作系统,就不使能NETCONN API和Socket API编程。
LWIP_NETCONN 因为现在是无操作系统,就不使能NETCONN API和Socket API编程。
cc.h文件
cc.h文件定义大小端模式,输出调试的宏等
注意:不是复制的 cc.h 51行需要注释掉
/** Copyright (c) 2001-2003 Swedish Institute of Computer Science.* All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met:** 1. Redistributions of source code must retain the above copyright notice,* this list of conditions and the following disclaimer.* 2. Redistributions in binary form must reproduce the above copyright notice,* this list of conditions and the following disclaimer in the documentation* and/or other materials provided with the distribution.* 3. The name of the author may not be used to endorse or promote products* derived from this software without specific prior written permission. ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE.** This file is part of the lwIP TCP/IP stack.* * Author: Adam Dunkels <adam@sics.se>**/
#ifndef LWIP_ARCH_CC_H
#define LWIP_ARCH_CC_H/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
#if defined __ANDROID__
#define LWIP_UNIX_ANDROID
#elif defined __linux__
#define LWIP_UNIX_LINUX
#elif defined __APPLE__
#define LWIP_UNIX_MACH
#elif defined __OpenBSD__
#define LWIP_UNIX_OPENBSD
#elif defined __CYGWIN__
#define LWIP_UNIX_CYGWIN
#elif defined __GNU__
#define LWIP_UNIX_HURD
#endif#define LWIP_TIMEVAL_PRIVATE 0
//#include <sys/time.h>#define LWIP_ERRNO_INCLUDE <errno.h>#if defined(LWIP_UNIX_LINUX) || defined(LWIP_UNIX_HURD)
#define LWIP_ERRNO_STDINCLUDE 1
#endif#define LWIP_RAND() ((u32_t)rand())/* different handling for unit test, normally not needed */
#ifdef LWIP_NOASSERT_ON_ERROR
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \handler;}} while(0)
#endif#if defined(LWIP_UNIX_ANDROID) && defined(FD_SET)
typedef __kernel_fd_set fd_set;
#endif#if defined(LWIP_UNIX_MACH)
/* sys/types.h and signal.h bring in Darwin byte order macros. pull theheader here and disable LwIP's version so that apps still can getthe macros via LwIP headers and use system headers */
#include <sys/types.h>
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#endifstruct sio_status_s;
typedef struct sio_status_s sio_status_t;
#define sio_fd_t sio_status_t*
#define __sio_fd_t_definedtypedef unsigned int sys_prot_t;#endif /* LWIP_ARCH_CC_H */
perf.h文件是与系统统计与测量相关的头文件,我们暂时无需使用任何统计与测量功能,因此该头文件的量宏定义直接为空即可
#ifndef __PERF_H__#define __PERF_H__#define PERF_START /* null definition */#define PERF_STOP(x) /* null definition */#endif /* __PERF_H__ */
再将以下文件按原步骤添加到lwip/arch中
ethernetif.c文件
底层驱动的函数,LwIP的contrib包中就包含这个文件的模板,我们直接拿过来修改即可。(该文件内容不可直接使用 直接使用建议复制下方源码)
也可直接复制以下源代码
/* Includes ------------------------------------------------------------------*/
#include "stm32h5xx_hal.h"
#include "lwip/opt.h"
#include "lwip/timeouts.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "lan8742.h"
#include <string.h>/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Network interface name */
#define IFNAME0 's'
#define IFNAME1 't'#define ETH_DMA_TRANSMIT_TIMEOUT (20U)#define ETH_RX_BUFFER_SIZE 1524U
#define ETH_RX_BUFFER_CNT 12U
#define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT) * 2U)/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
typedef enum
{
RX_ALLOC_OK = 0x00,
RX_ALLOC_ERROR = 0x01
} RxAllocStatusTypeDef;typedef struct
{
struct pbuf_custom pbuf_custom;
uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32);
} RxBuff_t;extern ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
extern ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
extern u8_t memp_memory_RX_POOL_base[];/* Variable Definitions */
LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");
static uint8_t RxAllocStatus;/* Global Ethernet handle*/
extern ETH_HandleTypeDef heth;
extern ETH_TxPacketConfig TxConfig;/* Private function prototypes -----------------------------------------------*/
u32_t sys_now(void);int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit (void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void);lan8742_Object_t LAN8742;
lan8742_IOCtx_t LAN8742_IOCtx = {ETH_PHY_IO_Init,ETH_PHY_IO_DeInit,ETH_PHY_IO_WriteReg,ETH_PHY_IO_ReadReg,ETH_PHY_IO_GetTick};/* Private functions ---------------------------------------------------------*/
void pbuf_free_custom(struct pbuf *p);
/*******************************************************************************LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/
/**
* @brief In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
HAL_ETH_Init(&heth);/* set MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;/* set MAC hardware address */
netif->hwaddr[0] = heth.Init.MACAddr[0];
netif->hwaddr[1] = heth.Init.MACAddr[1];
netif->hwaddr[2] = heth.Init.MACAddr[2];
netif->hwaddr[3] = heth.Init.MACAddr[3];
netif->hwaddr[4] = heth.Init.MACAddr[4];
netif->hwaddr[5] = heth.Init.MACAddr[5];/* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD;/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;/* Initialize the RX POOL */
LWIP_MEMPOOL_INIT(RX_POOL);
/* Set PHY IO functions */
LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);/* Initialize the LAN8742 ETH PHY */
LAN8742_Init(&LAN8742);ethernet_link_check_state(netif);
}/**
* @brief This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become available since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
uint32_t i = 0U;
struct pbuf *q = NULL;
err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};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;if(i>0){Txbuffer[i-1].next = &Txbuffer[i];}if(q->next == NULL){Txbuffer[i].next = NULL;}i++;
}TxConfig.Length = p->tot_len;
TxConfig.TxBuffer = Txbuffer;
TxConfig.pData = p;HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);return errval;
}/**
* @brief Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf * low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;if(RxAllocStatus == RX_ALLOC_OK)
{HAL_ETH_ReadData(&heth, (void **)&p);
}
return p;}/**
* @brief This function is the ethernetif_input task, it is processed when a packet
* is ready to be read from the interface. It uses the function low_level_input()
* that should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input(struct netif *netif)
{
struct pbuf *p = NULL;do{p = low_level_input( netif );if (p != NULL){if (netif->input( p, netif) != ERR_OK ){pbuf_free(p);}}} while(p!=NULL);}/**
* @brief Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.* You can instead declare your own function an call etharp_output()* from it if you have to do some checks before sending (e.g. if link* is available...) */
netif->output = etharp_output;
netif->linkoutput = low_level_output;/* initialize the hardware */
low_level_init(netif);return ERR_OK;
}/**
* @brief Custom Rx pbuf free callback
* @param pbuf: pbuf to be freed
* @retval None
*/
void pbuf_free_custom(struct pbuf *p)
{
struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p;
LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);/* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to* call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
if (RxAllocStatus == RX_ALLOC_ERROR)
{RxAllocStatus = RX_ALLOC_OK;
}
}/**
* @brief Returns the current time in milliseconds
* when LWIP_TIMERS == 1 and NO_SYS == 1
* @param None
* @retval Current Time value
*/
u32_t sys_now(void)
{
return HAL_GetTick();
}/*******************************************************************************PHI IO Functions
*******************************************************************************/
/**
* @brief Initializes the MDIO interface GPIO and clocks.
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_Init(void)
{
/* We assume that MDIO GPIO configuration is already donein the ETH_MspInit() else it should be done here
*//* Configure the MDIO Clock */
HAL_ETH_SetMDIOClockRange(&heth);return 0;
}/**
* @brief De-Initializes the MDIO interface .
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_DeInit (void)
{
return 0;
}/**
* @brief Read a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param pRegVal: pointer to hold the register value
* @retval 0 if OK -1 if Error
*/
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
{
if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK)
{return -1;
}return 0;
}/**
* @brief Write a value to a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param RegVal: Value to be written
* @retval 0 if OK -1 if Error
*/
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
{
if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK)
{return -1;
}return 0;
}/**
* @brief Get the time in millisecons used for internal PHY driver process.
* @retval Time value
*/
int32_t ETH_PHY_IO_GetTick(void)
{
return HAL_GetTick();
}/**
* @brief
* @retval None
*/
void ethernet_link_check_state(struct netif *netif)
{
ETH_MACConfigTypeDef MACConf = {0};
int32_t PHYLinkState = 0U;
uint32_t linkchanged = 0U, speed = 0U, duplex =0U;PHYLinkState = LAN8742_GetLinkState(&LAN8742);if(netif_is_link_up(netif) && (PHYLinkState <= LAN8742_STATUS_LINK_DOWN))
{HAL_ETH_Stop(&heth);netif_set_down(netif);netif_set_link_down(netif);
}
else if(!netif_is_link_up(netif) && (PHYLinkState > LAN8742_STATUS_LINK_DOWN))
{switch (PHYLinkState){case LAN8742_STATUS_100MBITS_FULLDUPLEX:duplex = ETH_FULLDUPLEX_MODE;speed = ETH_SPEED_100M;linkchanged = 1;break;case LAN8742_STATUS_100MBITS_HALFDUPLEX:duplex = ETH_HALFDUPLEX_MODE;speed = ETH_SPEED_100M;linkchanged = 1;break;case LAN8742_STATUS_10MBITS_FULLDUPLEX:duplex = ETH_FULLDUPLEX_MODE;speed = ETH_SPEED_10M;linkchanged = 1;break;case LAN8742_STATUS_10MBITS_HALFDUPLEX:duplex = ETH_HALFDUPLEX_MODE;speed = ETH_SPEED_10M;linkchanged = 1;break;default:break;}if(linkchanged){/* Get MAC Config MAC */HAL_ETH_GetMACConfig(&heth, &MACConf);MACConf.DuplexMode = duplex;MACConf.Speed = speed;HAL_ETH_SetMACConfig(&heth, &MACConf);//HAL_ETH_Start(&heth);HAL_ETH_Start_IT(&heth);netif_set_up(netif);netif_set_link_up(netif);}
}
}
void HAL_ETH_RxAllocateCallback(uint8_t **buff)
{
struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL);
if (p)
{/* Get the buff from the struct pbuf address. */*buff = (uint8_t *)p + offsetof(RxBuff_t, buff);p->custom_free_function = pbuf_free_custom;/* Initialize the struct pbuf.* This must be performed whenever a buffer's allocated because it may be* changed by lwIP or the app, e.g., pbuf_free decrements ref. */pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE);
}
else
{RxAllocStatus = RX_ALLOC_ERROR;*buff = NULL;
}
}void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
{
struct pbuf **ppStart = (struct pbuf **)pStart;
struct pbuf **ppEnd = (struct pbuf **)pEnd;
struct pbuf *p = NULL;/* Get the struct pbuf from the buff address. */
p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff));
p->next = NULL;
p->tot_len = 0;
p->len = Length;/* Chain the buffer. */
if (!*ppStart)
{/* The first buffer of the packet. */*ppStart = p;
}
else
{/* Chain the buffer to the end of the packet. */(*ppEnd)->next = p;
}
*ppEnd = p;/* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its tot_len* set to its own length, plus the length of all the following pbufs in the chain. */
for (p = *ppStart; p != NULL; p = p->next)
{p->tot_len += Length;
}/* Invalidate data cache because Rx DMA's writing to physical memory makes it stale. */
}void HAL_ETH_TxFreeCallback(uint32_t * buff)
{
pbuf_free((struct pbuf *)buff);
}
创建文件 并添加到工程分组中
ethernetif.h文件
#ifndef __ETHERNETIF_H__
#define __ETHERNETIF_H__#include "lwip/err.h"
#include "lwip/netif.h"#define ETH_RST_GPIO_Port GPIOC
#define ETH_RST_Pin GPIO_PIN_0/* Exported types ------------------------------------------------------------*/
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif);
void ethernet_link_check_state(struct netif *netif);
#endif
创建lan8742.c文件
#include "lan8742.h" /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines* @{*/
#define LAN8742_SW_RESET_TO ((uint32_t)500U)
#define LAN8742_INIT_TO ((uint32_t)2000U)
#define LAN8742_MAX_DEV_ADDR ((uint32_t)31U)
/*** @}*//* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup LAN8742_Private_Functions LAN8742 Private Functions* @{*//*** @brief Register IO functions to component object* @param pObj: device object of LAN8742_Object_t. * @param ioctx: holds device IO functions. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_ERROR if missing mandatory function*/
int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx)
{if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick){return LAN8742_STATUS_ERROR;}pObj->IO.Init = ioctx->Init;pObj->IO.DeInit = ioctx->DeInit;pObj->IO.ReadReg = ioctx->ReadReg;pObj->IO.WriteReg = ioctx->WriteReg;pObj->IO.GetTick = ioctx->GetTick;return LAN8742_STATUS_OK;
}/*** @brief Initialize the lan8742 and configure the needed hardware resources* @param pObj: device object LAN8742_Object_t. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_ADDRESS_ERROR if cannot find device address* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register* LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset*/int32_t LAN8742_Init(lan8742_Object_t *pObj){uint32_t tickstart = 0, regvalue = 0, addr = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->Is_Initialized == 0){if(pObj->IO.Init != 0){/* GPIO and Clocks initialization */pObj->IO.Init();}/* for later check */pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1;/* Get the device address from special mode register */ for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++){if(pObj->IO.ReadReg(addr, LAN8742_SMR, ®value) < 0){ status = LAN8742_STATUS_READ_ERROR;/* Can't read from this device address continue with next address */continue;}if((regvalue & LAN8742_SMR_PHY_ADDR) == addr){pObj->DevAddr = addr;status = LAN8742_STATUS_OK;break;}}if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR){status = LAN8742_STATUS_ADDRESS_ERROR;}/* if device address is matched */if(status == LAN8742_STATUS_OK){/* set a software reset */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0){ /* get software reset status */if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) >= 0){ tickstart = pObj->IO.GetTick();/* wait until software reset is done or timeout occured */while(regvalue & LAN8742_BCR_SOFT_RESET){if((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO){if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) < 0){ status = LAN8742_STATUS_READ_ERROR;break;}}else{status = LAN8742_STATUS_RESET_TIMEOUT;break;}} }else{status = LAN8742_STATUS_READ_ERROR;}}else{status = LAN8742_STATUS_WRITE_ERROR;}}}if(status == LAN8742_STATUS_OK){tickstart = pObj->IO.GetTick();/* Wait for 2s to perform initialization */while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO){}pObj->Is_Initialized = 1;}return status;}/*** @brief De-Initialize the lan8742 and it's hardware resources* @param pObj: device object LAN8742_Object_t. * @retval None*/
int32_t LAN8742_DeInit(lan8742_Object_t *pObj)
{if(pObj->Is_Initialized){if(pObj->IO.DeInit != 0){if(pObj->IO.DeInit() < 0){return LAN8742_STATUS_ERROR;}}pObj->Is_Initialized = 0;}return LAN8742_STATUS_OK;
}/*** @brief Disable the LAN8742 power down mode.* @param pObj: device object LAN8742_Object_t. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0){readval &= ~LAN8742_BCR_POWER_DOWN;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Enable the LAN8742 power down mode.* @param pObj: device object LAN8742_Object_t. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0){readval |= LAN8742_BCR_POWER_DOWN;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Start the auto negotiation process.* @param pObj: device object LAN8742_Object_t. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0){readval |= LAN8742_BCR_AUTONEGO_EN;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Get the link state of LAN8742 device.* @param pObj: Pointer to device object. * @param pLinkState: Pointer to link state* @retval LAN8742_STATUS_LINK_DOWN if link is down* LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed * LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD* LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD* LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD* LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD * LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj)
{uint32_t readval = 0;/* Read Status register */if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0){return LAN8742_STATUS_READ_ERROR;}/* Read Status register again */if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0){return LAN8742_STATUS_READ_ERROR;}if((readval & LAN8742_BSR_LINK_STATUS) == 0){/* Return Link Down status */return LAN8742_STATUS_LINK_DOWN; }/* Check Auto negotiaition */if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0){return LAN8742_STATUS_READ_ERROR;}if((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN){if(((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)) {return LAN8742_STATUS_100MBITS_FULLDUPLEX;}else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT){return LAN8742_STATUS_100MBITS_HALFDUPLEX;} else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE){return LAN8742_STATUS_10MBITS_FULLDUPLEX;}else{return LAN8742_STATUS_10MBITS_HALFDUPLEX;} }else /* Auto Nego enabled */{if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0){return LAN8742_STATUS_READ_ERROR;}/* Check if auto nego not done */if((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0){return LAN8742_STATUS_AUTONEGO_NOTDONE;}if((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD){return LAN8742_STATUS_100MBITS_FULLDUPLEX;}else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD){return LAN8742_STATUS_100MBITS_HALFDUPLEX;}else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD){return LAN8742_STATUS_10MBITS_FULLDUPLEX;}else{return LAN8742_STATUS_10MBITS_HALFDUPLEX;} }
}/*** @brief Set the link state of LAN8742 device.* @param pObj: Pointer to device object. * @param pLinkState: link state can be one of the following* LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD* LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD* LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD* LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_ERROR if parameter error * LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState)
{uint32_t bcrvalue = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &bcrvalue) >= 0){/* Disable link config (Auto nego, speed and duplex) */bcrvalue &= ~(LAN8742_BCR_AUTONEGO_EN | LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);if(LinkState == LAN8742_STATUS_100MBITS_FULLDUPLEX){bcrvalue |= (LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE);}else if (LinkState == LAN8742_STATUS_100MBITS_HALFDUPLEX){bcrvalue |= LAN8742_BCR_SPEED_SELECT;}else if (LinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX){bcrvalue |= LAN8742_BCR_DUPLEX_MODE;}else{/* Wrong link status parameter */status = LAN8742_STATUS_ERROR;} }else{status = LAN8742_STATUS_READ_ERROR;}if(status == LAN8742_STATUS_OK){/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, bcrvalue) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}return status;
}/*** @brief Enable loopback mode.* @param pObj: Pointer to device object. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0){readval |= LAN8742_BCR_LOOPBACK;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Disable loopback mode.* @param pObj: Pointer to device object. * @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0){readval &= ~LAN8742_BCR_LOOPBACK;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Enable IT source.* @param pObj: Pointer to device object. * @param Interrupt: IT source to be enabled* should be a value or a combination of the following:* LAN8742_WOL_IT * LAN8742_ENERGYON_IT * LAN8742_AUTONEGO_COMPLETE_IT * LAN8742_REMOTE_FAULT_IT * LAN8742_LINK_DOWN_IT * LAN8742_AUTONEGO_LP_ACK_IT * LAN8742_PARALLEL_DETECTION_FAULT_IT* LAN8742_AUTONEGO_PAGE_RECEIVED_IT* @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0){readval |= Interrupt;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Disable IT source.* @param pObj: Pointer to device object. * @param Interrupt: IT source to be disabled* should be a value or a combination of the following:* LAN8742_WOL_IT * LAN8742_ENERGYON_IT * LAN8742_AUTONEGO_COMPLETE_IT * LAN8742_REMOTE_FAULT_IT * LAN8742_LINK_DOWN_IT * LAN8742_AUTONEGO_LP_ACK_IT * LAN8742_PARALLEL_DETECTION_FAULT_IT* LAN8742_AUTONEGO_PAGE_RECEIVED_IT* @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register* LAN8742_STATUS_WRITE_ERROR if connot write to register*/
int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0){readval &= ~Interrupt;/* Apply configuration */if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0){status = LAN8742_STATUS_WRITE_ERROR;}}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Clear IT flag.* @param pObj: Pointer to device object. * @param Interrupt: IT flag to be cleared* should be a value or a combination of the following:* LAN8742_WOL_IT * LAN8742_ENERGYON_IT * LAN8742_AUTONEGO_COMPLETE_IT * LAN8742_REMOTE_FAULT_IT * LAN8742_LINK_DOWN_IT * LAN8742_AUTONEGO_LP_ACK_IT * LAN8742_PARALLEL_DETECTION_FAULT_IT* LAN8742_AUTONEGO_PAGE_RECEIVED_IT* @retval LAN8742_STATUS_OK if OK* LAN8742_STATUS_READ_ERROR if connot read register*/
int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt)
{uint32_t readval = 0;int32_t status = LAN8742_STATUS_OK; if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) < 0){status = LAN8742_STATUS_READ_ERROR;}return status;
}/*** @brief Get IT Flag status.* @param pObj: Pointer to device object. * @param Interrupt: IT Flag to be checked, * should be a value or a combination of the following:* LAN8742_WOL_IT * LAN8742_ENERGYON_IT * LAN8742_AUTONEGO_COMPLETE_IT * LAN8742_REMOTE_FAULT_IT * LAN8742_LINK_DOWN_IT * LAN8742_AUTONEGO_LP_ACK_IT * LAN8742_PARALLEL_DETECTION_FAULT_IT* LAN8742_AUTONEGO_PAGE_RECEIVED_IT * @retval 1 IT flag is SET* 0 IT flag is RESET* LAN8742_STATUS_READ_ERROR if connot read register*/
int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt)
{uint32_t readval = 0;int32_t status = 0;if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) >= 0){status = ((readval & Interrupt) == Interrupt);}else{status = LAN8742_STATUS_READ_ERROR;}return status;
}
创建lan8742.h文件
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LAN8742_H
#define LAN8742_H#ifdef __cplusplusextern "C" {
#endif /* Includes ------------------------------------------------------------------*/
#include <stdint.h>/** @addtogroup BSP* @{*/ /** @addtogroup Component* @{*//** @defgroup LAN8742* @{*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup LAN8742_Exported_Constants LAN8742 Exported Constants* @{*/ /** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping* @{*/
#define LAN8742_BCR ((uint16_t)0x0000U)
#define LAN8742_BSR ((uint16_t)0x0001U)
#define LAN8742_PHYI1R ((uint16_t)0x0002U)
#define LAN8742_PHYI2R ((uint16_t)0x0003U)
#define LAN8742_ANAR ((uint16_t)0x0004U)
#define LAN8742_ANLPAR ((uint16_t)0x0005U)
#define LAN8742_ANER ((uint16_t)0x0006U)
#define LAN8742_ANNPTR ((uint16_t)0x0007U)
#define LAN8742_ANNPRR ((uint16_t)0x0008U)
#define LAN8742_MMDACR ((uint16_t)0x000DU)
#define LAN8742_MMDAADR ((uint16_t)0x000EU)
#define LAN8742_ENCTR ((uint16_t)0x0010U)
#define LAN8742_MCSR ((uint16_t)0x0011U)
#define LAN8742_SMR ((uint16_t)0x0012U)
#define LAN8742_TPDCR ((uint16_t)0x0018U)
#define LAN8742_TCSR ((uint16_t)0x0019U)
#define LAN8742_SECR ((uint16_t)0x001AU)
#define LAN8742_SCSIR ((uint16_t)0x001BU)
#define LAN8742_CLR ((uint16_t)0x001CU)
#define LAN8742_ISFR ((uint16_t)0x001DU)
#define LAN8742_IMR ((uint16_t)0x001EU)
#define LAN8742_PHYSCSR ((uint16_t)0x001FU)
/*** @}*//** @defgroup LAN8742_BCR_Bit_Definition LAN8742 BCR Bit Definition* @{*/
#define LAN8742_BCR_SOFT_RESET ((uint16_t)0x8000U)
#define LAN8742_BCR_LOOPBACK ((uint16_t)0x4000U)
#define LAN8742_BCR_SPEED_SELECT ((uint16_t)0x2000U)
#define LAN8742_BCR_AUTONEGO_EN ((uint16_t)0x1000U)
#define LAN8742_BCR_POWER_DOWN ((uint16_t)0x0800U)
#define LAN8742_BCR_ISOLATE ((uint16_t)0x0400U)
#define LAN8742_BCR_RESTART_AUTONEGO ((uint16_t)0x0200U)
#define LAN8742_BCR_DUPLEX_MODE ((uint16_t)0x0100U)
/*** @}*//** @defgroup LAN8742_BSR_Bit_Definition LAN8742 BSR Bit Definition* @{*/
#define LAN8742_BSR_100BASE_T4 ((uint16_t)0x8000U)
#define LAN8742_BSR_100BASE_TX_FD ((uint16_t)0x4000U)
#define LAN8742_BSR_100BASE_TX_HD ((uint16_t)0x2000U)
#define LAN8742_BSR_10BASE_T_FD ((uint16_t)0x1000U)
#define LAN8742_BSR_10BASE_T_HD ((uint16_t)0x0800U)
#define LAN8742_BSR_100BASE_T2_FD ((uint16_t)0x0400U)
#define LAN8742_BSR_100BASE_T2_HD ((uint16_t)0x0200U)
#define LAN8742_BSR_EXTENDED_STATUS ((uint16_t)0x0100U)
#define LAN8742_BSR_AUTONEGO_CPLT ((uint16_t)0x0020U)
#define LAN8742_BSR_REMOTE_FAULT ((uint16_t)0x0010U)
#define LAN8742_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
#define LAN8742_BSR_LINK_STATUS ((uint16_t)0x0004U)
#define LAN8742_BSR_JABBER_DETECT ((uint16_t)0x0002U)
#define LAN8742_BSR_EXTENDED_CAP ((uint16_t)0x0001U)
/*** @}*//** @defgroup LAN8742_PHYI1R_Bit_Definition LAN8742 PHYI1R Bit Definition* @{*/
#define LAN8742_PHYI1R_OUI_3_18 ((uint16_t)0xFFFFU)
/*** @}*//** @defgroup LAN8742_PHYI2R_Bit_Definition LAN8742 PHYI2R Bit Definition* @{*/
#define LAN8742_PHYI2R_OUI_19_24 ((uint16_t)0xFC00U)
#define LAN8742_PHYI2R_MODEL_NBR ((uint16_t)0x03F0U)
#define LAN8742_PHYI2R_REVISION_NBR ((uint16_t)0x000FU)
/*** @}*//** @defgroup LAN8742_ANAR_Bit_Definition LAN8742 ANAR Bit Definition* @{*/
#define LAN8742_ANAR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8742_ANAR_REMOTE_FAULT ((uint16_t)0x2000U)
#define LAN8742_ANAR_PAUSE_OPERATION ((uint16_t)0x0C00U)
#define LAN8742_ANAR_PO_NOPAUSE ((uint16_t)0x0000U)
#define LAN8742_ANAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U)
#define LAN8742_ANAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U)
#define LAN8742_ANAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
#define LAN8742_ANAR_100BASE_TX_FD ((uint16_t)0x0100U)
#define LAN8742_ANAR_100BASE_TX ((uint16_t)0x0080U)
#define LAN8742_ANAR_10BASE_T_FD ((uint16_t)0x0040U)
#define LAN8742_ANAR_10BASE_T ((uint16_t)0x0020U)
#define LAN8742_ANAR_SELECTOR_FIELD ((uint16_t)0x000FU)
/*** @}*//** @defgroup LAN8742_ANLPAR_Bit_Definition LAN8742 ANLPAR Bit Definition* @{*/
#define LAN8742_ANLPAR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8742_ANLPAR_REMOTE_FAULT ((uint16_t)0x2000U)
#define LAN8742_ANLPAR_PAUSE_OPERATION ((uint16_t)0x0C00U)
#define LAN8742_ANLPAR_PO_NOPAUSE ((uint16_t)0x0000U)
#define LAN8742_ANLPAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U)
#define LAN8742_ANLPAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U)
#define LAN8742_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
#define LAN8742_ANLPAR_100BASE_TX_FD ((uint16_t)0x0100U)
#define LAN8742_ANLPAR_100BASE_TX ((uint16_t)0x0080U)
#define LAN8742_ANLPAR_10BASE_T_FD ((uint16_t)0x0040U)
#define LAN8742_ANLPAR_10BASE_T ((uint16_t)0x0020U)
#define LAN8742_ANLPAR_SELECTOR_FIELD ((uint16_t)0x000FU)
/*** @}*//** @defgroup LAN8742_ANER_Bit_Definition LAN8742 ANER Bit Definition* @{*/
#define LAN8742_ANER_RX_NP_LOCATION_ABLE ((uint16_t)0x0040U)
#define LAN8742_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
#define LAN8742_ANER_PARALLEL_DETECT_FAULT ((uint16_t)0x0010U)
#define LAN8742_ANER_LP_NP_ABLE ((uint16_t)0x0008U)
#define LAN8742_ANER_NP_ABLE ((uint16_t)0x0004U)
#define LAN8742_ANER_PAGE_RECEIVED ((uint16_t)0x0002U)
#define LAN8742_ANER_LP_AUTONEG_ABLE ((uint16_t)0x0001U)
/*** @}*//** @defgroup LAN8742_ANNPTR_Bit_Definition LAN8742 ANNPTR Bit Definition* @{*/
#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8742_ANNPTR_MESSAGE_PAGE ((uint16_t)0x2000U)
#define LAN8742_ANNPTR_ACK2 ((uint16_t)0x1000U)
#define LAN8742_ANNPTR_TOGGLE ((uint16_t)0x0800U)
#define LAN8742_ANNPTR_MESSAGGE_CODE ((uint16_t)0x07FFU)
/*** @}*//** @defgroup LAN8742_ANNPRR_Bit_Definition LAN8742 ANNPRR Bit Definition* @{*/
#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8742_ANNPRR_ACK ((uint16_t)0x4000U)
#define LAN8742_ANNPRR_MESSAGE_PAGE ((uint16_t)0x2000U)
#define LAN8742_ANNPRR_ACK2 ((uint16_t)0x1000U)
#define LAN8742_ANNPRR_TOGGLE ((uint16_t)0x0800U)
#define LAN8742_ANNPRR_MESSAGGE_CODE ((uint16_t)0x07FFU)
/*** @}*//** @defgroup LAN8742_MMDACR_Bit_Definition LAN8742 MMDACR Bit Definition* @{*/
#define LAN8742_MMDACR_MMD_FUNCTION ((uint16_t)0xC000U)
#define LAN8742_MMDACR_MMD_FUNCTION_ADDR ((uint16_t)0x0000U)
#define LAN8742_MMDACR_MMD_FUNCTION_DATA ((uint16_t)0x4000U)
#define LAN8742_MMDACR_MMD_DEV_ADDR ((uint16_t)0x001FU)
/*** @}*//** @defgroup LAN8742_ENCTR_Bit_Definition LAN8742 ENCTR Bit Definition* @{*/
#define LAN8742_ENCTR_TX_ENABLE ((uint16_t)0x8000U)
#define LAN8742_ENCTR_TX_TIMER ((uint16_t)0x6000U)
#define LAN8742_ENCTR_TX_TIMER_1S ((uint16_t)0x0000U)
#define LAN8742_ENCTR_TX_TIMER_768MS ((uint16_t)0x2000U)
#define LAN8742_ENCTR_TX_TIMER_512MS ((uint16_t)0x4000U)
#define LAN8742_ENCTR_TX_TIMER_265MS ((uint16_t)0x6000U)
#define LAN8742_ENCTR_RX_ENABLE ((uint16_t)0x1000U)
#define LAN8742_ENCTR_RX_MAX_INTERVAL ((uint16_t)0x0C00U)
#define LAN8742_ENCTR_RX_MAX_INTERVAL_64MS ((uint16_t)0x0000U)
#define LAN8742_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
#define LAN8742_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
#define LAN8742_ENCTR_RX_MAX_INTERVAL_1S ((uint16_t)0x0C00U)
#define LAN8742_ENCTR_EX_CROSS_OVER ((uint16_t)0x0002U)
#define LAN8742_ENCTR_EX_MANUAL_CROSS_OVER ((uint16_t)0x0001U)
/*** @}*//** @defgroup LAN8742_MCSR_Bit_Definition LAN8742 MCSR Bit Definition* @{*/
#define LAN8742_MCSR_EDPWRDOWN ((uint16_t)0x2000U)
#define LAN8742_MCSR_FARLOOPBACK ((uint16_t)0x0200U)
#define LAN8742_MCSR_ALTINT ((uint16_t)0x0040U)
#define LAN8742_MCSR_ENERGYON ((uint16_t)0x0002U)
/*** @}*//** @defgroup LAN8742_SMR_Bit_Definition LAN8742 SMR Bit Definition* @{*/
#define LAN8742_SMR_MODE ((uint16_t)0x00E0U)
#define LAN8742_SMR_PHY_ADDR ((uint16_t)0x001FU)
/*** @}*//** @defgroup LAN8742_TPDCR_Bit_Definition LAN8742 TPDCR Bit Definition* @{*/
#define LAN8742_TPDCR_DELAY_IN ((uint16_t)0x8000U)
#define LAN8742_TPDCR_LINE_BREAK_COUNTER ((uint16_t)0x7000U)
#define LAN8742_TPDCR_PATTERN_HIGH ((uint16_t)0x0FC0U)
#define LAN8742_TPDCR_PATTERN_LOW ((uint16_t)0x003FU)
/*** @}*//** @defgroup LAN8742_TCSR_Bit_Definition LAN8742 TCSR Bit Definition* @{*/
#define LAN8742_TCSR_TDR_ENABLE ((uint16_t)0x8000U)
#define LAN8742_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
#define LAN8742_TCSR_TDR_CH_CABLE_TYPE ((uint16_t)0x0600U)
#define LAN8742_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
#define LAN8742_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
#define LAN8742_TCSR_TDR_CH_CABLE_OPEN ((uint16_t)0x0400U)
#define LAN8742_TCSR_TDR_CH_CABLE_MATCH ((uint16_t)0x0600U)
#define LAN8742_TCSR_TDR_CH_STATUS ((uint16_t)0x0100U)
#define LAN8742_TCSR_TDR_CH_LENGTH ((uint16_t)0x00FFU)
/*** @}*//** @defgroup LAN8742_SCSIR_Bit_Definition LAN8742 SCSIR Bit Definition* @{*/
#define LAN8742_SCSIR_AUTO_MDIX_ENABLE ((uint16_t)0x8000U)
#define LAN8742_SCSIR_CHANNEL_SELECT ((uint16_t)0x2000U)
#define LAN8742_SCSIR_SQE_DISABLE ((uint16_t)0x0800U)
#define LAN8742_SCSIR_XPOLALITY ((uint16_t)0x0010U)
/*** @}*//** @defgroup LAN8742_CLR_Bit_Definition LAN8742 CLR Bit Definition* @{*/
#define LAN8742_CLR_CABLE_LENGTH ((uint16_t)0xF000U)
/*** @}*//** @defgroup LAN8742_IMR_ISFR_Bit_Definition LAN8742 IMR ISFR Bit Definition* @{*/
#define LAN8742_INT_8 ((uint16_t)0x0100U)
#define LAN8742_INT_7 ((uint16_t)0x0080U)
#define LAN8742_INT_6 ((uint16_t)0x0040U)
#define LAN8742_INT_5 ((uint16_t)0x0020U)
#define LAN8742_INT_4 ((uint16_t)0x0010U)
#define LAN8742_INT_3 ((uint16_t)0x0008U)
#define LAN8742_INT_2 ((uint16_t)0x0004U)
#define LAN8742_INT_1 ((uint16_t)0x0002U)
/*** @}*//** @defgroup LAN8742_PHYSCSR_Bit_Definition LAN8742 PHYSCSR Bit Definition* @{*/
#define LAN8742_PHYSCSR_AUTONEGO_DONE ((uint16_t)0x1000U)
#define LAN8742_PHYSCSR_HCDSPEEDMASK ((uint16_t)0x001CU)
#define LAN8742_PHYSCSR_10BT_HD ((uint16_t)0x0004U)
#define LAN8742_PHYSCSR_10BT_FD ((uint16_t)0x0014U)
#define LAN8742_PHYSCSR_100BTX_HD ((uint16_t)0x0008U)
#define LAN8742_PHYSCSR_100BTX_FD ((uint16_t)0x0018U)
/*** @}*//** @defgroup LAN8742_Status LAN8742 Status* @{*/ #define LAN8742_STATUS_READ_ERROR ((int32_t)-5)
#define LAN8742_STATUS_WRITE_ERROR ((int32_t)-4)
#define LAN8742_STATUS_ADDRESS_ERROR ((int32_t)-3)
#define LAN8742_STATUS_RESET_TIMEOUT ((int32_t)-2)
#define LAN8742_STATUS_ERROR ((int32_t)-1)
#define LAN8742_STATUS_OK ((int32_t) 0)
#define LAN8742_STATUS_LINK_DOWN ((int32_t) 1)
#define LAN8742_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2)
#define LAN8742_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3)
#define LAN8742_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4)
#define LAN8742_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5)
#define LAN8742_STATUS_AUTONEGO_NOTDONE ((int32_t) 6)
/*** @}*//** @defgroup LAN8742_IT_Flags LAN8742 IT Flags* @{*/
#define LAN8742_WOL_IT LAN8742_INT_8
#define LAN8742_ENERGYON_IT LAN8742_INT_7
#define LAN8742_AUTONEGO_COMPLETE_IT LAN8742_INT_6
#define LAN8742_REMOTE_FAULT_IT LAN8742_INT_5
#define LAN8742_LINK_DOWN_IT LAN8742_INT_4
#define LAN8742_AUTONEGO_LP_ACK_IT LAN8742_INT_3
#define LAN8742_PARALLEL_DETECTION_FAULT_IT LAN8742_INT_2
#define LAN8742_AUTONEGO_PAGE_RECEIVED_IT LAN8742_INT_1
/*** @}*//*** @}*//* Exported types ------------------------------------------------------------*/
/** @defgroup LAN8742_Exported_Types LAN8742 Exported Types* @{*/
typedef int32_t (*lan8742_Init_Func) (void);
typedef int32_t (*lan8742_DeInit_Func) (void);
typedef int32_t (*lan8742_ReadReg_Func) (uint32_t, uint32_t, uint32_t *);
typedef int32_t (*lan8742_WriteReg_Func) (uint32_t, uint32_t, uint32_t);
typedef int32_t (*lan8742_GetTick_Func) (void);typedef struct
{ lan8742_Init_Func Init; lan8742_DeInit_Func DeInit;lan8742_WriteReg_Func WriteReg;lan8742_ReadReg_Func ReadReg; lan8742_GetTick_Func GetTick;
} lan8742_IOCtx_t; typedef struct
{uint32_t DevAddr;uint32_t Is_Initialized;lan8742_IOCtx_t IO;void *pData;
}lan8742_Object_t;
/*** @}*/ /* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup LAN8742_Exported_Functions LAN8742 Exported Functions* @{*/
int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx);
int32_t LAN8742_Init(lan8742_Object_t *pObj);
int32_t LAN8742_DeInit(lan8742_Object_t *pObj);
int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj);
int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj);
int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj);
int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj);
int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState);
int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj);
int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj);
int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt);
/*** @}*/ #ifdef __cplusplus
}
#endif
#endif /* LAN8742_H */
创建app_ethernet.c及app_ethernet.h文件并添加
app_ethernet.c代码
/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "lwip/opt.h"
#include "main.h"
#if LWIP_DHCP
#include "lwip/dhcp.h"
#endif
#include "app_ethernet.h"
#include "ethernetif.h"/* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t EthernetLinkTimer;#if LWIP_DHCP
#define MAX_DHCP_TRIES 4
uint32_t DHCPfineTimer = 0;
uint8_t DHCP_state = DHCP_OFF;
#endif/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*** @brief Notify the User about the network interface config status* @param netif: the network interface* @retval None*/
void ethernet_link_status_updated(struct netif *netif)
{if (netif_is_link_up(netif)){
#if LWIP_DHCP/* Update DHCP state machine */DHCP_state = DHCP_START;
#else
// BSP_LED_On(LED2);
// BSP_LED_Off(LED3);
#endif /* LWIP_DHCP */netif_set_up(netif);}else{
#if LWIP_DHCP/* Update DHCP state machine */DHCP_state = DHCP_LINK_DOWN;
#else
// BSP_LED_Off(LED2);
// BSP_LED_On(LED3);
#endif /* LWIP_DHCP */netif_set_down(netif);}
}#if LWIP_NETIF_LINK_CALLBACK
/*** @brief Ethernet Link periodic check* @param netif* @retval None*/
void Ethernet_Link_Periodic_Handle(struct netif *netif)
{/* Ethernet Link every 100ms */if (HAL_GetTick() - EthernetLinkTimer >= 100){EthernetLinkTimer = HAL_GetTick();
// ethernet_link_check_state(netif);}
}
#endif#if LWIP_DHCP
/*** @brief DHCP_Process_Handle* @param None* @retval None*/
void DHCP_Process(struct netif *netif)
{ip_addr_t ipaddr;ip_addr_t netmask;ip_addr_t gw;struct dhcp *dhcp;switch (DHCP_state){case DHCP_START:{ip_addr_set_zero_ip4(&netif->ip_addr);ip_addr_set_zero_ip4(&netif->netmask);ip_addr_set_zero_ip4(&netif->gw);dhcp_start(netif);DHCP_state = DHCP_WAIT_ADDRESS;}break;case DHCP_WAIT_ADDRESS:{if (dhcp_supplied_address(netif)){DHCP_state = DHCP_ADDRESS_ASSIGNED;char ip_str[16];ip4_addr_set_u32(&ipaddr, netif_ip4_addr(netif)->addr);ip4addr_ntoa_r(&ipaddr, ip_str, sizeof(ip_str));printf("IPv4 address: %s\n", ip_str);}else{dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);/* DHCP timeout */if (dhcp->tries > MAX_DHCP_TRIES){DHCP_state = DHCP_TIMEOUT;/* Static address used */IP_ADDR4(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);netif_set_addr(netif, &ipaddr, &netmask, &gw);}}}break;case DHCP_LINK_DOWN:{DHCP_state = DHCP_OFF;}break;default: break;}
}/*** @brief DHCP periodic check* @param netif* @retval None*/void DHCP_Periodic_Handle(struct netif *netif)
{/* Fine DHCP periodic process every 500ms */if (HAL_GetTick() - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS){DHCPfineTimer = HAL_GetTick();/* process DHCP state machine */DHCP_Process(netif);}
}#endif
app_ethernet.h代码
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_ETHERNET_H
#define __APP_ETHERNET_H#ifdef __cplusplusextern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "lwip/netif.h"/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* DHCP process states */
#define DHCP_OFF (uint8_t) 0
#define DHCP_START (uint8_t) 1
#define DHCP_WAIT_ADDRESS (uint8_t) 2
#define DHCP_ADDRESS_ASSIGNED (uint8_t) 3
#define DHCP_TIMEOUT (uint8_t) 4
#define DHCP_LINK_DOWN (uint8_t) 5/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void ethernet_link_status_updated(struct netif *netif);
void Ethernet_Link_Periodic_Handle(struct netif *netif);
#if LWIP_DHCP
void DHCP_Process(struct netif *netif);
void DHCP_Periodic_Handle(struct netif *netif);
#endif #ifdef __cplusplus
}
#endif#endif /* __APP_ETHERNET_H */
这里lwip移植基本完成 最后一步需要完成协议栈初始化、获取数据包。
在工程文件Core\src中创建lwip.c文件及 Core\src文件夹中创建lwip.h文件
添加到工程分组中
lwip.c文件
设置主机的IP地址、子网掩码、网关地址等
#include "lwip.h"uint8_t flag_netif = 0;
struct netif gnetif;
ip4_addr_t ipaddr;
uint8_t lwip_flag;
ip4_addr_t netmask;
ip4_addr_t gw;
extern ETH_HandleTypeDef EthHandle;
uint32_t pRegValue;void MX_LWIP_Init(void)
{/* IP addresses initialization *///复位ETHHAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_RESET);HAL_Delay(100);HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_SET);HAL_Delay(100);/* Initilialize the LwIP stack without RTOS */lwip_init();/* IP addresses initialization without DHCP (IPv4) */IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);/* add the network interface (IPv4/IPv6) without RTOS */netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);/* Registers the default network interface */netif_set_default(&gnetif);if (netif_is_link_up(&gnetif)){flag_netif = 1; /* When the netif is fully configured this function must be called */netif_set_up(&gnetif);}else{/* When the netif link is down this function must be called */netif_set_down(&gnetif);}/* Set the link callback function, this function is called on change of link status*/netif_set_link_callback(&gnetif, ethernet_link_status_updated);
}/*处理接收到的数据包*/
void MX_LWIP_Process(void)
{lwip_flag = 0;ethernetif_input(&gnetif);/* Handle timeouts */sys_check_timeouts();
}
lwip.h文件 (配置IP地址)
#ifndef __LWIP_H_
#define __LWIP_H_#include "main.h"
#include "lwip/opt.h"
#include "lwip/init.h"
#include "netif/etharp.h"
#include "lwip/netif.h"
#include "lwip/timeouts.h"
#if LWIP_DHCP
#include "lwip/dhcp.h"
#endif
#include "ethernetif.h"
#include "app_ethernet.h"
#include "tcp.h"
#include "lan8742.h"#define ETH_RST_GPIO_Port GPIOC
#define ETH_RST_Pin GPIO_PIN_0/*设置的IP*/
#define IP_ADDR0 ((uint8_t) 192U) /*换为自己需要配置的IP地址*/
#define IP_ADDR1 ((uint8_t) 168U)
#define IP_ADDR2 ((uint8_t) 0U)
#define IP_ADDR3 ((uint8_t) 1U)/*子网掩码*/
#define NETMASK_ADDR0 ((uint8_t) 255U) /*换为自己需要配置的子网掩码*/
#define NETMASK_ADDR1 ((uint8_t) 255U)
#define NETMASK_ADDR2 ((uint8_t) 0U)
#define NETMASK_ADDR3 ((uint8_t) 0U)/*网关地址*/
#define GW_ADDR0 ((uint8_t) 192U) /*换为自己需要配置的网关地址*/
#define GW_ADDR1 ((uint8_t) 168U)
#define GW_ADDR2 ((uint8_t) 0U)
#define GW_ADDR3 ((uint8_t) 1U)void MX_LWIP_Init(void);
void Reset_network(void);
void MX_LWIP_Process(void);#endif
main.c文件
在main.c文件中 添加#include "lwip.h" 头文件
添加lwip初始化函数和数据包处理函数
编译成功并下载
可以ping通 这样移植lwip就成功了
通过上面的步骤,我们能使用开发板获取网络的数据包了,但是获取数据包的方式有两种,一种是查询方式,另一种是中断方式。这里选择查询方式,查询方式通过主函数的while循环进行周期性处理,去获取网卡中是否接收到数据包,然后递交给上层协议去处理。
中断方式后续更新。
作者能力有限 有什么问题 欢迎大家指正或讨论