implementation of ethernet and ARP (not completely working yet, hangs on received ARP request)
Stefan Schuermans

Stefan Schuermans commited on 2012-03-17 01:03:19
Showing 14 changed files, with 546 additions and 109 deletions.

... ...
@@ -15,7 +15,7 @@
15 15
          </top_modules>
16 16
       </db_ref>
17 17
    </db_ref_list>
18
-   <WVObjectSize size="13" />
18
+   <WVObjectSize size="19" />
19 19
    <wvobject fp_name="/e_testbed/s_clk" type="logic" db_ref_id="1">
20 20
       <obj_property name="ElementShortName">s_clk</obj_property>
21 21
       <obj_property name="ObjectShortName">s_clk</obj_property>
... ...
@@ -74,4 +74,34 @@
74 74
       <obj_property name="ObjectShortName">i_instr_data[31:0]</obj_property>
75 75
       <obj_property name="Radix">HEXRADIX</obj_property>
76 76
    </wvobject>
77
+   <wvobject fp_name="/e_testbed/system/eth/r_rx_start" type="array" db_ref_id="1">
78
+      <obj_property name="ElementShortName">r_rx_start[31:0]</obj_property>
79
+      <obj_property name="ObjectShortName">r_rx_start[31:0]</obj_property>
80
+      <obj_property name="Radix">HEXRADIX</obj_property>
81
+   </wvobject>
82
+   <wvobject fp_name="/e_testbed/system/eth/r_rx_cur" type="array" db_ref_id="1">
83
+      <obj_property name="ElementShortName">r_rx_cur[31:0]</obj_property>
84
+      <obj_property name="ObjectShortName">r_rx_cur[31:0]</obj_property>
85
+      <obj_property name="Radix">HEXRADIX</obj_property>
86
+   </wvobject>
87
+   <wvobject fp_name="/e_testbed/system/eth/r_rx_size" type="array" db_ref_id="1">
88
+      <obj_property name="ElementShortName">r_rx_size[31:0]</obj_property>
89
+      <obj_property name="ObjectShortName">r_rx_size[31:0]</obj_property>
90
+      <obj_property name="Radix">HEXRADIX</obj_property>
91
+   </wvobject>
92
+   <wvobject fp_name="/e_testbed/system/eth/r_rx_end" type="array" db_ref_id="1">
93
+      <obj_property name="ElementShortName">r_rx_end[31:0]</obj_property>
94
+      <obj_property name="ObjectShortName">r_rx_end[31:0]</obj_property>
95
+      <obj_property name="Radix">HEXRADIX</obj_property>
96
+   </wvobject>
97
+   <wvobject fp_name="/e_testbed/system/eth/r_rx_new_start" type="array" db_ref_id="1">
98
+      <obj_property name="ElementShortName">r_rx_new_start[31:0]</obj_property>
99
+      <obj_property name="ObjectShortName">r_rx_new_start[31:0]</obj_property>
100
+      <obj_property name="Radix">HEXRADIX</obj_property>
101
+   </wvobject>
102
+   <wvobject fp_name="/e_testbed/system/eth/r_rx_new_end" type="array" db_ref_id="1">
103
+      <obj_property name="ElementShortName">r_rx_new_end[31:0]</obj_property>
104
+      <obj_property name="ObjectShortName">r_rx_new_end[31:0]</obj_property>
105
+      <obj_property name="Radix">HEXRADIX</obj_property>
106
+   </wvobject>
77 107
 </wave_config>
... ...
@@ -1,4 +1,4 @@
1
-SRCS=cyc_cnt.c eth.c lcd.c leds.c main.c switches.c uart.c
1
+SRCS=$(wildcard *.c)
2 2
 
3 3
 PERL=perl
4 4
 CC=mipsel-elf-gcc
