网络使用参考

Version 1.0


1. 概述

EMAC驱动路径:rtk/proj/sc/driver/sysdriver/emac/

LWIP路径:rtk/proj/sc/middleware/tcpip/


2. 配置

2.1. mak配置

在相应的product config中修改mak文件的配置,需要启用两个选项:CONFIG_EMAC_SUPPORT = TRUE编译EMAC驱动,CONFIG_SW_NET_SUPPORT = TRUE编译LWIP。


2.2. API 使用(socket 基本接口)

请参考 http://lwip.nongnu.org/2_1_x/group__if__api.html 下对socketAPI以及参数介绍。

#include "sockets.h"

#define AF_INET 2
#define SOCK_RAW 3
#define IP_PROTO_ICMP 1
#define PING_DATA_SIZE 32

static ip_addr_t ping_addr;
static int pinglen = 0;

static void ssn_ping_prepare_echo(struct icmp_echo_hdr *pecho, u16_t len)
{
  size_t i;
  size_t nlen = len - sizeof(struct icmp_echo_hdr);

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

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

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

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

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

  ssn_ping_prepare_echo(iecho, (u16_t)ping_size);

  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));
  }

  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 = 0;
  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(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);
      }

      CamOsPrintf("host is alive %d ms\n", (sys_now() - ping_time));
      return ;
    }
    fromlen = sizeof(from);
  }

  {
    CamOsPrintf("ping failed host is not alive\n");
  }
}
void dome_ping(char* szParam)
{
    char ip[20] = "127.0.0.1";
    int times = 1, s;
    int cnt;

    struct timeval timeout;
    timeout.tv_sec = PING_RCV_TIMEO/1000;
    timeout.tv_usec = (PING_RCV_TIMEO%1000)*1000;


    pinglen = 0;
    cnt = sscanfl( szParam, "%s %d %d", ip, &times,&pinglen);
    if(cnt == 0)
    {
        strcpy(ip, "192.168.1.133");//target IP
        pinglen = 0;
    }

    ip4_addr_set_u32(ip_2_ip4(&ping_addr), inet_addr(ip));

    if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0)
    {
        CamOsPrintf("__uartCmd_ping lwip_socket creat fail\n");
        return;
    }

    lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

    CamOsPrintf("Pinging: %u.%u.%u.%u\r\n",
            (unsigned char) ( ( htonl(ip_2_ip4(&ping_addr)->addr) >> 24 ) & 0xff ),
            (unsigned char) ( ( htonl(ip_2_ip4(&ping_addr)->addr) >> 16 ) & 0xff ),
            (unsigned char) ( ( htonl(ip_2_ip4(&ping_addr)->addr) >> 8 ) & 0xff ),
            (unsigned char) ( ( htonl(ip_2_ip4(&ping_addr)->addr) >> 0 ) & 0xff ));

    while (times-- > 0) {
        if(times == 0)
            pinglen = 0;
        else if(times == 1)
            pinglen = 18;
        else if(times == 2)
            pinglen = 32;
        ping_send(s,&ping_addr);
        ping_time = sys_now();
        ping_recv(s);

    }
    close(s);
}

3. 命令调试

当前支持如下ipconfigtftp命令简单测试网络功能,EMAC启用网络扫描会比较耗时,因此还要通过命令estart来启动。

3.1. ipconfig

在板端输入如下命令可配置网络:

ipconfig eth0 ip xxx.xxx.xxx.xxx
ipconfig eth0 mask xxx.xxx.xxx.xxx
ipconfig eth0 gw xxx.xxx.xxx.xxx
ipconfig eth0 hw xx:xx:xx:xx:xx:xx

板端测试方法:

SS-RTOS # estart
emac init g_rxdesc is 23ed1000
SS-RTOS # Auto-Negotiation...
Link Status Speed:100 Full-duplex:1

SS-RTOS # 
SS-RTOS # 
SS-RTOS # ipconfig
register device[1] [eth0]
SS-RTOS # ipconfig eth0 ip 169.254.172.252
IP Address =>  169.254.172.252 
SS-RTOS # ipconfig eth0 mask 255.255.0.0
Netmask =>  255.255.0.0
SS-RTOS # ipconfig eth0 gw 169.254.172.1
Gateway =>  169.254.172.1
SS-RTOS # ipconfig eth0 hw 00:84:16:00:00:01
HWaddr => 00:84:16:00:00:01
SS-RTOS # ping 169.254.172.131
host is alive 39 ms
SS-RTOS # 
SS-RTOS # ping 169.254.172.130
ping failed host is not alive
SS-RTOS # 

Windows下使用WIN+R输入cmd呼出dos:

C:\Users\test>ipconfig

以太网适配器 以太网 2:

   连接特定的 DNS 后缀 . . . . . . . :
   本地链接 IPv6 地址. . . . . . . . : fe80::a70e:88a0:7a75:8d9d%7
   自动配置 IPv4 地址  . . . . . . . : 169.254.172.131
   子网掩码  . . . . . . . . . . . . : 255.255.0.0
   默认网关. . . . . . . . . . . . . :

C:\Users\test>ping 169.254.172.252

正在 Ping 169.254.172.252 具有 32 字节的数据:
来自 169.254.172.252 的回复: 字节=32 时间=28ms TTL=255
来自 169.254.172.252 的回复: 字节=32 时间=15ms TTL=255
来自 169.254.172.252 的回复: 字节=32 时间=33ms TTL=255
来自 169.254.172.252 的回复: 字节=32 时间=19ms TTL=255

169.254.172.252 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 15ms,最长 = 33ms,平均 = 23ms

板端和PC能够互相ping通。

3.2. tftp

PC需要使用tftpd32软件作为server,在板端使用命令tftp 0x21000000 boot.bin

SS-RTOS # estart
emac init g_rxdesc is 23ed1000
SS-RTOS # 
SS-RTOS # 
SS-RTOS # Auto-Negotiation...
Link Status Speed:100 Full-duplex:1

SS-RTOS # 
SS-RTOS # 
SS-RTOS # ipconfig eth0 ip 169.254.172.252; ipconfig eth0 mask 255.255.0.0;
IP Address =>  169.254.172.252 
Netmask =>  255.255.0.0
SS-RTOS #  ipconfig eth0 gw 169.254.172.1; ipconfig eth0 hw 00:84:16:00:00:01;
Gateway =>  169.254.172.1
HWaddr => 00:84:16:00:00:01
SS-RTOS # ipconfig eth0
IP addr :  169.254.172.252 
Netmask :  255.255.0.0
Gateway :  169.254.172.1
HWaddr  :  00:84:16:00:00:01
Rx pack:51 bytes:6160 errors:0 dropped:0 length_err:0 over_err:0 crc_err:0 frame_err:0 fifo err:0 miss_err:0
Tx pack:1 bytes:42 errors:0 dropped:0 aborted_err:0 carrier_err:0 fifo_err:0 heartbeat_err:0 window_err:0
multicast:0 collisions:0 rx_compressed:0 tx_compressed:0
SS-RTOS # ping 169.254.172.131
host is alive 40 ms
SS-RTOS # 
SS-RTOS # setenv serverip 169.254.172.131; saveenv;
SS-RTOS # 
SS-RTOS # tftp 0x21000000 boot.bin
TFTP from server 169.254.172.131; our IP address is 169.254.172.252
Filename boot.bin
Load address: 0x21000000
Loading:########
    130.9 KiB/s
done
Bytes transferred = 286720 (46000 hex)
SS-RTOS # 

可以从日志中看到板端RTOS成功从TFTP Server读取文件到内存地址0x21000000处。