⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lwipstack.c

📁 在luminary平台下移植lwip到freertos,集成开发环境KEIL
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
//
// Include standard library declarations.
//
//*****************************************************************************
#include <string.h>

//*****************************************************************************
//
// Include FreeRTOS declarations.
//
//*****************************************************************************
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

//*****************************************************************************
//
// lwIP API Header Files
//
//*****************************************************************************
#include "lwip/init.h"
#include "lwip/api.h"
#include "lwip/netifapi.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "lwip/tcpip.h"
#include "lwip/sockets.h"
#include "lwip/mem.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
#include "netif/etharp.h"
#include "lwip/autoip.h"
#include "lwip/dhcp.h"

//*****************************************************************************
//
// Luminary Micro DriverLib Header Files required for this interface driver.
//
//*****************************************************************************
#include "hw_ethernet.h"
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "debug.h"
#include "gpio.h"
#include "ethernet.h"
#include "interrupt.h"
#include "sysctl.h"

//#include "Apps/httpd.h"

#include "ETHIsr.h"
#include "LWIPStack.h"

// Sanity Check:  This interface driver will NOT work if the following defines are incorrect.
#if (PBUF_LINK_HLEN != 16)
#warning "PBUF_LINK_HLEN must be 16 for this interface driver!"
#endif
#if (ETH_PAD_SIZE != 2)
#warning "ETH_PAD_SIZE must be 2 for this interface driver!"
#endif

// Forward declarations.
static void ethernetif_input(void *pParams);
static struct pbuf * low_level_input(struct netif *netif);
static err_t low_level_output(struct netif *netif, struct pbuf *p);
static err_t low_level_transmit(struct netif *netif, struct pbuf *p);


void UART1printf(const char *pcString, ...);
//*****************************************************************************
//
// The lwIP network interface structure for the Stellaris Ethernet MAC.
//
//*****************************************************************************
static struct netif lwip_netif;

//*****************************************************************************
//
// In this function, the hardware should be initialized.
// Called from stellarisif_init().
//
// @param netif the already initialized lwip network interface structure
//        for this ethernetif
//!
//! \return None.
//!
//*****************************************************************************
static err_t low_level_init(struct netif *netif)
{

	ETHServiceTaskDisable(0);

	// set MAC hardware address length
	netif->hwaddr_len = ETHARP_HWADDR_LEN;

	LWIP_DEBUGF(NETIF_DEBUG, ("low_level_transmit: frame sent\n"));

	// set MAC hardware address
	ETHServiceTaskMACAddress(0, &(netif->hwaddr[0]));

	LWIP_DEBUGF(NETIF_DEBUG, ("low_level_init: MAC address is \%"X8_F"%"X8_F"%"X8_F"%"X8_F"%"X8_F"%"X8_F"\n",
					netif->hwaddr[0],netif->hwaddr[1],netif->hwaddr[2],
					netif->hwaddr[3],netif->hwaddr[4],netif->hwaddr[5]));

	// maximum transfer unit
	netif->mtu = ETH_MTU;

	LWIP_DEBUGF(NETIF_DEBUG, ("low_level_init: MTU set to %"U16_F"\n",netif->mtu));

	// device capabilities
	// don't set NETIF_FLAG_ETHARP if this device is not an ethernet one
	netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;

	// Create the task that handles the incoming packets.
	if (pdPASS == xTaskCreate(ethernetif_input, ( signed portCHAR * ) "ETH_INPUT", netifINTERFACE_TASK_STACK_SIZE, (void *)netif, netifINTERFACE_TASK_PRIORITY, NULL))
	{
		ETHServiceTaskEnable(0);LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input: Waiting for Ethernet to become ready\n"));
		ETHServiceTaskWaitReady(0);
		netif->flags |= NETIF_FLAG_LINK_UP;

		LWIP_DEBUGF(NETIF_DEBUG, ("low_level_init: Ethernet link is up\n"));

		return ERR_OK;

	}
	else
	{
		LWIP_DEBUGF(NETIF_DEBUG, ("low_level_init: create receive task error\n"));
		return ERR_IF;
	}
}

