Contiki-NG
enc28j60.c
1 /*
2  * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 
32 #include "contiki.h"
33 #include "enc28j60.h"
34 #include <stdio.h>
35 #include <string.h>
36 
37 #define DEBUG 0
38 #if DEBUG
39 #define PRINTF(...) printf(__VA_ARGS__)
40 #else
41 #define PRINTF(...)
42 #endif
43 
44 #define EIE 0x1b
45 #define EIR 0x1c
46 #define ESTAT 0x1d
47 #define ECON2 0x1e
48 #define ECON1 0x1f
49 
50 #define ESTAT_CLKRDY 0x01
51 #define ESTAT_TXABRT 0x02
52 
53 #define ECON1_RXEN 0x04
54 #define ECON1_TXRTS 0x08
55 
56 #define ECON2_AUTOINC 0x80
57 #define ECON2_PKTDEC 0x40
58 
59 #define EIR_TXIF 0x08
60 
61 #define ERXTX_BANK 0x00
62 
63 #define ERDPTL 0x00
64 #define ERDPTH 0x01
65 #define EWRPTL 0x02
66 #define EWRPTH 0x03
67 #define ETXSTL 0x04
68 #define ETXSTH 0x05
69 #define ETXNDL 0x06
70 #define ETXNDH 0x07
71 #define ERXSTL 0x08
72 #define ERXSTH 0x09
73 #define ERXNDL 0x0a
74 #define ERXNDH 0x0b
75 #define ERXRDPTL 0x0c
76 #define ERXRDPTH 0x0d
77 
78 #define RX_BUF_START 0x0000
79 #define RX_BUF_END 0x0fff
80 
81 #define TX_BUF_START 0x1200
82 
83 /* MACONx registers are in bank 2 */
84 #define MACONX_BANK 0x02
85 
86 #define MACON1 0x00
87 #define MACON3 0x02
88 #define MACON4 0x03
89 #define MABBIPG 0x04
90 #define MAIPGL 0x06
91 #define MAIPGH 0x07
92 #define MAMXFLL 0x0a
93 #define MAMXFLH 0x0b
94 
95 #define MACON1_TXPAUS 0x08
96 #define MACON1_RXPAUS 0x04
97 #define MACON1_MARXEN 0x01
98 
99 #define MACON3_PADCFG_FULL 0xe0
100 #define MACON3_TXCRCEN 0x10
101 #define MACON3_FRMLNEN 0x02
102 #define MACON3_FULDPX 0x01
103 
104 #define MAX_MAC_LENGTH 1518
105 
106 #define MAADRX_BANK 0x03
107 #define MAADR1 0x04 /* MAADR<47:40> */
108 #define MAADR2 0x05 /* MAADR<39:32> */
109 #define MAADR3 0x02 /* MAADR<31:24> */
110 #define MAADR4 0x03 /* MAADR<23:16> */
111 #define MAADR5 0x00 /* MAADR<15:8> */
112 #define MAADR6 0x01 /* MAADR<7:0> */
113 #define MISTAT 0x0a
114 #define EREVID 0x12
115 
116 #define EPKTCNT_BANK 0x01
117 #define ERXFCON 0x18
118 #define EPKTCNT 0x19
119 
120 #define ERXFCON_UCEN 0x80
121 #define ERXFCON_ANDOR 0x40
122 #define ERXFCON_CRCEN 0x20
123 #define ERXFCON_MCEN 0x02
124 #define ERXFCON_BCEN 0x01
125 
126 
127 PROCESS(enc_watchdog_process, "Enc28j60 watchdog");
128 
129 static uint8_t initialized = 0;
130 static uint8_t bank = ERXTX_BANK;
131 static uint8_t enc_mac_addr[6];
132 static int received_packets = 0;
133 static int sent_packets = 0;
134 
135 /*---------------------------------------------------------------------------*/
136 static uint8_t
137 is_mac_mii_reg(uint8_t reg)
138 {
139  /* MAC or MII register (otherwise, ETH register)? */
140  switch(bank) {
141  case MACONX_BANK:
142  return reg < EIE;
143  case MAADRX_BANK:
144  return reg <= MAADR2 || reg == MISTAT;
145  case ERXTX_BANK:
146  case EPKTCNT_BANK:
147  default:
148  return 0;
149  }
150 }
151 /*---------------------------------------------------------------------------*/
152 static uint8_t
153 readreg(uint8_t reg)
154 {
155  uint8_t r;
156  enc28j60_arch_spi_select();
157  enc28j60_arch_spi_write(0x00 | (reg & 0x1f));
158  if(is_mac_mii_reg(reg)) {
159  /* MAC and MII registers require that a dummy byte be read first. */
160  enc28j60_arch_spi_read();
161  }
162  r = enc28j60_arch_spi_read();
163  enc28j60_arch_spi_deselect();
164  return r;
165 }
166 /*---------------------------------------------------------------------------*/
167 static void
168 writereg(uint8_t reg, uint8_t data)
169 {
170  enc28j60_arch_spi_select();
171  enc28j60_arch_spi_write(0x40 | (reg & 0x1f));
172  enc28j60_arch_spi_write(data);
173  enc28j60_arch_spi_deselect();
174 }
175 /*---------------------------------------------------------------------------*/
176 static void
177 setregbitfield(uint8_t reg, uint8_t mask)
178 {
179  if(is_mac_mii_reg(reg)) {
180  writereg(reg, readreg(reg) | mask);
181  } else {
182  enc28j60_arch_spi_select();
183  enc28j60_arch_spi_write(0x80 | (reg & 0x1f));
184  enc28j60_arch_spi_write(mask);
185  enc28j60_arch_spi_deselect();
186  }
187 }
188 /*---------------------------------------------------------------------------*/
189 static void
190 clearregbitfield(uint8_t reg, uint8_t mask)
191 {
192  if(is_mac_mii_reg(reg)) {
193  writereg(reg, readreg(reg) & ~mask);
194  } else {
195  enc28j60_arch_spi_select();
196  enc28j60_arch_spi_write(0xa0 | (reg & 0x1f));
197  enc28j60_arch_spi_write(mask);
198  enc28j60_arch_spi_deselect();
199  }
200 }
201 /*---------------------------------------------------------------------------*/
202 static void
203 setregbank(uint8_t new_bank)
204 {
205  writereg(ECON1, (readreg(ECON1) & 0xfc) | (new_bank & 0x03));
206  bank = new_bank;
207 }
208 /*---------------------------------------------------------------------------*/
209 static void
210 writedata(const uint8_t *data, int datalen)
211 {
212  int i;
213  enc28j60_arch_spi_select();
214  /* The Write Buffer Memory (WBM) command is 0 1 1 1 1 0 1 0 */
215  enc28j60_arch_spi_write(0x7a);
216  for(i = 0; i < datalen; i++) {
217  enc28j60_arch_spi_write(data[i]);
218  }
219  enc28j60_arch_spi_deselect();
220 }
221 /*---------------------------------------------------------------------------*/
222 static void
223 writedatabyte(uint8_t byte)
224 {
225  writedata(&byte, 1);
226 }
227 /*---------------------------------------------------------------------------*/
228 static int
229 readdata(uint8_t *buf, int len)
230 {
231  int i;
232  enc28j60_arch_spi_select();
233  /* THe Read Buffer Memory (RBM) command is 0 0 1 1 1 0 1 0 */
234  enc28j60_arch_spi_write(0x3a);
235  for(i = 0; i < len; i++) {
236  buf[i] = enc28j60_arch_spi_read();
237  }
238  enc28j60_arch_spi_deselect();
239  return i;
240 }
241 /*---------------------------------------------------------------------------*/
242 static uint8_t
243 readdatabyte(void)
244 {
245  uint8_t r;
246  readdata(&r, 1);
247  return r;
248 }
249 /*---------------------------------------------------------------------------*/
250 static void
251 softreset(void)
252 {
253  enc28j60_arch_spi_select();
254  /* The System Command (soft reset) is 1 1 1 1 1 1 1 1 */
255  enc28j60_arch_spi_write(0xff);
256  enc28j60_arch_spi_deselect();
257  bank = ERXTX_BANK;
258 }
259 /*---------------------------------------------------------------------------*/
260 #if DEBUG
261 static uint8_t
262 readrev(void)
263 {
264  uint8_t rev;
265  setregbank(MAADRX_BANK);
266  rev = readreg(EREVID);
267  switch(rev) {
268  case 2:
269  return 1;
270  case 6:
271  return 7;
272  default:
273  return rev;
274  }
275 }
276 #endif
277 /*---------------------------------------------------------------------------*/
278 static void
279 reset(void)
280 {
281  PRINTF("enc28j60: resetting chip\n");
282 
283  enc28j60_arch_spi_init();
284 
285  /*
286  6.0 INITIALIZATION
287 
288  Before the ENC28J60 can be used to transmit and receive packets,
289  certain device settings must be initialized. Depending on the
290  application, some configuration options may need to be
291  changed. Normally, these tasks may be accomplished once after
292  Reset and do not need to be changed thereafter.
293 
294  6.1 Receive Buffer
295 
296  Before receiving any packets, the receive buffer must be
297  initialized by programming the ERXST and ERXND pointers. All
298  memory between and including the ERXST and ERXND addresses will be
299  dedicated to the receive hardware. It is recommended that the
300  ERXST pointer be programmed with an even address.
301 
302  Applications expecting large amounts of data and frequent packet
303  delivery may wish to allocate most of the memory as the receive
304  buffer. Applications that may need to save older packets or have
305  several packets ready for transmission should allocate less
306  memory.
307 
308  When programming the ERXST pointer, the ERXWRPT registers will
309  automatically be updated with the same values. The address in
310  ERXWRPT will be used as the starting location when the receive
311  hardware begins writing received data. For tracking purposes, the
312  ERXRDPT registers should additionally be programmed with the same
313  value. To program ERXRDPT, the host controller must write to
314  ERXRDPTL first, followed by ERXRDPTH. See Section 7.2.4 “Freeing
315  Receive Buffer Space for more information
316 
317  6.2 Transmission Buffer
318 
319  All memory which is not used by the receive buffer is considered
320  the transmission buffer. Data which is to be transmitted should be
321  written into any unused space. After a packet is transmitted,
322  however, the hardware will write a seven-byte status vector into
323  memory after the last byte in the packet. Therefore, the host
324  controller should leave at least seven bytes between each packet
325  and the beginning of the receive buffer. No explicit action is
326  required to initialize the transmission buffer.
327 
328  6.3 Receive Filters
329 
330  The appropriate receive filters should be enabled or disabled by
331  writing to the ERXFCON register. See Section 8.0 “Receive Filters
332  for information on how to configure it.
333 
334  6.4 Waiting For OST
335 
336  If the initialization procedure is being executed immediately
337  following a Power-on Reset, the ESTAT.CLKRDY bit should be polled
338  to make certain that enough time has elapsed before proceeding to
339  modify the MAC and PHY registers. For more information on the OST,
340  see Section 2.2 “Oscillator Start-up Timer.
341  */
342 
343  softreset();
344 
345  /* Workaround for erratum #2. */
346  clock_delay_usec(1000);
347 
348  /* Wait for OST */
349  while((readreg(ESTAT) & ESTAT_CLKRDY) == 0);
350 
351  setregbank(ERXTX_BANK);
352  /* Set up receive buffer */
353  writereg(ERXSTL, RX_BUF_START & 0xff);
354  writereg(ERXSTH, RX_BUF_START >> 8);
355  writereg(ERXNDL, RX_BUF_END & 0xff);
356  writereg(ERXNDH, RX_BUF_END >> 8);
357  writereg(ERDPTL, RX_BUF_START & 0xff);
358  writereg(ERDPTH, RX_BUF_START >> 8);
359  writereg(ERXRDPTL, RX_BUF_END & 0xff);
360  writereg(ERXRDPTH, RX_BUF_END >> 8);
361 
362  /* Receive filters */
363  setregbank(EPKTCNT_BANK);
364  writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN);
365 
366  /*
367  6.5 MAC Initialization Settings
368 
369  Several of the MAC registers require configuration during
370  initialization. This only needs to be done once; the order of
371  programming is unimportant.
372 
373  1. Set the MARXEN bit in MACON1 to enable the MAC to receive
374  frames. If using full duplex, most applications should also set
375  TXPAUS and RXPAUS to allow IEEE defined flow control to function.
376 
377  2. Configure the PADCFG, TXCRCEN and FULDPX bits of MACON3. Most
378  applications should enable automatic padding to at least 60 bytes
379  and always append a valid CRC. For convenience, many applications
380  may wish to set the FRMLNEN bit as well to enable frame length
381  status reporting. The FULDPX bit should be set if the application
382  will be connected to a full-duplex configured remote node;
383  otherwise, it should be left clear.
384 
385  3. Configure the bits in MACON4. For conformance to the IEEE 802.3
386  standard, set the DEFER bit.
387 
388  4. Program the MAMXFL registers with the maximum frame length to
389  be permitted to be received or transmitted. Normal network nodes
390  are designed to handle packets that are 1518 bytes or less.
391 
392  5. Configure the Back-to-Back Inter-Packet Gap register,
393  MABBIPG. Most applications will program this register with 15h
394  when Full-Duplex mode is used and 12h when Half-Duplex mode is
395  used.
396 
397  6. Configure the Non-Back-to-Back Inter-Packet Gap register low
398  byte, MAIPGL. Most applications will program this register with
399  12h.
400 
401  7. If half duplex is used, the Non-Back-to-Back Inter-Packet Gap
402  register high byte, MAIPGH, should be programmed. Most
403  applications will program this register to 0Ch.
404 
405  8. If Half-Duplex mode is used, program the Retransmission and
406  Collision Window registers, MACLCON1 and MACLCON2. Most
407  applications will not need to change the default Reset values. If
408  the network is spread over exceptionally long cables, the default
409  value of MACLCON2 may need to be increased.
410 
411  9. Program the local MAC address into the MAADR1:MAADR6 registers.
412  */
413 
414  setregbank(MACONX_BANK);
415 
416  /* Turn on reception and IEEE-defined flow control */
417  setregbitfield(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
418 
419  /* Set padding, crc, full duplex */
420  setregbitfield(MACON3, MACON3_PADCFG_FULL | MACON3_TXCRCEN | MACON3_FULDPX |
421  MACON3_FRMLNEN);
422 
423  /* Don't modify MACON4 */
424 
425  /* Set maximum frame length in MAMXFL */
426  writereg(MAMXFLL, MAX_MAC_LENGTH & 0xff);
427  writereg(MAMXFLH, MAX_MAC_LENGTH >> 8);
428 
429  /* Set back-to-back inter packet gap */
430  writereg(MABBIPG, 0x15);
431 
432  /* Set non-back-to-back packet gap */
433  writereg(MAIPGL, 0x12);
434 
435  /* Set MAC address */
436  setregbank(MAADRX_BANK);
437  writereg(MAADR6, enc_mac_addr[5]);
438  writereg(MAADR5, enc_mac_addr[4]);
439  writereg(MAADR4, enc_mac_addr[3]);
440  writereg(MAADR3, enc_mac_addr[2]);
441  writereg(MAADR2, enc_mac_addr[1]);
442  writereg(MAADR1, enc_mac_addr[0]);
443 
444  /*
445  6.6 PHY Initialization Settings
446 
447  Depending on the application, bits in three of the PHY module’s
448  registers may also require configuration. The PHCON1.PDPXMD bit
449  partially controls the device’s half/full-duplex
450  configuration. Normally, this bit is initialized correctly by the
451  external circuitry (see Section 2.6 “LED Configuration). If the
452  external circuitry is not present or incorrect, however, the host
453  controller must program the bit properly. Alternatively, for an
454  externally configurable system, the PDPXMD bit may be read and the
455  FULDPX bit be programmed to match.
456 
457  For proper duplex operation, the PHCON1.PDPXMD bit must also match
458  the value of the MACON3.FULDPX bit.
459 
460  If using half duplex, the host controller may wish to set the
461  PHCON2.HDLDIS bit to prevent automatic loopback of the data which
462  is transmitted. The PHY register, PHLCON, controls the outputs of
463  LEDA and LEDB. If an application requires a LED configuration
464  other than the default, PHLCON must be altered to match the new
465  requirements. The settings for LED operation are discussed in
466  Section 2.6 “LED Configuration. The PHLCON register is shown in
467  Register 2-2 (page 9).
468  */
469 
470  /* Don't worry about PHY configuration for now */
471 
472  /* Turn on autoincrement for buffer access */
473  setregbitfield(ECON2, ECON2_AUTOINC);
474 
475  /* Turn on reception */
476  writereg(ECON1, ECON1_RXEN);
477 }
478 /*---------------------------------------------------------------------------*/
479 void
480 enc28j60_init(const uint8_t *mac_addr)
481 {
482  if(initialized) {
483  return;
484  }
485 
486  memcpy(enc_mac_addr, mac_addr, 6);
487 
488  /* Start watchdog process */
489  process_start(&enc_watchdog_process, NULL);
490 
491  reset();
492 
493  PRINTF("ENC28J60 rev. B%d\n", readrev());
494 
495  initialized = 1;
496 }
497 /*---------------------------------------------------------------------------*/
498 int
499 enc28j60_send(const uint8_t *data, uint16_t datalen)
500 {
501  uint16_t dataend;
502 
503  if(!initialized) {
504  return -1;
505  }
506 
507  /*
508  1. Appropriately program the ETXST pointer to point to an unused
509  location in memory. It will point to the per packet control
510  byte. In the example, it would be programmed to 0120h. It is
511  recommended that an even address be used for ETXST.
512 
513  2. Use the WBM SPI command to write the per packet control byte,
514  the destination address, the source MAC address, the
515  type/length and the data payload.
516 
517  3. Appropriately program the ETXND pointer. It should point to the
518  last byte in the data payload. In the example, it would be
519  programmed to 0156h.
520 
521  4. Clear EIR.TXIF, set EIE.TXIE and set EIE.INTIE to enable an
522  interrupt when done (if desired).
523 
524  5. Start the transmission process by setting
525  ECON1.TXRTS.
526  */
527 
528  setregbank(ERXTX_BANK);
529  /* Set up the transmit buffer pointer */
530  writereg(ETXSTL, TX_BUF_START & 0xff);
531  writereg(ETXSTH, TX_BUF_START >> 8);
532  writereg(EWRPTL, TX_BUF_START & 0xff);
533  writereg(EWRPTH, TX_BUF_START >> 8);
534 
535  /* Write the transmission control register as the first byte of the
536  output packet. We write 0x00 to indicate that the default
537  configuration (the values in MACON3) will be used. */
538  writedatabyte(0x00); /* MACON3 */
539 
540  writedata(data, datalen);
541 
542  /* Write a pointer to the last data byte. */
543  dataend = TX_BUF_START + datalen;
544  writereg(ETXNDL, dataend & 0xff);
545  writereg(ETXNDH, dataend >> 8);
546 
547  /* Clear EIR.TXIF */
548  clearregbitfield(EIR, EIR_TXIF);
549 
550  /* Don't care about interrupts for now */
551 
552  /* Send the packet */
553  setregbitfield(ECON1, ECON1_TXRTS);
554  while((readreg(ECON1) & ECON1_TXRTS) > 0);
555 
556 #if DEBUG
557  if((readreg(ESTAT) & ESTAT_TXABRT) != 0) {
558  uint16_t erdpt;
559  uint8_t tsv[7];
560  erdpt = (readreg(ERDPTH) << 8) | readreg(ERDPTL);
561  writereg(ERDPTL, (dataend + 1) & 0xff);
562  writereg(ERDPTH, (dataend + 1) >> 8);
563  readdata(tsv, sizeof(tsv));
564  writereg(ERDPTL, erdpt & 0xff);
565  writereg(ERDPTH, erdpt >> 8);
566  PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n"
567  " tsv: %02x%02x%02x%02x%02x%02x%02x\n", datalen,
568  0xff & data[0], 0xff & data[1], 0xff & data[2],
569  0xff & data[3], 0xff & data[4], 0xff & data[5],
570  tsv[6], tsv[5], tsv[4], tsv[3], tsv[2], tsv[1], tsv[0]);
571  } else {
572  PRINTF("enc28j60: tx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen,
573  0xff & data[0], 0xff & data[1], 0xff & data[2],
574  0xff & data[3], 0xff & data[4], 0xff & data[5]);
575  }
576 #endif
577 
578  sent_packets++;
579  PRINTF("enc28j60: sent_packets %d\n", sent_packets);
580  return datalen;
581 }
582 /*---------------------------------------------------------------------------*/
583 int
584 enc28j60_read(uint8_t *buffer, uint16_t bufsize)
585 {
586  int n, len, next, err;
587 
588  uint8_t nxtpkt[2];
589  uint8_t status[2];
590  uint8_t length[2];
591 
592  if(!initialized) {
593  return -1;
594  }
595 
596  err = 0;
597 
598  setregbank(EPKTCNT_BANK);
599  n = readreg(EPKTCNT);
600 
601  if(n == 0) {
602  return 0;
603  }
604 
605  PRINTF("enc28j60: EPKTCNT 0x%02x\n", n);
606 
607  setregbank(ERXTX_BANK);
608  /* Read the next packet pointer */
609  nxtpkt[0] = readdatabyte();
610  nxtpkt[1] = readdatabyte();
611 
612  PRINTF("enc28j60: nxtpkt 0x%02x%02x\n", nxtpkt[1], nxtpkt[0]);
613 
614  length[0] = readdatabyte();
615  length[1] = readdatabyte();
616 
617  PRINTF("enc28j60: length 0x%02x%02x\n", length[1], length[0]);
618 
619  status[0] = readdatabyte();
620  status[1] = readdatabyte();
621 
622  /* This statement is just to avoid a compiler warning: */
623  status[0] = status[0];
624  PRINTF("enc28j60: status 0x%02x%02x\n", status[1], status[0]);
625 
626  len = (length[1] << 8) + length[0];
627  if(bufsize >= len) {
628  readdata(buffer, len);
629  } else {
630  uint16_t i;
631 
632  err = 1;
633 
634  /* flush rx fifo */
635  for(i = 0; i < len; i++) {
636  readdatabyte();
637  }
638  }
639 
640  /* Read an additional byte at odd lengths, to avoid FIFO corruption */
641  if((len % 2) != 0) {
642  readdatabyte();
643  }
644 
645  /* Errata #14 */
646  next = (nxtpkt[1] << 8) + nxtpkt[0];
647  if(next == RX_BUF_START) {
648  next = RX_BUF_END;
649  } else {
650  next = next - 1;
651  }
652  writereg(ERXRDPTL, next & 0xff);
653  writereg(ERXRDPTH, next >> 8);
654 
655  setregbitfield(ECON2, ECON2_PKTDEC);
656 
657  if(err) {
658  PRINTF("enc28j60: rx err: flushed %d\n", len);
659  return 0;
660  }
661  PRINTF("enc28j60: rx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", len,
662  0xff & buffer[0], 0xff & buffer[1], 0xff & buffer[2],
663  0xff & buffer[3], 0xff & buffer[4], 0xff & buffer[5]);
664 
665  received_packets++;
666  PRINTF("enc28j60: received_packets %d\n", received_packets);
667  return len;
668 }
669 /*---------------------------------------------------------------------------*/
670 PROCESS_THREAD(enc_watchdog_process, ev, data)
671 {
672  static struct etimer et;
673 
674  PROCESS_BEGIN();
675 
676  while(1) {
677 #define RESET_PERIOD (30 * CLOCK_SECOND)
678  etimer_set(&et, RESET_PERIOD);
680 
681  PRINTF("enc28j60: test received_packet %d > sent_packets %d\n", received_packets, sent_packets);
682  if(received_packets <= sent_packets) {
683  PRINTF("enc28j60: resetting chip\n");
684  reset();
685  }
686  received_packets = 0;
687  sent_packets = 0;
688  }
689 
690  PROCESS_END();
691 }
692 /*---------------------------------------------------------------------------*/
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
Definition: process.h:157
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:150
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition: etimer.c:213
A timer.
Definition: etimer.h:76
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1097
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99