网络使用参考
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, ×,&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. 命令调试¶
当前支持如下ipconfig
、tftp
命令简单测试网络功能,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处。