基于Enc28j60的LwIP(1.4.1)移植

        移植过程比较容易,网上一堆教程,本文主要将low_level_output和low_level_input针对Enc28j60做一些优化,减少数据拷贝。

        网上比较多的应该是如下代码:

static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
	struct pbuf *q = NULL;
	uint16_t packet_len = 0;


	//遍历pbuf链表
	for(q = p; q != NULL; q = q->next)
	{
		memcpy(&lwip_txbuf[packet_len],q->payload,q->len);
		packet_len += q->len;
		if(packet_len > MAX_FRAMELEN || packet_len > p->tot_len)
		{
			LWIP_PLATFORM_DIAG(("PacketTx error! packet_len=%"U32_F",tot_len=%"U32_F"\n\t", packet_len, p->tot_len));
			return ERR_BUF;
		}
	}
	if(packet_len == p->tot_len)
	{
		Enc28j60_PacketTransfer(packet_len,lwip_txbuf);
		return ERR_OK;
	}
	LWIP_PLATFORM_DIAG(("PacketTx error! packet_len=%"U32_F",tot_len=%"U32_F"\n\t", packet_len, p->tot_len));
	return ERR_BUF;
}
static struct pbuf *
low_level_input(struct netif *netif)
{
	struct pbuf *p = NULL;
	struct pbuf *q = NULL;
	uint16_t packet_len = 0;
	uint16_t temp_len = 0;
	packet_len = Enc28j60_PacketReceive(MAX_FRAMELEN,lwip_rxbuf);
	if(packet_len == 0)
	{
		return NULL;
	}


	/* We allocate a pbuf chain of pbufs from the pool. */
	p = pbuf_alloc(PBUF_RAW, packet_len, PBUF_POOL);
	if(p != NULL) 
	{
		for(q = p; q != NULL; q = q->next)
		{
			memcpy(q->payload, &lwip_rxbuf[temp_len],q->len);
			temp_len += q->len;
			if(temp_len >= packet_len) break;
		}
		else 
	{
		LWIP_PLATFORM_DIAG(("PacketRx: pbuf_alloc fail ,len=%"U32_F"\n\t", packet_len));
		return NULL;
	}
	return p;  	
}

从中可以看到有使用memcpy拷贝数据,大量数据通信时,会花费大量时间在拷贝上,为此做如下修改:

static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
	return pkt_send(p);
}
static struct pbuf *
low_level_input(struct netif *netif)
{
	return pkt_recv();
}
err_t pkt_send(struct pbuf *pkt_buf)
{
	while((Enc28j60_Read(ECON1) & ECON1_TXRTS)!=0);
	Enc28j60_Write(EWRPTL, TXSTART_INIT&0xFF);
	Enc28j60_Write(EWRPTH, TXSTART_INIT>>8);
	Enc28j60_Write(ETXNDL, (TXSTART_INIT + pkt_buf->tot_len)&0xFF);
	Enc28j60_Write(ETXNDH, (TXSTART_INIT + pkt_buf->tot_len)>>8);


	Enc28j60_Write_Op(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
	Packet_In(pkt_buf);


	Enc28j60_Write_Op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
	if((Enc28j60_Read(EIR) & EIR_TXERIF))
	{
		Enc28j60_Set_Bank(ECON1);
		Enc28j60_Write_Op(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
	}


	return ERR_OK;
}
static void Packet_In(struct pbuf *pkt_buf)
{
	struct pbuf *q = NULL;
	uint8_t	*buf;
	uint16_t len;


	ENC28J60_CSL();
	Enc28j60_ReadWrite(ENC28J60_WRITE_BUF_MEM);
	for(q = pkt_buf; q != NULL; q = q->next)
	{
		len = q->len;
		buf = q->payload;
		while(len--)
		{
			Enc28j60_ReadWrite(*buf++);
		}
	}
	ENC28J60_CSH();
}
struct pbuf *pkt_recv(void)
{
	struct pbuf *pkt_buf = NULL;
	uint16_t packet_len = 0;


	if(Enc28j60_Read(EPKTCNT) ==0)
	{
		return NULL;
	}
	packet_len = get_pkt_length();
	if(packet_len == 0)
	{
		return NULL;
	}
	/* We allocate a pbuf chain of pbufs from the pool. */
	pkt_buf = pbuf_alloc(PBUF_RAW, packet_len, PBUF_POOL);
	if(pkt_buf != NULL) 
	{
		Packet_Out(pkt_buf);
		Enc28j60_Write(ERXRDPTL, (NextPacketPtr));
	Enc28j60_Write(ERXRDPTH, (NextPacketPtr)>>8);
	Enc28j60_Write_Op(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);


	return pkt_buf;  	
}
static uint16_t get_pkt_length(void)
{
	uint16_t pkt_len = 0;
	uint16_t rx_status;


	Enc28j60_Write(ERDPTL, (NextPacketPtr));
	Enc28j60_Write(ERDPTH, (NextPacketPtr)>>8);
	NextPacketPtr  = Enc28j60_Read_Op(ENC28J60_READ_BUF_MEM, 0);
	NextPacketPtr |= Enc28j60_Read_Op(ENC28J60_READ_BUF_MEM, 0)<<8;
	pkt_len  = Enc28j60_Read_Op(ENC28J60_READ_BUF_MEM, 0);
	pkt_len |= Enc28j60_Read_Op(ENC28J60_READ_BUF_MEM, 0)<<8;
	pkt_len -= 4; 
	rx_status  = Enc28j60_Read_Op(ENC28J60_READ_BUF_MEM, 0);
	rx_status |= Enc28j60_Read_Op(ENC28J60_READ_BUF_MEM, 0)<<8;	  
	if(pkt_len > MAX_FRAMELEN-1)
	{
		pkt_len = MAX_FRAMELEN-1;
	}


	if((rx_status & 0x80)==0)
	{
		pkt_len = 0;
	}
	return pkt_len;
}
static void Packet_Out(struct pbuf *pkt_buf)
{
	struct pbuf *q = NULL;
	uint8_t	*buf;
	uint16_t len;
	ENC28J60_CSL();
	Enc28j60_ReadWrite(ENC28J60_READ_BUF_MEM);
	for(q = pkt_buf; q != NULL; q = q->next)
	{
		len = q->len;
		buf = q->payload;
		while(len--)
		{
			*buf++ = Enc28j60_ReadWrite(0xFF);
		}
	}
	ENC28J60_CSH();
}

         以上操作可以避免memcpy的使用,除了做如上优化,还可以将SPI读写BUFF改为DMA读写。


你可能感兴趣的:(LwIP)