<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于DWC_ether_qos的以太網驅動開發-LWIP的ICMP模塊介紹與PING收發測

嵌入式USB開發 ? 來源:嵌入式USB開發 ? 作者:嵌入式USB開發 ? 2023-09-18 17:51 ? 次閱讀

本文轉自公眾號歡迎關注
https://mp.weixin.qq.com/s/6MTNop3zBKdQ-gabbWo63Q

一. 前言

ICMP即Internet Control Message Protocol因特網控制消息協議。

ICMP是網絡層協議,IP不可分割的一部分。

ICMP用于報告數據報處理中的錯誤,比如以下情況下時發送ICMP消息:當數據報無法到達其目的地時,當網關沒有轉發數據報的緩沖能力時,以及當網關可以指示主機在較短的路由上發送數據時。

互聯網協議的設計并不是絕對可靠的。ICMP這些控制消息的目的是提供有關通信環境中問題的反饋,而不是使IP可靠。不能確保數據報的傳遞或控制消息的返回,一些數據報可能無法送達時也沒有任何丟失報告。如果需要可靠的通信,則使用IP的更高級別協議必須實現其自己的可靠性程序。

ICMP消息通常報告數據報處理中的錯誤,且不發送關于ICMP消息的ICMP消息,否則消息會無限遞歸。此外,ICMP消息只發送關于處理分段數據報的零分段時的錯誤。(片段零的片段offeset等于零)。

參考

RFC 792

https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml

二. ICMP消息格式

ICMP消息格式

從 ICMP 的報文格式來說,ICMP 是 IP 的上層協議,他是在IP報的基礎上再添加ICMP報格式。但是 ICMP 是分擔了 IP 的一部分功能。所以,他也被認為是與 IP 同層的協議。

圖片

我們這里只關注ICMP部分,ICMP由首部和數據兩部分組成,如下

區域類型Type代碼Code校驗和Checksum
字節大小112
區域首部數據,根據類型不一樣而不一樣,對于ping拆為了16位的ID和16位的序列號
字節大小4
區域ICMP數據部分
字節大小類型不同長度不同

Type和Code如下表

類型TYPE代碼CODE**用途描述 Description**查詢類Query差錯類Error
00Echo Reply——回顯應答(Ping應答)x
30Network Unreachable——網絡不可達x
31Host Unreachable——主機不可達x
32Protocol Unreachable——協議不可達x
33Port Unreachable——端口不可達x
34Fragmentation needed but no frag. bit set——需要進行分片但設置不分片比特x
35Source routing failed——源站選路失敗x
36Destination network unknown——目的網絡未知x
37Destination host unknown——目的主機未知x
38Source host isolated (obsolete)——源主機被隔離(作廢不用)x
39Destination network administratively prohibited——目的網絡被強制禁止x
310Destination host administratively prohibited——目的主機被強制禁止x
311Network unreachable for TOS——由于服務類型TOS,網絡不可達x
312Host unreachable for TOS——由于服務類型TOS,主機不可達x
313Communication administratively prohibited by filtering——由于過濾,通信被強制禁止x
314Host precedence violation——主機越權x
315Precedence cutoff in effect——優先中止生效x
40Source quench——源端被關閉(基本流控制)
50Redirect for network——對網絡重定向
51Redirect for host——對主機重定向
52Redirect for TOS and network——對服務類型和網絡重定向
53Redirect for TOS and host——對服務類型和主機重定向
80Echo request——回顯請求(Ping請求)x
90Router advertisement——路由器通告
100Route solicitation——路由器請求
110TTL equals 0 during transit——傳輸期間生存時間為0x
111TTL equals 0 during reassembly——在數據報組裝期間生存時間為0x
120IP header bad (catchall error)——壞的IP首部(包括各種差錯)x
121Required options missing——缺少必需的選項x
130Timestamp request (obsolete)——時間戳請求(作廢不用)x
14Timestamp reply (obsolete)——時間戳應答(作廢不用)x
150Information request (obsolete)——信息請求(作廢不用)x
160Information reply (obsolete)——信息應答(作廢不用)x
170Address mask request——地址掩碼請求x
180Address mask reply——地址掩碼應答