/**
 * Called from ethernetif_input
 *
 * This function will read a single packet from the Stellaris ethernet
 * interface, if available, and return a pointer to a pbuf.  The timestamp
 * of the packet will be placed into the pbuf structure.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return pointer to pbuf packet if available, NULL otherswise.
 */
static struct pbuf * low_level_input(struct netif *netif)
{
	struct pbuf *p, *q;
	u16_t len;
	u32_t temp;
	int i;
	unsigned long *ptr;
#if LWIP_PTPD
	u32_t time_s, time_ns;

	/* Get the current timestamp if PTPD is enabled */
	lwIPHostGetTime(&time_s, &time_ns);
#endif

	/* Check if a packet is available, if not, return NULL packet. */
	if ((HWREG(ETH_BASE + MAC_O_NP) & MAC_NP_NPR_M) == 0)
	{
		int err = ETHServiceTaskLastError(0);
		if ((ETH_ERROR & err) && (ETH_OVERFLOW & err))
		{
			LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input: Ethernet overflow\n"));
			LINK_STATS_INC(link.drop);
		}
		return (NULL);
	}

	/**
	 * Obtain the size of the packet and put it into the "len" variable.
	 * Note:  The length returned in the FIFO length position includes the
	 * two bytes for the length + the 4 bytes for the FCS.
	 *
	 */
	temp = HWREG(ETH_BASE + MAC_O_DATA);
	len = temp & 0xFFFF;

	/* We allocate a pbuf chain of pbufs from the pool. */
	p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

	/* If a pbuf was allocated, read the packet into the pbuf. */
	if (p != NULL)
	{
		/* Place the first word into the first pbuf location. */
		*(unsigned long *)p->payload = temp;
		p->payload = (char *)(p->payload) + 4;
		p->len -= 4;

		/* Process all but the last buffer in the pbuf chain. */
		q = p;
		while (q != NULL)
		{
			/* Setup a byte pointer into the payload section of the pbuf. */
			ptr = q->payload;

			/**
			 * Read data from FIFO into the current pbuf
			 * (assume pbuf length is modulo 4)
			 *
			 */
			for (i = 0; i < q->len; i += 4)
			{
				*ptr++ = HWREG(ETH_BASE + MAC_O_DATA);
			}

			/* Link in the next pbuf in the chain. */
			q = q->next;
		}

		/* Restore the first pbuf parameters to their original values. */
		p->payload = (char *)(p->payload) - 4;
		p->len += 4;

		/* Adjust the link statistics */
		LINK_STATS_INC(link.recv);

#if LWIP_PTPD
		// Place the timestamp in the PBUF
		p->time_s = time_s;
		p->time_ns = time_ns;
#endif
	}

	// If no pbuf available, just drain the RX fifo.
	else
	{
		for (i = 4; i < len; i+=4)
		{
			temp = HWREG(ETH_BASE + MAC_O_DATA);
		}

		// Adjust the link statistics
		LINK_STATS_INC(link.memerr);
		LINK_STATS_INC(link.drop);
	}

	return (p);
}

/**
 * The function low_level_init creates a thread with this function.
 *
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_receive() 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
 */

static void ethernetif_input(void *pParams)
{
	struct netif *netif;
	struct ethernetif *ethernetif;
	struct pbuf *p;

	netif = (struct netif*) pParams;
	ethernetif = netif->state;

	for (;;)
	{
		do
		{
			// move received packet into a new pbuf
			p = low_level_input(netif);

			if ((p == NULL) && (0 == ETHServiceTaskPacketAvail(0)))
			{
				// Actually enables only RX interrupt
				ETHServiceTaskEnableReceive(0);

				// No packet could be read.  Wait a for an interrupt to tell us
				// there is more data available.
				xSemaphoreTake(ETHRxBinSemaphore[0], ( portTickType ) (ETH_BLOCK_TIME_WAITING_FOR_INPUT_MS / portTICK_RATE_MS));
			}

		} while (p == NULL);

		LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: frame received\n"));

		if (ERR_OK != netif->input(p, netif))
		{
			LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: input error\n"));
			pbuf_free(p);
			p = NULL;
		}
	}
}

