问题一:
我在调试中发现我的程序永远在创建ethernetif_input的任务里出不来了。我的ethernetif_input任务是在low_level_init函数中创建的,于是我把ethernetif_input优先级降到了所有任务中的最低。
(请问应该可以让ethernetif_input是最低的优先级任务吧,我现在任务就只有tcpip任务——优先级为7,LWIP_ENTRY——优先级为10,MAIN_TASK——优先级为3,ethernetif_input——优先级为16。操作系统运行后创建任务MAIN_TASK,在MAIN_TASK中创建LWIP_ENTRY,在LWIP_ENTRY中调用的LwIP最基本的初始化工作函数中有tcpip_init(NULL, NULL);在tcpip_init中创建了tcpip任务——tcpip_thread,然后在设置LwIP,包括添加配置网络接口、建立接收任务等工作的函数中的函数ethernetif_input函数中创建任务ethernetif_input——优先级为16。请教这样的优先级安排没问题吧)。
答:对于你提出来优先级别的问题,我曾经也一直困扰我,不知道哪个任务优先级别高好一点,但是经过一段时间的测试,我把我的优先级别列出来,仅供你参考使用:不是唯一和一定的。
函数 优先级
tcpip_thread 6
ethernetif_input 7
LwIPEntry 20 (这个任务建立了以上两个任务)
也就是说:我整个程序最高的优先级就是6 其他都别 6 和 7 低 应用程序更低
问题二:
我降低了ethernetif_input优先级后用PING命令还是无法PING通,在串口输出上没有看到ethernetif_input函数中加的调试输出的东西,我就想我的ethernetif_input函数可能有问题,于是想改为大哥您的那个ethernetif_input函数。在您的函数中发现一个问题。
void ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p;
while(1)
{
ethernetif = netif->state;
do{
p = low_level_input(netif);
if (p == NULL)
OSTimeDlyHMSM(0,0,0,100);
}while(p == NULL);
void ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p;
while(1)
{
ethernetif = netif->state;
do{
p = low_level_input(netif);
if (p == NULL)
OSTimeDlyHMSM(0,0,0,100);
}while(p == NULL);
#if LINK_STATS
lwip_stats.link.recv++;
#endif
lwip_stats.link.recv++;
#endif
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
#if 1
etharp_ip_input(netif, p); //更新ARP表
#endif
//跳过以太网头部字段
pbuf_header(p, -sizeof(struct eth_hdr));
//传递到网络层
netif->input(p, netif);
break;
case ETHTYPE_ARP:
//将netif传递到ARP模块
p = etharp_arp_input(netif, ethernetif->ethaddr, p);
if(p != NULL) {
low_level_output(netif, p);
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
}
在上面函数中用到了p = etharp_arp_input(netif, ethernetif->ethaddr, p);但是在etharp.c中找到etharp_arp_input函数原型,它为void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p),是无返回值类型,大哥应该是对函数etharp_arp_input()进行了修改的,能将修改后的函数给我看看吗,返回的是什么呢?
答:原函数如下->
#if 1
etharp_ip_input(netif, p); //更新ARP表
#endif
//跳过以太网头部字段
pbuf_header(p, -sizeof(struct eth_hdr));
//传递到网络层
netif->input(p, netif);
break;
case ETHTYPE_ARP:
//将netif传递到ARP模块
p = etharp_arp_input(netif, ethernetif->ethaddr, p);
if(p != NULL) {
low_level_output(netif, p);
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
}
在上面函数中用到了p = etharp_arp_input(netif, ethernetif->ethaddr, p);但是在etharp.c中找到etharp_arp_input函数原型,它为void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p),是无返回值类型,大哥应该是对函数etharp_arp_input()进行了修改的,能将修改后的函数给我看看吗,返回的是什么呢?
答:原函数如下->
struct pbuf *
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
struct etharp_hdr *hdr;
/* these are aligned properly, whereas the ARP header fields might not be */
struct ip_addr sipaddr, dipaddr;
u8_t i;
u8_t for_us;
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
struct etharp_hdr *hdr;
/* these are aligned properly, whereas the ARP header fields might not be */
struct ip_addr sipaddr, dipaddr;
u8_t i;
u8_t for_us;
LWIP_ASSERT("netif != NULL", netif != NULL);
/* drop short ARP packets */
if (p->tot_len < sizeof(struct etharp_hdr)) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F") ", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
pbuf_free(p);
return;
}
/* drop short ARP packets */
if (p->tot_len < sizeof(struct etharp_hdr)) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F") ", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
pbuf_free(p);
return;
}
hdr = p->payload;
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules). */
memcpy((void *)&sipaddr, (void *)&hdr->sipaddr, sizeof(sipaddr));
memcpy((void *)&dipaddr,(void *) &hdr->dipaddr, sizeof(dipaddr));
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
* structure packing (not using structure copy which breaks strict-aliasing rules). */
memcpy((void *)&sipaddr, (void *)&hdr->sipaddr, sizeof(sipaddr));
memcpy((void *)&dipaddr,(void *) &hdr->dipaddr, sizeof(dipaddr));
/* this interface is not configured? */
if (netif->ip_addr.addr == 0) {
for_us = 0;
} else {
/* ARP packet directed to us? */
for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
}
if (netif->ip_addr.addr == 0) {
for_us = 0;
} else {
/* ARP packet directed to us? */
for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
}
/* ARP message directed to us? */
if (for_us) {
/* add IP address in ARP cache; assume requester wants to talk to us.
* can result in directly sending the queued packets for this host. */
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
/* ARP message not directed to us? */
} else {
/* update the source IP address in the cache, if present */
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
}
if (for_us) {
/* add IP address in ARP cache; assume requester wants to talk to us.
* can result in directly sending the queued packets for this host. */
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
/* ARP message not directed to us? */
} else {
/* update the source IP address in the cache, if present */
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
}
/* now act on the message itself */
switch (htons(hdr->opcode)) {
/* ARP request? */
case ARP_REQUEST:
/* ARP request. If it asked for our address, we send out a
* reply. In any case, we time-stamp any existing ARP entry,
* and possiby send out an IP packet that was queued on it. */
switch (htons(hdr->opcode)) {
/* ARP request? */
case ARP_REQUEST:
/* ARP request. If it asked for our address, we send out a
* reply. In any case, we time-stamp any existing ARP entry,
* and possiby send out an IP packet that was queued on it. */
LWIP_DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request "));
/* ARP request for our address? */
if (for_us) {
/* ARP request for our address? */
if (for_us) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address "));
/* re-use pbuf to send ARP reply */
hdr->opcode = htons(ARP_REPLY);
/* re-use pbuf to send ARP reply */
hdr->opcode = htons(ARP_REPLY);
hdr->dipaddr = hdr->sipaddr;
hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
i = netif->hwaddr_len;
while(i > 0) {
i--;
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
hdr->shwaddr.addr[i] = ethaddr->addr[i];
hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
}
while(i > 0) {
i--;
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
hdr->shwaddr.addr[i] = ethaddr->addr[i];
hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
}
hdr->hwtype = htons(HWTYPE_ETHERNET);
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
hdr->ethhdr.type = htons(ETHTYPE_ARP);
/* return ARP reply */
netif->linkoutput(netif, p);
/* we are not configured? */
} else if (netif->ip_addr.addr == 0) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored. "));
/* request was not directed to us */
} else {
/* { for_us == 0 and netif->ip_addr.addr != 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP request was not for us. "));
}
break;
case ARP_REPLY:
/* ARP reply. We already updated the ARP cache earlier. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply "));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
/* DHCP wants to know about ARP replies from any host with an
* IP address also offered to us by the DHCP server. We do not
* want to take a duplicate IP address on a single network.
* @todo How should we handle redundant (fail-over) interfaces?
* */
dhcp_arp_reply(netif, &sipaddr);
#endif
break;
default:
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F" ", htons(hdr->opcode)));
break;
}
/* free ARP packet */
pbuf_free(p);
p =NULL;
return NULL;
}
/* return ARP reply */
netif->linkoutput(netif, p);
/* we are not configured? */
} else if (netif->ip_addr.addr == 0) {
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored. "));
/* request was not directed to us */
} else {
/* { for_us == 0 and netif->ip_addr.addr != 0 } */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP request was not for us. "));
}
break;
case ARP_REPLY:
/* ARP reply. We already updated the ARP cache earlier. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply "));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
/* DHCP wants to know about ARP replies from any host with an
* IP address also offered to us by the DHCP server. We do not
* want to take a duplicate IP address on a single network.
* @todo How should we handle redundant (fail-over) interfaces?
* */
dhcp_arp_reply(netif, &sipaddr);
#endif
break;
default:
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F" ", htons(hdr->opcode)));
break;
}
/* free ARP packet */
pbuf_free(p);
p =NULL;
return NULL;
}