当前位置: 技术问答>linux和unix
以太网的缓冲区不够用怎么办?请教各位帮忙!
来源: 互联网 发布时间:2016-04-24
本文导语: IP数据报的最大长度是65535字节,然后它会分片,分成长度为1500字节的片(40多片)传给MAC层,发送 (1)小弟最近很困惑,假如来了一个接收中断,那如果接收端的以太网的buffer只有buffer[8][1500]这么大怎么办? (...
IP数据报的最大长度是65535字节,然后它会分片,分成长度为1500字节的片(40多片)传给MAC层,发送
(1)小弟最近很困惑,假如来了一个接收中断,那如果接收端的以太网的buffer只有buffer[8][1500]这么大怎么办?
(2)9200手册上说这个缓冲区是循环的,我不太理解循环缓冲区的原理,假如说来了一次中断,那么进入中断处理函数,读了buffer[0][1500],然后把这个buffer置为可用,那中断函数不退出就能再接到数据存到buffer[0][1500]中么?
(3)9200手册上说EMAC_RBQP是接收缓冲队列指针,初始化成接收缓冲区的首地址
regs->EMAC_RBQP = (AT91_REG) tdList;
那这个指针是不是始终指向首地址啊?还是会根据接收到的不同的buffer自动增加?对硬件理解不够,困惑ing
以下是小弟写的接收处理函数,用的是9200的EMAC+DM9161的PHY,在lwip下的移植
希望熟悉9200EMAC的朋友给予指点,谢谢!
static struct pbuf *
low_level_input(struct netif *netif)
{
struct pbuf *p, *q;
struct pbuf *h;
u16_t len;
unsigned char *p_recv;
unsigned int pktlen,total_len=0;
u16_t rxBuffIndex=0;
u16_t i=0;
//得到本次接收数据的总长度
while(tdList[i++].addr & EMAC_DESC_DONE);
total_len+=MAX_RBUFF_SZ;
if(total_len==MAX_RBUFF_SZ)
total_len=0;
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL);
if (p != NULL)
{
q=p;
#if ETH_PAD_SIZE
pbuf_header(q, -ETH_PAD_SIZE); /* drop the padding word */
#endif
//原来的bit0应该初始化成0,受到数据EMAC_DESC_DONE自动置位
while(tdList[rxBuffIndex].addr & EMAC_DESC_DONE)
{
p_recv =(char *)(tdList[rxBuffIndex].addr & 0xFFFFFFFC);;
pktlen = tdList[rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
if(q!=NULL)
{
memcpy((char *)q->payload, p_recv, pktlen);
q->len=pktlen;
}
//清零后这个缓冲区可以继续接收别的数据?
tdList[rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
if (rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
rxBuffIndex = 0;
else
rxBuffIndex++;
q=q->next;
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
}
else
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
return p;
}
(1)小弟最近很困惑,假如来了一个接收中断,那如果接收端的以太网的buffer只有buffer[8][1500]这么大怎么办?
(2)9200手册上说这个缓冲区是循环的,我不太理解循环缓冲区的原理,假如说来了一次中断,那么进入中断处理函数,读了buffer[0][1500],然后把这个buffer置为可用,那中断函数不退出就能再接到数据存到buffer[0][1500]中么?
(3)9200手册上说EMAC_RBQP是接收缓冲队列指针,初始化成接收缓冲区的首地址
regs->EMAC_RBQP = (AT91_REG) tdList;
那这个指针是不是始终指向首地址啊?还是会根据接收到的不同的buffer自动增加?对硬件理解不够,困惑ing
以下是小弟写的接收处理函数,用的是9200的EMAC+DM9161的PHY,在lwip下的移植
希望熟悉9200EMAC的朋友给予指点,谢谢!
static struct pbuf *
low_level_input(struct netif *netif)
{
struct pbuf *p, *q;
struct pbuf *h;
u16_t len;
unsigned char *p_recv;
unsigned int pktlen,total_len=0;
u16_t rxBuffIndex=0;
u16_t i=0;
//得到本次接收数据的总长度
while(tdList[i++].addr & EMAC_DESC_DONE);
total_len+=MAX_RBUFF_SZ;
if(total_len==MAX_RBUFF_SZ)
total_len=0;
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL);
if (p != NULL)
{
q=p;
#if ETH_PAD_SIZE
pbuf_header(q, -ETH_PAD_SIZE); /* drop the padding word */
#endif
//原来的bit0应该初始化成0,受到数据EMAC_DESC_DONE自动置位
while(tdList[rxBuffIndex].addr & EMAC_DESC_DONE)
{
p_recv =(char *)(tdList[rxBuffIndex].addr & 0xFFFFFFFC);;
pktlen = tdList[rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */
if(q!=NULL)
{
memcpy((char *)q->payload, p_recv, pktlen);
q->len=pktlen;
}
//清零后这个缓冲区可以继续接收别的数据?
tdList[rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */
if (rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */
rxBuffIndex = 0;
else
rxBuffIndex++;
q=q->next;
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
}
else
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
return p;
}
|
发包的时候需要发包程序维持一个自己的缓冲区,然后再发送给网卡的缓冲区做发送用。
而收包的时候数据包首先到达网卡的缓冲区,如果缓冲区满了,数据包会被丢掉。
而收包的时候数据包首先到达网卡的缓冲区,如果缓冲区满了,数据包会被丢掉。