/**
 * Called from ethernetif_init
 *
 * This function with either place the packet into the Stellaris transmit fifo,
 * or will place the packet in the interface PBUF Queue for subsequent
 * transmission when the transmitter becomes idle.
 *
 * @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
 *
 */
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
	err_t status;

	// Bump the reference count on the pbuf to prevent it from being
	// freed till we are done with it.
	pbuf_ref(p);

	// Prevent from simultaneously writing to ETH TX FIFO
	xSemaphoreTake(ETHTxAccessMutex[0], ( portTickType ) portMAX_DELAY);

	// If the transmitter is idle, send the pbuf now.
	if (((HWREG(ETH_BASE + MAC_O_TR) & MAC_TR_NEWTX) == 0))
	{
		// Send packet via eth controller
		status = low_level_transmit(netif, p);
	}
	else
	{
		LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: Ethernet transmitter busy\n"));
		// Enable generating transmit interrupt for eth. controller
		EthernetIntEnable(ETH_BASE, ETH_INT_TX);

		// Waiting for finishing transmitting from interrupt routine
		xSemaphoreTake(ETHTxBinSemaphore[0], ( portTickType ) portMAX_DELAY);

		// Send packet via eth controller
		status = low_level_transmit(netif, p);

		// Disable generating transmit interrupt for eth. controller
		EthernetIntDisable(ETH_BASE, ETH_INT_TX);
	}

	// Release mutex
	xSemaphoreGive(ETHTxAccessMutex[0]);

	pbuf_free(p);

	return status;
}

/**
 * Called from low_level_output
 *
 * 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 This function MUST be called with interrupts disabled or with the
 *       Stellaris Ethernet transmit fifo protected.
 */
static err_t low_level_transmit(struct netif *netif, struct pbuf *p)
{
	int iBuf;
	unsigned char *pucBuf;
	unsigned long *pulBuf;
	struct pbuf *q;
	int iGather;
	unsigned long ulGather;
	unsigned char *pucGather;

	if (0 == ETHServiceTaskLinkStatus(0))
	{
		// ~ bitwise negation, all bit except NETIF_FLAG_LINK_UP set to 1 and AND with current flag
		netif->flags &= ~NETIF_FLAG_LINK_UP;LWIP_DEBUGF(NETIF_DEBUG, ("low_level_transmit: link is down\n"));
		LINK_STATS_INC(link.err);
		return (ERR_IF);
	}
	else
	{
		netif->flags |= NETIF_FLAG_LINK_UP;
	}

	/**
	 * Fill in the first two bytes of the payload data (configured as padding
	 * with ETH_PAD_SIZE = 2) with the total length of the payload data
	 * (minus the Ethernet MAC layer header).
	 *
	 */
	*((unsigned short *)(p->payload)) = p->tot_len - 16;

	/* Initialize the gather register. */
	iGather = 0;
	pucGather = (unsigned char *)&ulGather;
	ulGather = 0;

	/* Copy data from the pbuf(s) into the TX Fifo. */
	for (q = p; q != NULL; q = q->next)
	{
		/* Intialize a char pointer and index to the pbuf payload data. */
		pucBuf = (unsigned char *)q->payload;
		iBuf = 0;

		/**
		 * If the gather buffer has leftover data from a previous pbuf
		 * in the chain, fill it up and write it to the Tx FIFO.
		 *
		 */
		while ((iBuf < q->len) && (iGather != 0))
		{
			/* Copy a byte from the pbuf into the gather buffer. */
			pucGather[iGather] = pucBuf[iBuf++];

			/* Increment the gather buffer index modulo 4. */
			iGather = ((iGather + 1) % 4);
		}

		/**
		 * If the gather index is 0 and the pbuf index is non-zero,
		 * we have a gather buffer to write into the Tx FIFO.
		 *
		 */
		if ((iGather == 0) && (iBuf != 0))
		{
			HWREG(ETH_BASE + MAC_O_DATA) = ulGather;
			ulGather = 0;
		}

		/* Initialze a long pointer into the pbuf for 32-bit access. */
		pulBuf = (unsigned long *)&pucBuf[iBuf];

		/**
		 * Copy words of pbuf data into the Tx FIFO, but don't go past
		 * the end of the pbuf.
		 *
		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -