RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

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

3天內(nèi)不再提示

基于DWC_ether_qos的以太網(wǎng)驅(qū)動開發(fā)-LWIP的ICMP模塊介紹與PING收發(fā)測

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

本文轉(zhuǎn)自公眾號歡迎關(guān)注
https://mp.weixin.qq.com/s/6MTNop3zBKdQ-gabbWo63Q

一. 前言

ICMP即Internet Control Message Protocol因特網(wǎng)控制消息協(xié)議。

ICMP是網(wǎng)絡(luò)層協(xié)議,IP不可分割的一部分。

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

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

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

參考

RFC 792

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

二. ICMP消息格式

ICMP消息格式

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

圖片

我們這里只關(guān)注ICMP部分,ICMP由首部和數(shù)據(jù)兩部分組成,如下

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

Type和Code如下表

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

使用wirshark協(xié)助解析

圖片

圖片

三. LWIP中ICMP相關(guān)代碼分析

這里只看IPV4相關(guān)的,IPV6下也有對應(yīng)的實現(xiàn)。

ipv4/icmp.c

icmp.h

3.1調(diào)試打印

可以配置宏ICMP_DEBUG,使能調(diào)試打印,一遍跟蹤對應(yīng)的程序處理過程。

lwipopts.h中配置

#define ICMP_DEBUG LWIP_DBG_ON

3.2數(shù)據(jù)結(jié)構(gòu)

實現(xiàn)了以下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 */

定義了頭的數(shù)據(jù)結(jié)構(gòu)

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字節(jié)數(shù)據(jù)拆分成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輸入數(shù)據(jù)流

關(guān)鍵代碼是icmp_input

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

通過switch處理各種類型

switch (type) {


  case ICMP_ER:

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

case ICMP_ECHO:

如果是多播地址不響應(yīng)

然后檢查ICMP頭部至少要8字節(jié)。

然后檢查checksum

最后調(diào)用ip4_output_if發(fā)送響應(yīng)包。

3.4輸出數(shù)據(jù)流

icmp_dest_unreach

icmp_time_exceeded

都是調(diào)用

icmp_send_response

3.5發(fā)送PING

收到響應(yīng)進入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

發(fā)送ping可以裸機可以使用raw PCB,帶OS可以使用socket實現(xiàn)

詳見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地址打印顯示不對)

圖片

四. 總結(jié)

了解ICMP包的格式,了解LWIP發(fā)送ping和對堆ping請求響應(yīng)的過程。

審核編輯 黃宇

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

    關(guān)注

    40

    文章

    5419

    瀏覽量

    171590
  • ICMP
    +關(guān)注

    關(guān)注

    0

    文章

    52

    瀏覽量

    14923
  • Ping
    +關(guān)注

    關(guān)注

    0

    文章

    69

    瀏覽量

    15974
  • LwIP
    +關(guān)注

    關(guān)注

    2

    文章

    86

    瀏覽量

    27146
收藏 人收藏

    評論

    相關(guān)推薦

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-MAC幀格式介紹

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-MDIO驅(qū)動編寫與測試

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-MDIO驅(qū)動編寫與測試 一.前言
    的頭像 發(fā)表于 08-30 09:37 ?3734次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-MDIO<b class='flag-5'>驅(qū)動</b>編寫與測試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-描述符鏈表介紹

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-數(shù)據(jù)流驗證過程

    轉(zhuǎn)自公眾號歡迎關(guān)注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-數(shù)據(jù)流驗證過程
    的頭像 發(fā)表于 08-31 08:41 ?2007次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-數(shù)據(jù)流驗證過程

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-收發(fā)驅(qū)動編寫與調(diào)試

    本文轉(zhuǎn)自公眾號,歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-收發(fā)驅(qū)動編寫與調(diào)試 (
    的頭像 發(fā)表于 09-05 08:47 ?2316次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>收發(fā)</b><b class='flag-5'>驅(qū)動</b>編寫與調(diào)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-無OS環(huán)境移植LWIP

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的內(nèi)存池介紹

    本文轉(zhuǎn)自公眾號,歡迎關(guān)注 https://mp.weixin.qq.com/s/mBoGSf_u9edFF01U_OZT9g 一.前言 lwIP為基礎(chǔ)結(jié)構(gòu)提供了專用的內(nèi)存池管理,比如netconn
    的頭像 發(fā)表于 09-07 08:45 ?1715次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>的內(nèi)存池<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的堆管理介紹

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的堆管理介紹 (
    的頭像 發(fā)表于 09-08 08:40 ?1292次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>的堆管理<b class='flag-5'>介紹</b>

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的堆(內(nèi)存池)未對齊導(dǎo)致問題的案例分享

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 https://mp.weixin.qq.com/s/ErIa2ss2YZLGYbSwoJEzog 一.?前言 內(nèi)存未對齊訪問問題這個已經(jīng)是老生常談的問題了, 由于LWIP
    的頭像 發(fā)表于 09-09 08:44 ?1716次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>的堆(內(nèi)存池)未對齊導(dǎo)致問題的案例分享

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-RTOS環(huán)境移植LWIP與性能測試

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP在PC上進行開發(fā)調(diào)試

    本文轉(zhuǎn)自公眾號歡迎關(guān)注 基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP在PC上進行開發(fā)
    的頭像 發(fā)表于 09-11 08:40 ?1996次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-<b class='flag-5'>LWIP</b>在PC上進行<b class='flag-5'>開發(fā)</b>調(diào)試

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的定時器模塊詳解

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

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-LWIP的ARP模塊介紹

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

    設(shè)計軟件核心以太網(wǎng)服務(wù)質(zhì)量數(shù)據(jù)手冊免費下載

    本文描述Synopsys設(shè)計軟件核心以太網(wǎng)服務(wù)質(zhì)量DWC以太網(wǎng)QoS核心5.10A。DWC以太網(wǎng)
    發(fā)表于 10-23 08:00 ?16次下載
    設(shè)計軟件核心<b class='flag-5'>以太網(wǎng)</b>服務(wù)質(zhì)量數(shù)據(jù)手冊免費下載

    基于DWC_ether_qos以太網(wǎng)驅(qū)動開發(fā)-包過濾

    以太網(wǎng)上數(shù)據(jù)非常多,如果所有數(shù)據(jù)都接收交給軟件去處理軟件負載會非常重,所以一般只需要接收發(fā)給自己的數(shù)據(jù)即可
    的頭像 發(fā)表于 09-02 09:19 ?1745次閱讀
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>-包過濾
    RM新时代网站-首页