... ...
@@ -0,0 +1,227 @@
1
+#include "arp.h"
2
+#include "config.h"
3
+#include "ethernet.h"
4
+// TODO #include "ip.h"
5
+#include "macros.h"
6
+#include "nethelp.h"
7
+
8
+// timing parameters
9
+#define ARP_TICKS_MAX        (150) /**< maximum age of ARP table entries
10
+                                        (in 200ms steps) */
11
+#define ARP_NO_MAC_TICKS_MAX  (50) /**< maximum age of ARP table entries
12
+                                        without MAC (in 200ms steps) */
13
+#define ARP_RETRY_TICKS        (8) /**< time after which to retry ARP query
14
+                                        (must be power of 2, in 200ms steps) */
15
+
16
+/// ARP table
17
+#define ARP_TAB_FLAG_IN_USE (1)
18
+#define ARP_TAB_FLAG_MAC_OK (2)
19
+struct arp_table
20
+{
21
+  unsigned char flags; /// flags - see constants
22
+  unsigned char ticks; /// age of entry in 200ms steps
23
+  unsigned char mac[6];
24
+  unsigned char ip[4];
25
+} arp_tab[12];
26
+
27
+/**
28
+ * @brief send an ARP request
29
+ * @param[in] ip IP address to query MAC for
30
+ */
31
+static void arp_send_request(unsigned char ip[4])
32
+{
33
+  struct arp_packet arp_request;
34
+
35
+  // build ARP request
36
+  arp_request.arp_hdr.hw_type = htons(0x0001); // ethernet
37
+  arp_request.arp_hdr.proto_type = htons(0x0800); // IP
38
+  arp_request.arp_hdr.hw_len = 0x06; // length of a MAC address
39
+  arp_request.arp_hdr.proto_len = 0x04; // length of an IP address
40
+  arp_request.arp_hdr.op = htons(0x0001); // ARP request
41
+  mac_cpy(arp_request.arp_hdr.src_mac, config_mac.mac); // own MAC
42
+  ip_cpy(arp_request.arp_hdr.src_ip, config_ip.ip); // own IP
43
+  mac_cpy(arp_request.arp_hdr.dest_mac,
44
+          "\xFF\xFF\xFF\xFF\xFF\xFF"); // broadcast MAC
45
+  ip_cpy(arp_request.arp_hdr.dest_ip, ip); // requested IP
46
+
47
+  // send ARP request
48
+  mac_cpy(arp_request.eth_hdr.dest, arp_request.arp_hdr.dest_mac);
49
+  arp_request.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
50
+  ethernet_send(&arp_request, sizeof(arp_request));
51
+}
52
+
53
+/// initialize
54
+/* extern */ void arp_init(void)
55
+{
56
+  unsigned int i;
57
+
58
+  // empty ARP table
59
+  for (i = 0; i < count(arp_tab); ++i)
60
+    arp_tab[i].flags = 0;
61
+}
62
+
63
+/// tick procedure - call every 200ms
64
+/* extern */ void arp_tick200(void)
65
+{
66
+  unsigned int i;
67
+
68
+  // increase age of ARP table entires and remove timed out ones
69
+  for (i = 0; i < count(arp_tab); ++i) {
70
+    // entry in use
71
+    if (arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) {
72
+      arp_tab[i].ticks++; // increase age
73
+      // entry has a MAC
74
+      if (arp_tab[i].flags & ARP_TAB_FLAG_MAC_OK) {
75
+        if (arp_tab[i].ticks > ARP_TICKS_MAX) // too old
76
+          arp_tab[i].flags = 0; // remove entry
77
+      }
78
+      // entry does not have a MAC
79
+      else {
80
+        if (arp_tab[i].ticks > ARP_NO_MAC_TICKS_MAX) // too old
81
+          arp_tab[i].flags = 0; // remove entry
82
+        else if ((arp_tab[i].ticks & (ARP_RETRY_TICKS - 1)) == 0) // re-request
83
+          arp_send_request(arp_tab[i].ip);
84
+      }
85
+    }
86
+  }
87
+}
88
+
89
+/**
90
+ * @brief process a received ARP packet
91
+ * @param[in] ptr pointer to data of packet
92
+ * @param[in] sz size of packet
93
+ */
94
+/* extern */ void arp_recv(void *ptr, unsigned int sz)
95
+{
96
+  struct arp_packet *arp_pack;
97
+
98
+  // packet too short
99
+  if (sz < sizeof(struct arp_packet))
100
+    return;
101
+
102
+  arp_pack = (struct arp_packet *)ptr;
103
+
104
+  // not IP over ethernet
105
+  if (arp_pack->arp_hdr.hw_type != htons(0x0001) || // ethernet
106
+      arp_pack->arp_hdr.proto_type != htons(0x0800) || // IP
107
+      arp_pack->arp_hdr.hw_len != 0x06 || // length of a MAC address
108
+      arp_pack->arp_hdr.proto_len != 0x04) // length of an IP address
109
+    // we do not support other protocols than IP over ethernet
110
+    return;
111
+
112
+  // source MAC is broadcast MAC -> broken packet / attac -> get lost
113
+  if (mac_eq(arp_pack->arp_hdr.src_mac, "\xFF\xFF\xFF\xFF\xFF\xFF"))
114
+    return;
115
+
116
+  // ARP request for own IP address
117
+  if (arp_pack->arp_hdr.op == htons(0x0001) && // ARP request
118
+      ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
119
+    struct arp_packet arp_reply;
120
+
121
+    // build ARP reply
122
+    arp_reply.arp_hdr.hw_type = htons(0x0001); // ethernet
123
+    arp_reply.arp_hdr.proto_type = htons(0x0800); // IP
124
+    arp_reply.arp_hdr.hw_len = 0x06; // length of a MAC address
125
+    arp_reply.arp_hdr.proto_len = 0x04; // length of an IP address
126
+    arp_reply.arp_hdr.op = htons(0x0002); // ARP reply
127
+    mac_cpy(arp_reply.arp_hdr.src_mac, config_mac.mac); // own MAC
128
+    ip_cpy(arp_reply.arp_hdr.src_ip, config_ip.ip); // own IP
129
+    mac_cpy(arp_reply.arp_hdr.dest_mac,
130
+            arp_pack->arp_hdr.src_mac); // requestor's MAC
131
+    ip_cpy(arp_reply.arp_hdr.dest_ip,
132
+           arp_pack->arp_hdr.src_ip); // requestor's IP
133
+
134
+    // send ARP reply
135
+    mac_cpy(arp_reply.eth_hdr.dest,
136
+            arp_reply.arp_hdr.dest_mac); // ethernet destination address
137
+    arp_reply.eth_hdr.type = htons(0x0806); // ethernet packet type: ARP
138
+    ethernet_send(&arp_reply, sizeof(arp_reply));
139
+
140
+    return;
141
+  }
142
+
143
+  // ARP reply to own MAC address and own IP address
144
+  if (arp_pack->arp_hdr.op == htons(0x0002) && // ARP reply
145
+      mac_eq(arp_pack->arp_hdr.dest_mac, config_mac.mac) && // own MAC address
146
+      ip_eq(arp_pack->arp_hdr.dest_ip, config_ip.ip)) { // own IP address
147
+    unsigned int i;
148
+
149
+    // search IP in ARP tabale
150
+    for (i = 0; i < count(arp_tab); ++i)
151
+      if ((arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) &&
152
+          ip_eq(arp_pack->arp_hdr.src_ip, arp_tab[i].ip))
153
+        break;
154
+    // if found in ARP table
155
+    // (we do not want to put an entry in the ARP table
156
+    //  if we have not asked for the MAC of this IP)
157
+    if (i < count(arp_tab)) {
158
+      // update ARP table entry
159
+      arp_tab[i].flags = ARP_TAB_FLAG_IN_USE | ARP_TAB_FLAG_MAC_OK;
160
+      arp_tab[i].ticks = 0;
161
+      mac_cpy(arp_tab[i].mac, arp_pack->arp_hdr.src_mac);
162
+      // notify IP
163
+      //  - IP might be waiting for the MAC to transmit a packet
164
+      // TODO ip_got_mac(arp_tab[i].ip, arp_tab[i].mac);
165
+    }
166
+    return;
167
+  }
168
+
169
+}
170
+
171
+/**
172
+ * @brief look up the MAC for an IP address
173
+ * @param[in] ip IP address to look up
174
+ * @param[out] mac MAC address for this IP address
175
+ * @return 0 in case of success, 1 if the MAC address is unknown
176
+ */
177
+/* extern */ int arp_lookup(unsigned char ip[4], unsigned char mac[6])
178
+{
179
+  unsigned int i, j;
180
+
181
+  // own IP
182
+  if (ip_eq(ip, config_ip.ip))
183
+    // own IP may not be looked up via ARP
184
+    return 1;
185
+
186
+  // search IP in ARP tabale
187
+  for (i = 0; i < count(arp_tab); ++i)
188
+    if ((arp_tab[i].flags & ARP_TAB_FLAG_IN_USE) &&
189
+        ip_eq(ip, arp_tab[i].ip))
190
+      break;
191
+
192
+  // not found
193
+  if (i >= count(arp_tab)) {
194
+    // find a free entry
195
+    for (i = 0; i < count(arp_tab); ++i)
196
+      if (!(arp_tab[i].flags & ARP_TAB_FLAG_IN_USE))
197
+        break;
198
+
199
+    // no free entry
200
+    if (i >= count(arp_tab)) {
201
+      // find oldest entry
202
+      i = 0;
203
+      for (j = 1; j < count(arp_tab); ++j)
204
+        if (arp_tab[j].ticks > arp_tab[i].ticks )
205
+          i = j;
206
+    }
207
+
208
+    // set up this entry
209
+    arp_tab[i].flags = ARP_TAB_FLAG_IN_USE;
210
+    arp_tab[i].ticks = 0;
211
+    ip_cpy(arp_tab[i].ip, ip);
212
+  }
213
+
214
+  // MAC available
215
+  if (arp_tab[i].flags & ARP_TAB_FLAG_MAC_OK) {
216
+    // return MAC and success
217
+    mac_cpy(mac, arp_tab[i].mac);
218
+    return 0;
219
+  }
220
+
221
+  // send ARP request
222
+  arp_send_request(ip);
223
+
224
+  // no success yet
225
+  return 1;
226
+}
227
+
... ...
@@ -0,0 +1,49 @@
1
+#ifndef ARP_H
2
+#define ARP_H
3
+
4
+#include "ethernet.h"
5
+
6
+/// header of an ARP packet
7
+struct arp_header
8
+{
9
+  unsigned short hw_type;
10
+  unsigned short proto_type;
11
+  unsigned char hw_len;
12
+  unsigned char proto_len;
13
+  unsigned short op;
14
+  unsigned char src_mac[6];
15
+  unsigned char src_ip[4];
16
+  unsigned char dest_mac[6];
17
+  unsigned char dest_ip[4];
18
+} __attribute__((packed));
19
+
20
+/// an ARP packet
21
+struct arp_packet
22
+{
23
+  struct ethernet_header eth_hdr;
24
+  struct arp_header arp_hdr;
25
+} __attribute__((packed));
26
+
27
+/// initialize
28
+extern void arp_init(void);
29
+
30
+/// tick procedure - call every 200ms
31
+extern void arp_tick200(void);
32
+
33
+/**
34
+ * @brief process a received ARP packet
35
+ * @param[in] ptr pointer to data of packet
36
+ * @param[in] sz size of packet
37
+ */
38
+extern void arp_recv(void *ptr, unsigned int sz);
39
+
40
+/**
41
+ * @brief look up the MAC for an IP address
42
+ * @param[in] ip IP address to look up
43
+ * @param[out] mac MAC address for this IP address
44
+ * @return 0 in case of success, 1 if the MAC address is unknown
45
+ */
46
+extern int arp_lookup(unsigned char ip[4], unsigned char mac[6]);
47
+
48
+#endif // #ifdef ARP_H
49
+
... ...
@@ -0,0 +1,16 @@
1
+#include "config.h"
2
+#include "macros.h"
3
+#include "nethelp.h"
4
+
5
+// MAC address
6
+/* extern */ struct config_mac config_mac = {
7
+  .mac = { 0x02, 0x4D, 0x49, 0x50, 0x53, 0x01 }
8
+};
9
+
10
+// IP configuration
11
+/* extern */ struct config_ip config_ip = {
12
+  .ip = { 192, 168, 0, 89 },
13
+  .mask = { 255, 255, 0, 0 },
14
+  .gw = { 192, 168, 0, 1 }
15
+};
16
+
... ...
@@ -0,0 +1,19 @@
1
+#ifndef CONFIG_H
2
+#define CONFIG_H
3
+
4
+// MAC address
5
+struct config_mac {
6
+  unsigned char mac[6];
7
+};
8
+extern struct config_mac config_mac;
9
+
10
+// IP configuration
11
+struct config_ip {
12
+  unsigned char ip[4]; ///< own IP address
13
+  unsigned char mask[4]; //</ subnet mask
14
+  unsigned char gw[4]; ///< dateway IP address
15
+};
16
+extern struct config_ip config_ip;
17
+
18
+#endif // #ifndef CONFIG_H
19
+
... ...
@@ -1,10 +1,11 @@
1
+#include "config.h"
1 2
 #include "eth.h"