使用wirshark協助解析

圖片

圖片

三. LWIP中ICMP相關代碼分析

這里只看IPV4相關的,IPV6下也有對應的實現。

ipv4/icmp.c

icmp.h

3.1調試打印

可以配置宏ICMP_DEBUG,使能調試打印,一遍跟蹤對應的程序處理過程。

lwipopts.h中配置

#define ICMP_DEBUG LWIP_DBG_ON

3.2數據結構

實現了以下Type

#define ICMP_ER   0    /* echo reply */


#define ICMP_DUR  3    /* destination unreachable */


#define ICMP_SQ   4    /* source quench */


#define ICMP_RD   5    /* redirect */


#define ICMP_ECHO 8    /* echo */


#define ICMP_TE  11    /* time exceeded */


#define ICMP_PP  12    /* parameter problem */


#define ICMP_TS  13    /* timestamp */


#define ICMP_TSR 14    /* timestamp reply */


#define ICMP_IRQ 15    /* information request */


#define ICMP_IR  16    /* information reply */


#define ICMP_AM  17    /* address mask request */


#define ICMP_AMR 18    /* address mask reply */

定義了頭的數據結構

struct icmp_hdr {


PACK_STRUCT_FLD_8(u8_t type);


PACK_STRUCT_FLD_8(u8_t code);


PACK_STRUCT_FIELD(u16_t chksum);


PACK_STRUCT_FIELD(u32_t data);


} PACK_STRUCT_STRUCT;

如果四echo則,ICMP首部后面4字節數據拆分成id和序列號

struct icmp_echo_hdr {


PACK_STRUCT_FLD_8(u8_t type);


PACK_STRUCT_FLD_8(u8_t code);


PACK_STRUCT_FIELD(u16_t chksum);


PACK_STRUCT_FIELD(u16_t id);


PACK_STRUCT_FIELD(u16_t seqno);


} PACK_STRUCT_STRUCT;

3.3輸入數據流

關鍵代碼是icmp_input

ethernet_input->Type=0x0800 ip4_input-> Protocol=0x01 icmp_input

通過switch處理各種類型

