ARM硬件平台上基于UCOS移植Lwip网络协议栈
chain = 1;
}
else
{
tr_len = q->len;
tr_ptr = (u8_t*)q->payload;
chain = 0;
}
}
ne2k_copyout(tr_len, tr_ptr);
if (chain == 1) NE_DATAW = temp_dw;
}
if(padLength>0)
ne2k_outpad(padLength);
/* Wait for remote dma to complete - ISR Bit 6 clear if busy */
while((u8_t)(NE_ISR & ENISR_RDC) == 0 );
/* clear RDC */
NE_ISR = ENISR_RDC;
/* Issue the transmit command.(start local dma) */
NE_TPSR = NE_START_PG;
NE_TBCR0 = packetLength & 0xff;
NE_TBCR1 = packetLength >> 8;
/* Start transmission (and shut off remote dma) */
NE_CR = ENCR_PAGE0 | ENCR_NODMA | ENCR_TRANS | ENCR_START;
/* reopen receive interrupt */
NE_CR = ENCR_PAGE2 | ENCR_NODMA | ENCR_START;
isr = NE_IMR;
isr |= ENISR_RX;
NE_CR = ENCR_PAGE0 | ENCR_NODMA | ENCR_START;
NE_IMR = isr;
#ifdef LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
return ERR_OK;
}
low_level_input函数从网卡读取数据,封装成pbuf形式后传递给上层应用层。其源代码如下:
static struct pbuf *
low_level_input(struct netif *netif)
{
struct pbuf *p, *q;
u16_t packetLength, len;
u8_t PDHeader[18]; /* Temp storage for ethernet headers */
u8_t * payload;
NE_ISR = ENISR_RDC;
// NE_RBCR1 = 0x0f; /* See controller manual , use send packet command */
NE_CR = ENCR_PAGE0 | ENCR_RREAD | ENCR_RWRITE | ENCR_START;
// NE_CR = ENCR_PAGE0 | ENCR_RREAD | ENCR_START;
/* get the first 18 bytes from nic */
ne2k_copyin(18,PDHeader);
/* Store real length, set len to packet length - header */
packetLength = ((unsigned) PDHeader[2] | (PDHeader[3] < 8 ));
/* verify if the packet is an IP packet or ARP packet */
if((PDHeader[3]>0x06)||(PDHeader[16] != 8)||(PDHeader[17] != 0 && PDHeader[17] != 6))
{
ne2k_discard(packetLength-14);
return NULL;
}
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, packetLength, PBUF_POOL);
if (p != NULL) {
/* We iterate over the pbuf chain until we have read the entire
packet into the pbuf. */
/* This assumes a minimum pbuf size of 14 ... a good assumption */
memcpy(p->payload, PDHeader + 4, 14);
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
available data in the pbuf is given by the q->len
variable. */
payload = q->payload;
len = q->len;
if (q == p) {
payload += 14;
len -=14;
}
ne2k_copyin(len,payload);
}
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
} else {
/* no more PBUF resource, Discard packet in buffer. */
ne2k_discard(packetLength-14);
#ifdef LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
return p;
}
Lwip要求的协议栈底层操作网卡的函数编写完毕。
4.5 移植完成后测试TCP/IP协议栈
我们使用查询方式读取网卡数据包,具体方案是建一个查询任务,周期性调用GetPacket()函数,函数源代码:
void GetPacket(void)
{
u8_t isr,curr,bnry;
NE_CR = ENCR_PAGE0 | ENCR_NODMA;
isr = NE_ISR;
/* got packet with no errors */
if (isr & ENISR_RX) {
NE_ISR = ENISR_RX;
NE_CR = ENCR_PAGE1 | ENCR_NODMA;
curr = NE_CURR;
NE_CR = ENCR_PAGE0 | ENCR_NODMA;
bnry = NE_BNRY;
/* get more than one packet until receive buffer is empty */
while(curr != bnry) {
ethernetif_input(&rtl8019_netif);
NE_CR = ENCR_PAGE1 | ENCR_NODMA;
curr = NE_CURR;
NE_CR = ENCR_PAGE0 | ENCR_NODMA;
bnry = NE_BNRY;
}
// rBNRY = NE_BNRY;
}
else {
NE_ISR = 0xFF;
};
}
在测试lwip协议栈前,我们需要初始化。初始化代码:
struct netif rtl8019_netif;
struct netif loop_netif;
extern err_t ethernetif_init(struct netif *netif);
void lwip_init_task(void)
{
struct ip_addr ipaddr, netmask, gw;
tcpip_init(NULL,NULL);
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,174);
IP4_ADDR(&netmask, 255,255,255,0);
netif_add(&rtl8019_netif,&ipaddr,&netmask,&gw,NULL,ethernetif_init,tcpip_input);
netif_set_default(&rtl8019_netif);
netif_set_up(&rtl8019_netif);
}
系统ping测试成功如图4.5-1 ping测试:
ARM硬件平台UCOS移植网络协议 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)