2 3
 
3 4
 static volatile unsigned int *const eth_ptr =
4 5
   (volatile unsigned int *)0x80000400;
5 6
 
6 7
 static unsigned int eth_idx_hw;
7
-static unsigned int eth_rx_buf[2][256];
8
+static unsigned int eth_rx_buf[2][381]; // max frame len: 1522 byte = 380.5 int
8 9
 static unsigned int *eth_rx_pos;
9 10
 
10 11
 /**
... ...
@@ -45,8 +46,7 @@ static void * eth_rx_get_pos(void)
45 46
 /** initialize MAC address */
46 47
 void eth_mac_init(void)
47 48
 {
48
-  static const unsigned char mac[6] = {0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
49
-  eth_mac_set(mac);
49
+  eth_mac_set(config_mac.mac);
50 50
 }
51 51
 
52 52
 /** initialize receiver */
... ...
@@ -0,0 +1,68 @@
1
+/* flpDistriR25S - flexipix distributor for pixels round 25mm with switch
2
+ * version 1.0.0 date 2011-06-12
3
+ * created by Stefan Schuermans <stefan@schuermans.info>
4
+ * Copyright (C) 2006-2011 flexipix GbR, Germany
5
+ */
6
+
7
+#include "arp.h"
8
+#include "config.h"
9
+#include "eth.h"
10
+#include "ethernet.h"
11
+// TODO #include "ip.h"
12
+#include "macros.h"
13
+#include "nethelp.h"
14
+
15
+/**
16
+ * @brief process a received ethernet packet
17
+ * @param[in] ptr pointer to data of packet
18
+ * @param[in] sz size of packet
19
+ */
20
+/* extern */ void ethernet_recv(void *ptr, unsigned int sz)
21
+{
22
+  struct ethernet_packet *eth_pack;
23
+
24
+  // packet too short
25
+  if (sz < sizeof(struct ethernet_packet))
26
+    return;
27
+
28
+  eth_pack = (struct ethernet_packet *)ptr;
29
+
30
+  // branch according to packet type
31
+  switch (eth_pack->eth_hdr.type)
32
+  {
33
+    // ARP
34
+    case htons(0x0806):
35
+      arp_recv(ptr, sz);
36
+      break;
37
+    // IP
38
+    case htons(0x0800):
39
+      // TODO ip_recv(ptr, sz);
40
+      break;
41
+  }
42
+}
43
+
44
+/**
45
+ * @brief send an ethernet packet
46
+ * @param[in] ptr pointer to data of packet
47
+ * @param[in] sz size of packet
48
+ *
49
+ * ptr must point to a ethernet_packet with eth_hdr.dest and eth_hdr.type
50
+ * already initialized
51
+ */
52
+/* extern */ void ethernet_send(void *ptr, unsigned int sz)
53
+{
54
+  struct ethernet_packet *eth_pack;
55
+
56
+  // packet too short
57
+  if (sz < sizeof(struct ethernet_packet))
58
+    return;
59
+
60
+  eth_pack = (struct ethernet_packet *)ptr;
61
+
62
+  // fill in source address
63
+  mac_cpy(eth_pack->eth_hdr.src, config_mac.mac);
64
+
65
+  // transmit packet
66
+  eth_tx(ptr, sz);
67
+}
68
+
... ...
@@ -0,0 +1,36 @@
1
+#ifndef ETHERNET_H
2
+#define ETHERNET_H
3
+
4
+/// header of an ethernet packet
5
+struct ethernet_header
6
+{
7
+  unsigned char dest[6];
8
+  unsigned char src[6];
9
+  unsigned short type;
10
+} __attribute__((packed));
11
+
12
+/// ethernet packet
13
+struct ethernet_packet
14
+{
15
+  struct ethernet_header eth_hdr;
16
+} __attribute__((packed));
17
+
18
+/**
19
+ * @brief process a received ethernet packet
20
+ * @param[in] ptr pointer to data of packet
21
+ * @param[in] sz size of packet
22
+ */
23
+void ethernet_recv(void *ptr, unsigned int sz);
24
+
25
+/**
26
+ * @brief send an ethernet packet
27
+ * @param[in] ptr pointer to data of packet
28
+ * @param[in] sz size of packet
29
+ *
30
+ * ptr must point to a ethernet_packet with eth_hdr.dest and eth_hdr.type
31
+ * already initialized
32
+ */
33
+void ethernet_send(void *ptr, unsigned int sz);
34
+
35
+#endif // #ifdef ETHERNET_H
36
+
... ...
@@ -0,0 +1,12 @@
1
+#ifndef MACROS_H
2
+#define MACROS_H
3
+
4
+// minimum and maximum
5
+#define min(a, b) ((a) < (b) ? (a) : (b))
6
+#define max(a, b) ((a) > (b) ? (a) : (b))
7
+
8
+// number of entries in an array
9
+#define count(array) (sizeof((array)) / sizeof((array)[0]))
10
+
11
+#endif // #ifndef INC_macros
12
+
... ...
@@ -1,3 +1,4 @@
1
+#include "arp.h"
1 2
 #include "cyc_cnt.h"
2 3
 #include "eth.h"
3 4
 #include "lcd.h"
... ...
@@ -5,46 +6,10 @@
5 6
 #include "uart.h"
6 7
 #include "switches.h"
7 8
 
8
-//#define CFG_SIMULATION
9
-
10
-#define CFG_ETH_RX
11
-#define CFG_ETH_TX
12
-#define CFG_UART
13
-#ifdef CFG_SIMULATION
14
-# define CFG_UART_CHK
15
-#else
16
-# define CFG_DELAY
17
-# define CFG_LCD
18
-# define CFG_SWITCHES
19
-#endif
20
-
21
-const int myconst = 0x12345678;
22
-
23
-int myvar = 0x11223344;
24
-
25
-volatile int data[100];
26
-
27
-#ifdef CFG_ETH_TX
28
-  static const unsigned char example_packet[] = {
29
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* destination MAC */
30
-    0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* source MAC */
31
-    0x08, 0x00, /* ethertype: IP */
32
-    0x45, 0x00, 0x00, 0x36, /* IP header: ..., len */
33
-    0x12, 0x34, 0x00, 0x00, /* IP header: ..., not fragmented */
34
-    0x40, 0x11, 0x00, 0x00, /* IP header: ..., UDP, ... */
35
-    0x7F, 0x00, 0x00, 0x01, /* source IP */
36
-    0xFF, 0xFF, 0xFF, 0xFF, /* destination IP */
37
-    0x00, 0x01, 0x00, 0x01, /* UDP: source port, destination port */
38
-    0x00, 0x22, 0x00, 0x00, /* UDP: len, ... */
39
-    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
40
-    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
41
-  };
42
-#endif
9
+unsigned char leds_val = 0x88;
43 10
 
44 11
 void switches(void)
45 12
 {
46
-#ifdef CFG_LCD
47
-#ifdef CFG_SWITCHES
48 13
   lcd_chr(1, 0, switches_get_state(sw_0) ? '0' : ' ');
49 14
   lcd_chr(1, 1, switches_get_state(sw_1) ? '1' : ' ');
50 15
   lcd_chr(1, 2, switches_get_state(sw_2) ? '2' : ' ');
... ...
@@ -56,75 +21,78 @@ void switches(void)
56 21
   lcd_chr(1, 8, switches_get_state(sw_center) ? 'C' : ' ');
57 22
   lcd_chr(1, 9, switches_get_state(sw_rot_a) ? 'a' : ' ');
58 23
   lcd_chr(1, 10, switches_get_state(sw_rot_b) ? 'b' : ' ');
59
-#endif
60
-#endif
61 24
 
62
-#ifdef CFG_LCD
63
-#ifdef CFG_SWITCHES
64 25
   unsigned int cnt = switches_get_rot_cnt();
65 26
   lcd_chr(1, 12, '0' + (cnt >> 9 & 0x7));
66 27
   lcd_chr(1, 13, '0' + (cnt >> 6 & 0x7));
67 28
   lcd_chr(1, 14, '0' + (cnt >> 3 & 0x7));
68 29
   lcd_chr(1, 15, '0' + (cnt & 0x7));
69
-#endif
70
-#endif
71 30
 }
72 31
 
73
-void delay(void)
32
+void leds_uart(void)
33
+{
34
+  unsigned short chr;
35
+
36
+  while (uart_can_rx()) {
37
+    chr = uart_rx();
38
+    if (uart_is_err(chr))
39
+      leds_val = 0;
40
+    else
41
+      leds_val = chr;
42
+    leds_set_state(leds_val);
43
+  }
44
+}
45
+
46
+void eth_task(void)
74 47
 {
75
-  unsigned int i;
76
-#ifdef CFG_ETH_RX
77 48
   void *vptr;
49
+  unsigned int sz, i;
78 50
   unsigned char *ptr;
79
-  unsigned int sz;
80
-#endif
81 51
 
82
-  for (i = 0; i < 10; ++i) {
83
-    switches();
84
-#ifdef CFG_ETH_RX
85 52
   while (eth_rx(&vptr, &sz)) {
86 53
     ptr = vptr;
87
-#ifdef CFG_UART
88
-      for ( ; sz > 0; ptr++, sz--)
89
-        uart_tx(*ptr);
90
-#endif
54
+    for (i = 0; i < sz; ++i)
55
+      uart_tx(ptr[i]);
56
+    ethernet_recv(vptr, sz);
57
+  }
58
+}
59
+
60
+void tasks(void)
61
+{
62
+  switches();
63
+  leds_uart();
64
+  eth_task();
91 65
 }
92
-#endif
93
-#ifdef CFG_DELAY
94
-    cyc_cnt_delay_ms(20);
95
-#endif
66
+
67
+void leds_tick200(void)
68
+{
69
+  leds_val = leds_val << 1 | leds_val >> 7;
70
+  leds_set_state(leds_val);
96 71
 }
72
+
73
+void tick200(void)
74
+{
75
+  leds_tick200();
76
+  arp_tick200();
97 77
 }
98 78
 
99 79
 int main()
100 80
 {
101 81
   unsigned int i;
102
-  unsigned short chr;
103
-  unsigned char leds;
104 82
 
105 83
   leds_set_state(0x01);
106 84
 
107
-  for (i = 0; i < sizeof(data) / sizeof(data[0]); ++i)
108
-    data[i] = i;
109
-
110
-  leds_set_state(0x02);
111
-
112
-#ifdef CFG_ETH_RX
113 85
   eth_mac_init();
114 86
   eth_rx_init();
115
-#endif
116 87
 
117
-  leds_set_state(0x04);
88
+  leds_set_state(0x02);
118 89
 
119
-#ifdef CFG_LCD
120 90
   lcd_init();
121 91
   lcd_str(0, "MIPS I system");
122 92
   lcd_str(1, "");
123
-#endif
124 93
 
125
-  leds_set_state(0x08);
94
+  leds_set_state(0x04);
126 95
 
127
-#ifdef CFG_UART
128 96
   uart_cfg_scale(62); /* 115200 */
129 97
   uart_cfg_bits(8);
130 98
   uart_cfg_stop(1);
... ...
@@ -136,40 +104,19 @@ int main()
136 104
   uart_tx('I');
137 105
   uart_tx('\r');
138 106
   uart_tx('\n');
139
-#ifdef CFG_UART_CHK
140
-  if (uart_rx() != 'M') while(1);
141
-  if (uart_rx() != 'I') while(1);
142
-  if (uart_rx() != 'P') while(1);
143
-  if (uart_rx() != 'S') while(1);
144
-  if (uart_rx() != ' ') while(1);
145
-  if (uart_rx() != 'I') while(1);
146
-  if (uart_rx() != '\r') while(1);
147
-  if (uart_rx() != '\n') while(1);
148
-#endif
149
-#endif
107
+
108
+  leds_set_state(0x08);
109
+
110
+  arp_init();
150 111
 
151 112
   leds_set_state(0x10);
152 113
 
153
-  leds = 0x11;
154 114
   while (1) {
155
-#ifdef CFG_UART
156
-    if (uart_can_rx()) {
157
-      chr = uart_rx();
158
-      if (uart_is_err(chr))
159
-        leds = 0;
160
-      else
161
-        leds = chr;
115
+    for (i = 0; i < 20; ++i) {
116
+      tasks();
117
+      cyc_cnt_delay_ms(10);
162 118
     }
163
-#endif
164
-    leds_set_state(leds);
165
-    leds = leds << 1 | leds >> 7;
166
-    delay();
167
-#ifdef CFG_ETH_TX
168
-#ifdef CFG_SWITCHES
169
-    if (switches_get_state(sw_center))
170
-#endif
171
-      eth_tx(example_packet, sizeof(example_packet));
172
-#endif
119
+    tick200();
173 120
   }
174 121
 
175 122
   return 0;
... ...
@@ -0,0 +1,33 @@
1
+#ifndef NETHELP_H
2
+#define NETHELP_H
3
+
4
+// byte order
5
+#define ntohs(n) (((unsigned short)(n) & 0xFF00) >> 8 | \
6
+                  ((unsigned short)(n) & 0x00FF) << 8)
7
+#define htons(h) (((unsigned short)(h) & 0xFF00) >> 8 | \
8
+                  ((unsigned short)(h) & 0x00FF) << 8)
9
+#define ntohl(n) (((unsigned int)(n) & 0xFF000000) >> 24 | \
10
+                  ((unsigned int)(n) & 0x00FF0000) >> 8 | \
11
+                  ((unsigned int)(n) & 0x0000FF00) << 8 | \
12
+                  ((unsigned int)(n) & 0x000000FF) << 24)
13
+#define htonl(h) (((unsigned int)(h) & 0xFF000000) >> 24 | \
14
+                  ((unsigned int)(h) & 0x00FF0000) >> 8 | \
15
+                  ((unsigned int)(h) & 0x0000FF00) << 8 | \
16
+                  ((unsigned int)(h) & 0x000000FF) << 24)
17
+
18
+// comparing MACs and IPs
19
+#define mac_eq(a, b) ((a)[0] == (b)[0] && (a)[1] == (b)[1] && \
20
+                      (a)[2] == (b)[2] && (a)[3] == (b)[3] && \
21
+                      (a)[4] == (b)[4] && (a)[5] == (b)[5])
22
+#define ip_eq(a, b) ((a)[0] == (b)[0] && (a)[1] == (b)[1] && \
23
+                     (a)[2] == (b)[2] && (a)[3] == (b)[3])
24
+
25
+// copying MACs and IPs
26
+#define mac_cpy(dest, src) ((dest)[0] = (src)[0], (dest)[1] = (src)[1], \
27
+                            (dest)[2] = (src)[2], (dest)[3] = (src)[3], \
28
+                            (dest)[4] = (src)[4], (dest)[5] = (src)[5])
29
+#define ip_cpy(dest, src) ((dest)[0] = (src)[0], (dest)[1] = (src)[1], \
30
+                           (dest)[2] = (src)[2], (dest)[3] = (src)[3])
31
+
32
+#endif // #ifndef NETHELP_H
33
+
... ...
@@ -407,7 +407,7 @@
407 407
     <property xil_pn:name="Shift Register Extraction" xil_pn:value="true" xil_pn:valueState="default"/>
408 408
     <property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
409 409
     <property xil_pn:name="Simulation Model Target" xil_pn:value="VHDL" xil_pn:valueState="default"/>
410
-    <property xil_pn:name="Simulation Run Time ISim" xil_pn:value="2 ms" xil_pn:valueState="non-default"/>
410
+    <property xil_pn:name="Simulation Run Time ISim" xil_pn:value="30 ms" xil_pn:valueState="non-default"/>
411 411
     <property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
412 412
     <property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
413 413
     <property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
... ...
@@ -110,7 +110,7 @@ BEGIN
110 110
     BEGIN
111 111
         s_eth_rxd   <= "0000";
112 112
         s_eth_rx_dv <= '0';
113
-        WAIT FOR 1 ms;
113
+        WAIT FOR 10 ms;
114 114
         WAIT UNTIL s_eth_clk = '1';
115 115
         WAIT UNTIL s_eth_clk = '0';
116 116
         FOR i IN 0 TO eth_data'length - 1 LOOP
117 117