switch (type) {


  case ICMP_ER:

比如對于收到別人的ping請求就是進入

case ICMP_ECHO:

如果是多播地址不響應

然后檢查ICMP頭部至少要8字節。

然后檢查checksum

最后調用ip4_output_if發送響應包。

3.4輸出數據流

icmp_dest_unreach

icmp_time_exceeded

都是調用

icmp_send_response

3.5發送PING

收到響應進入icmp_input的

case ICMP_ER:


    /* This is OK, echo reply might have been parsed by a raw PCB


       (as obviously, an echo request has been sent, too). */


    MIB2_STATS_INC(mib2.icmpinechoreps);


    break

發送ping可以裸機可以使用raw PCB,帶OS可以使用socket實現

詳見ping.c/h

#include "lwip/opt.h"


#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */


#include "ping.h"


#include "lwip/mem.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/timeouts.h"
#include "lwip/inet_chksum.h"
#include "lwip/prot/ip4.h"


#if PING_USE_SOCKETS
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include < string.h >
#endif /* PING_USE_SOCKETS */




/**
 * PING_DEBUG: Enable debugging for PING.
 */
#ifndef PING_DEBUG
#define PING_DEBUG     LWIP_DBG_ON
#endif


/** ping receive timeout - in milliseconds */
#ifndef PING_RCV_TIMEO
#define PING_RCV_TIMEO 1000
#endif


/** ping delay - in milliseconds */
#ifndef PING_DELAY
#define PING_DELAY     1000
#endif


/** ping identifier - must fit on a u16_t */
#ifndef PING_ID
#define PING_ID        0xAFAF
#endif


/** ping additional data size to include in the packet */
#ifndef PING_DATA_SIZE
#define PING_DATA_SIZE 32
#endif


/** ping result action - no default action */
#ifndef PING_RESULT
#define PING_RESULT(ping_ok)
#endif


/* ping variables */
static const ip_addr_t* ping_target;
static u16_t ping_seq_num;
#ifdef LWIP_DEBUG
static u32_t ping_time;
#endif /* LWIP_DEBUG */
#if !PING_USE_SOCKETS
static struct raw_pcb *ping_pcb;
#endif /* PING_USE_SOCKETS */


/** Prepare a echo ICMP request */
static void
ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
{
  size_t i;
  size_t data_len = len - sizeof(struct icmp_echo_hdr);


  ICMPH_TYPE_SET(iecho, ICMP_ECHO);
  ICMPH_CODE_SET(iecho, 0);
  iecho- >chksum = 0;
  iecho- >id     = PING_ID;
  iecho- >seqno  = lwip_htons(++ping_seq_num);


  /* fill the additional data buffer with some data */
  for(i = 0; i < data_len; i++) {
    ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
  }


  iecho- >chksum = inet_chksum(iecho, len);
}


#if PING_USE_SOCKETS


/* Ping using the socket ip */
static err_t
ping_send(int s, const ip_addr_t *addr)
{
  int err;
  struct icmp_echo_hdr *iecho;
  struct sockaddr_storage to;
  size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
  LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);


#if LWIP_IPV6
  if(IP_IS_V6(addr) && !ip6_addr_isipv4mappedipv6(ip_2_ip6(addr))) {
    /* todo: support ICMP6 echo */
    return ERR_VAL;
  }
#endif /* LWIP_IPV6 */


  iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
  if (!iecho) {
    return ERR_MEM;
  }


  ping_prepare_echo(iecho, (u16_t)ping_size);


#if LWIP_IPV4
  if(IP_IS_V4(addr)) {
    struct sockaddr_in *to4 = (struct sockaddr_in*)&to;
    to4- >sin_len    = sizeof(*to4);
    to4- >sin_family = AF_INET;
    inet_addr_from_ip4addr(&to4- >sin_addr, ip_2_ip4(addr));
  }
#endif /* LWIP_IPV4 */


#if LWIP_IPV6
  if(IP_IS_V6(addr)) {
    struct sockaddr_in6 *to6 = (struct sockaddr_in6*)&to;
    to6- >sin6_len    = sizeof(*to6);
    to6- >sin6_family = AF_INET6;
    inet6_addr_from_ip6addr(&to6- >sin6_addr, ip_2_ip6(addr));
  }
#endif /* LWIP_IPV6 */


  err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));


  mem_free(iecho);


  return (err ? ERR_OK : ERR_VAL);
}


static void
ping_recv(int s)
{
  char buf[64];
  int len;
  struct sockaddr_storage from;
  int fromlen = sizeof(from);


  while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
    if (len >= (int)(sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
      ip_addr_t fromaddr;
      memset(&fromaddr, 0, sizeof(fromaddr));


#if LWIP_IPV4
      if(from.ss_family == AF_INET) {
        struct sockaddr_in *from4 = (struct sockaddr_in*)&from;
        inet_addr_to_ip4addr(ip_2_ip4(&fromaddr), &from4- >sin_addr);
        IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V4);
      }
#endif /* LWIP_IPV4 */


#if LWIP_IPV6
      if(from.ss_family == AF_INET6) {
        struct sockaddr_in6 *from6 = (struct sockaddr_in6*)&from;
        inet6_addr_to_ip6addr(ip_2_ip6(&fromaddr), &from6- >sin6_addr);
        IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V6);
      }
#endif /* LWIP_IPV6 */


      LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
      ip_addr_debug_print_val(PING_DEBUG, fromaddr);
      LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" msn", (sys_now() - ping_time)));


      /* todo: support ICMP6 echo */
#if LWIP_IPV4
      if (IP_IS_V4_VAL(fromaddr)) {
        struct ip_hdr *iphdr;
        struct icmp_echo_hdr *iecho;


        iphdr = (struct ip_hdr *)buf;
        iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
        if ((iecho- >id == PING_ID) && (iecho- >seqno == lwip_htons(ping_seq_num))) {
          /* do some ping result processing */
          PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER));
          return;
        } else {
          LWIP_DEBUGF( PING_DEBUG, ("ping: dropn"));
        }
      }
#endif /* LWIP_IPV4 */
    }
    fromlen = sizeof(from);
  }


  if (len == 0) {
    LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %"U32_F" ms - timeoutn", (sys_now()-ping_time)));
  }


  /* do some ping result processing */
  PING_RESULT(0);
}


static void
ping_thread(void *arg)
{
  int s;
  int ret;


#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
  int timeout = PING_RCV_TIMEO;
#else
  struct timeval timeout;
  timeout.tv_sec = PING_RCV_TIMEO/1000;
  timeout.tv_usec = (PING_RCV_TIMEO%1000)*1000;
#endif
  LWIP_UNUSED_ARG(arg);


#if LWIP_IPV6
  if(IP_IS_V4(ping_target) || ip6_addr_isipv4mappedipv6(ip_2_ip6(ping_target))) {
    s = lwip_socket(AF_INET6, SOCK_RAW, IP_PROTO_ICMP);
  } else {
    s = lwip_socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6);
  }
#else
  s = lwip_socket(AF_INET,  SOCK_RAW, IP_PROTO_ICMP);
#endif
  if (s < 0) {
    return;
  }


  ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  LWIP_ASSERT("setting receive timeout failed", ret == 0);
  LWIP_UNUSED_ARG(ret);


  while (1) {
    if (ping_send(s, ping_target) == ERR_OK) {
      LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
      ip_addr_debug_print(PING_DEBUG, ping_target);
      LWIP_DEBUGF( PING_DEBUG, ("n"));


#ifdef LWIP_DEBUG
      ping_time = sys_now();
#endif /* LWIP_DEBUG */
      ping_recv(s);
    } else {
      LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
      ip_addr_debug_print(PING_DEBUG, ping_target);
      LWIP_DEBUGF( PING_DEBUG, (" - errorn"));
    }
    sys_msleep(PING_DELAY);
  }
}


#else /* PING_USE_SOCKETS */


/* Ping using the raw ip */
static u8_t
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
{
  struct icmp_echo_hdr *iecho;
  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(pcb);
  LWIP_UNUSED_ARG(addr);
  LWIP_ASSERT("p != NULL", p != NULL);


  if ((p- >tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
      pbuf_remove_header(p, PBUF_IP_HLEN) == 0) {
    iecho = (struct icmp_echo_hdr *)p- >payload;


    if ((iecho- >id == PING_ID) && (iecho- >seqno == lwip_htons(ping_seq_num))) {
      LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
      ip_addr_debug_print(PING_DEBUG, addr);
      LWIP_DEBUGF( PING_DEBUG, (" %"U32_F" msn", (sys_now()-ping_time)));


      /* do some ping result processing */
      PING_RESULT(1);
      pbuf_free(p);
      return 1; /* eat the packet */
    }
    /* not eaten, restore original packet */
    pbuf_add_header(p, PBUF_IP_HLEN);
  }


  return 0; /* don't eat the packet */
}


static void
ping_send(struct raw_pcb *raw, const ip_addr_t *addr)
{
  struct pbuf *p;
  struct icmp_echo_hdr *iecho;
  size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;


  LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
  ip_addr_debug_print(PING_DEBUG, addr);
  LWIP_DEBUGF( PING_DEBUG, ("n"));
  LWIP_ASSERT("ping_size <= 0xffff", ping_size <= 0xffff);


  p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
  if (!p) {
    return;
  }
  if ((p- >len == p- >tot_len) && (p- >next == NULL)) {
    iecho = (struct icmp_echo_hdr *)p- >payload;


    ping_prepare_echo(iecho, (u16_t)ping_size);


    raw_sendto(raw, p, addr);
#ifdef LWIP_DEBUG
    ping_time = sys_now();
#endif /* LWIP_DEBUG */
  }
  pbuf_free(p);
}


static void
ping_timeout(void *arg)
{
  struct raw_pcb *pcb = (struct raw_pcb*)arg;


  LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL);


  ping_send(pcb, ping_target);


  sys_timeout(PING_DELAY, ping_timeout, pcb);
}


static void
ping_raw_init(void)
{
  ping_pcb = raw_new(IP_PROTO_ICMP);
  LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);


  raw_recv(ping_pcb, ping_recv, NULL);
  raw_bind(ping_pcb, IP_ADDR_ANY);
  sys_timeout(PING_DELAY, ping_timeout, ping_pcb);
}


void
ping_send_now(void)
{
  LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);
  ping_send(ping_pcb, ping_target);
}


#endif /* PING_USE_SOCKETS */


void
ping_init(const ip_addr_t* ping_addr)
{
  ping_target = ping_addr;


#if PING_USE_SOCKETS
  sys_thread_new("ping_thread", ping_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
#else /* PING_USE_SOCKETS */
  ping_raw_init();
#endif /* PING_USE_SOCKETS */
}


#endif /* LWIP_RAW */
#ifndef LWIP_PING_H
#define LWIP_PING_H


#include "lwip/ip_addr.h"


/**
 * PING_USE_SOCKETS: Set to 1 to use sockets, otherwise the raw api is used
 */
#ifndef PING_USE_SOCKETS
#define PING_USE_SOCKETS    LWIP_SOCKET
#endif


void ping_init(const ip_addr_t* ping_addr);


#if !PING_USE_SOCKETS
void ping_send_now(void);
#endif /* !PING_USE_SOCKETS */


#endif /* LWIP_PING_H */

如下是帶OS的測試

ip_addr_t ping_addr;


  IP4_ADDR(&ping_addr, 192, 168, 1, 9);


  ping_init(&ping_addr);

打印如下,(這里printf不支持某些格式所以IP地址打印顯示不對)

圖片

四. 總結

了解ICMP包的格式,了解LWIP發送ping和對堆ping請求響應的過程。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 以太網
    +關注

    關注

    40

    文章

    5145

    瀏覽量

    167024
  • ICMP
    +關注

    關注

    0

    文章

    50

    瀏覽量

    14841
  • Ping
    +關注

    關注

    0

    文章

    67

    瀏覽量

    15840
  • LwIP
    +關注

    關注

    2

    文章

    82

    瀏覽量

    26738
收藏 人收藏

    評論

    相關推薦

    基于DWC_ether_qos以太網驅動開發-MAC幀格式介紹

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-MAC幀格式介紹 (qq.com) 一.前言 ? 在
    的頭像 發表于 08-30 09:23 ?1416次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-MAC幀格式<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-MDIO驅動編寫與測試

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-MDIO驅動編寫與測試 一.前言
    的頭像 發表于 08-30 09:37 ?2667次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-MDIO<b class='flag-5'>驅動</b>編寫與測試

    基于DWC_ether_qos以太網驅動開發-描述符鏈表介紹

    本文轉自公眾號歡迎關注 一.描述符概述 1.0 前言 對于DWC Ethernet QoS驅動的編寫來說,初始化完成之后,核心操作就是DMA的描述符鏈表配置(linked list
    的頭像 發表于 08-30 09:39 ?3113次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-描述符鏈表<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-數據流驗證過程

    轉自公眾號歡迎關注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太網驅動開發-數據流驗證過程
    的頭像 發表于 08-31 08:41 ?1313次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-數據流驗證過程

    基于DWC_ether_qos以太網驅動開發-收發驅動編寫與調試

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-收發驅動編寫與調試 (
    的頭像 發表于 09-05 08:47 ?1557次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>收發</b><b class='flag-5'>驅動</b>編寫與調試

    基于DWC_ether_qos以太網驅動開發-無OS環境移植LWIP

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-無OS環境移植LWIP (qq.com) https://mp.we
    的頭像 發表于 09-06 08:40 ?968次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-無OS環境移植<b class='flag-5'>LWIP</b>

    基于DWC_ether_qos以太網驅動開發-LWIP的內存池介紹

    本文轉自公眾號,歡迎關注 https://mp.weixin.qq.com/s/mBoGSf_u9edFF01U_OZT9g 一.前言 lwIP為基礎結構提供了專用的內存池管理,比如netconn
    的頭像 發表于 09-07 08:45 ?1004次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的內存池<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-LWIP的堆管理介紹

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-LWIP的堆管理介紹 (
    的頭像 發表于 09-08 08:40 ?828次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的堆管理<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網驅動開發-RTOS環境移植LWIP與性能測試

    本文轉自公眾號,歡迎關注 基于DWC_ether_qos以太網驅動開發-RTOS環境移植LWIP與性能測試 (qq.com) https:
    的頭像 發表于 09-11 11:20 ?1312次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-RTOS環境移植<b class='flag-5'>LWIP</b>與性能測試

    基于DWC_ether_qos以太網驅動開發-LWIP在PC上進行開發調試

    本文轉自公眾號歡迎關注 基于DWC_ether_qos以太網驅動開發-LWIP在PC上進行開發
    的頭像 發表于 09-11 08:40 ?1357次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>在PC上進行<b class='flag-5'>開發</b>調試

    基于DWC_ether_qos以太網驅動開發-LWIP的定時器模塊詳解

    一. 前言 LWIP的定時器模塊,實現了通用的軟件定時器,用于內部的周期事件處理,比如arp,tcp的超時等,用戶也可以使用。這一篇來分析該模塊的實現。 二.代碼分析 2.1源碼 源碼
    的頭像 發表于 09-18 09:33 ?1031次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的定時器<b class='flag-5'>模塊</b>詳解

    基于DWC_ether_qos以太網驅動開發-LWIP的ARP模塊介紹

    TCP/IP通訊第一步需要先調通ARP,否則TCP/IP包都不知道MAC地址要發給誰。這一篇來基于LWIP的ARP實現進行相關的分析。
    的頭像 發表于 09-18 09:34 ?1204次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-<b class='flag-5'>LWIP</b>的ARP<b class='flag-5'>模塊</b><b class='flag-5'>介紹</b>

    設計軟件核心以太網服務質量數據手冊免費下載

    本文描述Synopsys設計軟件核心以太網服務質量DWC以太網QoS核心5.10A。DWC以太網
    發表于 10-23 08:00 ?15次下載
    設計軟件核心<b class='flag-5'>以太網</b>服務質量數據手冊免費下載

    基于DWC_ether_qos以太網驅動開發-包過濾

    以太網上數據非常多,如果所有數據都接收交給軟件去處理軟件負載會非常重,所以一般只需要接收發給自己的數據即可
    的頭像 發表于 09-02 09:19 ?1014次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-包過濾

    基于DWC_ether_qos以太網驅動開發-軟復位介紹與問題案例

    一般模塊都會有軟復位的功能,軟復位在驅動編寫中很重要。一般初始化時執行軟復位使得模塊進入確定的初始狀態以提高可靠性,異常時也可以重新初始化來恢復,所以軟復位在驅動中一般是必須要做的動作
    的頭像 發表于 09-02 09:17 ?998次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>-軟復位<b class='flag-5'>介紹</b>與問題案例
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>