1 |
4 |
atypic |
/*********************************************
|
2 |
|
|
* vim:sw=8:ts=8:si:et
|
3 |
|
|
* To use the above modeline in vim you must have "set modeline" in your .vimrc
|
4 |
|
|
* Author: Guido Socher
|
5 |
|
|
* Copyright: GPL V2
|
6 |
|
|
*
|
7 |
|
|
* Based on the enc28j60.c file from the AVRlib library by Pascal Stang.
|
8 |
|
|
* For AVRlib See http://www.procyonengineering.com/
|
9 |
|
|
* Used with explicit permission of Pascal Stang.
|
10 |
|
|
*
|
11 |
|
|
* Title: Microchip ENC28J60 Ethernet Interface Driver
|
12 |
|
|
* Chip type : ATMEGA88 with ENC28J60
|
13 |
|
|
*********************************************/
|
14 |
|
|
#include <avr/io.h>
|
15 |
|
|
//#include "avr_compat.h"
|
16 |
|
|
#include "enc28j60.h"
|
17 |
|
|
#include "enc28j60conf.h"
|
18 |
|
|
#include <device.h>
|
19 |
|
|
//#include "nic.h"
|
20 |
|
|
#include "../global.h"
|
21 |
|
|
//#include "timeout.h"
|
22 |
|
|
#include <util/delay.h>
|
23 |
|
|
|
24 |
|
|
static uint8_t Enc28j60Bank;
|
25 |
|
|
static uint16_t NextPacketPtr;
|
26 |
|
|
// set CS to 0 = active
|
27 |
|
|
#define CSACTIVE ENC28J60_CONTROL_PORT&=~(1<<ENC28J60_CONTROL_CS)
|
28 |
|
|
// set CS to 1 = passive
|
29 |
|
|
#define CSPASSIVE ENC28J60_CONTROL_PORT|=(1<<ENC28J60_CONTROL_CS)
|
30 |
|
|
//
|
31 |
|
|
#define waitspi() while(!(SPSR&(1<<SPIF)))
|
32 |
|
|
|
33 |
|
|
//struct igordev_data idata;
|
34 |
|
|
int status;
|
35 |
|
|
/*
|
36 |
|
|
void nicInit(void)
|
37 |
|
|
{
|
38 |
|
|
buf_init(&idata.readbuf);
|
39 |
|
|
buf_init(&idata.writebuf);
|
40 |
|
|
status = 0;
|
41 |
|
|
enc28j60Init();
|
42 |
|
|
}
|
43 |
|
|
*/
|
44 |
|
|
void
|
45 |
|
|
nicDeinit(void)
|
46 |
|
|
{
|
47 |
|
|
/* NOP */
|
48 |
|
|
}
|
49 |
|
|
|
50 |
|
|
/* Read function for our device framework */
|
51 |
|
|
/*int
|
52 |
|
|
nicRead(int numbytes)
|
53 |
|
|
{
|
54 |
|
|
struct buf *buf;
|
55 |
|
|
unsigned int len;
|
56 |
|
|
char data;
|
57 |
|
|
char err;
|
58 |
|
|
int i;
|
59 |
|
|
*/
|
60 |
|
|
/* XXX: Larger receive buffers. */
|
61 |
|
|
/* buf = &idata.readbuf;
|
62 |
|
|
for (i = 0; i < numbytes; i++) {
|
63 |
|
|
len = nicPoll(1, &data);
|
64 |
|
|
if (len == 0)
|
65 |
|
|
break;
|
66 |
|
|
err = buf_write(buf, data);
|
67 |
|
|
if (err || buf->status & BUF_STATUS_FULL)
|
68 |
|
|
break;
|
69 |
|
|
}
|
70 |
|
|
status = IDEV_STATUS_OK;
|
71 |
|
|
return (0);
|
72 |
|
|
}
|
73 |
|
|
*/
|
74 |
|
|
/* Write function for our device framework. */
|
75 |
|
|
/*int
|
76 |
|
|
nicWrite(int numbytes)
|
77 |
|
|
{
|
78 |
|
|
struct buf *buf;
|
79 |
|
|
unsigned int len;
|
80 |
|
|
char data;
|
81 |
|
|
char err;
|
82 |
|
|
int i;
|
83 |
|
|
|
84 |
|
|
buf = &idata.writebuf;
|
85 |
|
|
*/ /* XXX: Larger send buffers. */
|
86 |
|
|
/* for (i = 0; i < numbytes; i++) {
|
87 |
|
|
err = buf_read(buf, &data);
|
88 |
|
|
if (err || buf->status & BUF_STATUS_EMPTY)
|
89 |
|
|
break;
|
90 |
|
|
nicSend(1, &data);
|
91 |
|
|
}
|
92 |
|
|
status = IDEV_STATUS_OK;
|
93 |
|
|
}
|
94 |
|
|
*/
|
95 |
|
|
void nicSend(unsigned int len, uint8_t* packet)
|
96 |
|
|
{
|
97 |
|
|
enc28j60PacketSend(len, packet);
|
98 |
|
|
}
|
99 |
|
|
|
100 |
|
|
unsigned int nicPoll(unsigned int maxlen, unsigned char* packet)
|
101 |
|
|
{
|
102 |
|
|
return enc28j60PacketReceive(maxlen, packet);
|
103 |
|
|
}
|
104 |
|
|
|
105 |
|
|
|
106 |
|
|
uint8_t enc28j60ReadOp(uint8_t op, uint8_t address)
|
107 |
|
|
{
|
108 |
|
|
CSACTIVE;
|
109 |
|
|
// issue read command
|
110 |
|
|
SPDR = op | (address & ADDR_MASK);
|
111 |
|
|
waitspi();
|
112 |
|
|
// read data
|
113 |
|
|
SPDR = 0x00;
|
114 |
|
|
waitspi();
|
115 |
|
|
// do dummy read if needed (for mac and mii, see datasheet page 29)
|
116 |
|
|
if(address & 0x80)
|
117 |
|
|
{
|
118 |
|
|
SPDR = 0x00;
|
119 |
|
|
waitspi();
|
120 |
|
|
}
|
121 |
|
|
// release CS
|
122 |
|
|
CSPASSIVE;
|
123 |
|
|
return(SPDR);
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
void enc28j60WriteOp(uint8_t op, uint8_t address, uint8_t data)
|
127 |
|
|
{
|
128 |
|
|
CSACTIVE;
|
129 |
|
|
// issue write command
|
130 |
|
|
SPDR = op | (address & ADDR_MASK);
|
131 |
|
|
waitspi();
|
132 |
|
|
// write data
|
133 |
|
|
SPDR = data;
|
134 |
|
|
waitspi();
|
135 |
|
|
CSPASSIVE;
|
136 |
|
|
}
|
137 |
|
|
|
138 |
|
|
void enc28j60ReadBuffer(uint16_t len, uint8_t* data)
|
139 |
|
|
{
|
140 |
|
|
CSACTIVE;
|
141 |
|
|
// issue read command
|
142 |
|
|
SPDR = ENC28J60_READ_BUF_MEM;
|
143 |
|
|
waitspi();
|
144 |
|
|
while(len)
|
145 |
|
|
{
|
146 |
|
|
len--;
|
147 |
|
|
// read data
|
148 |
|
|
SPDR = 0x00;
|
149 |
|
|
waitspi();
|
150 |
|
|
*data = SPDR;
|
151 |
|
|
data++;
|
152 |
|
|
}
|
153 |
|
|
// This is nonsence : *data='\0';
|
154 |
|
|
CSPASSIVE;
|
155 |
|
|
}
|
156 |
|
|
|
157 |
|
|
void enc28j60WriteBuffer(uint16_t len, uint8_t* data)
|
158 |
|
|
{
|
159 |
|
|
CSACTIVE;
|
160 |
|
|
// issue write command
|
161 |
|
|
SPDR = ENC28J60_WRITE_BUF_MEM;
|
162 |
|
|
waitspi();
|
163 |
|
|
while(len)
|
164 |
|
|
{
|
165 |
|
|
len--;
|
166 |
|
|
// write data
|
167 |
|
|
SPDR = *data;
|
168 |
|
|
data++;
|
169 |
|
|
waitspi();
|
170 |
|
|
}
|
171 |
|
|
CSPASSIVE;
|
172 |
|
|
}
|
173 |
|
|
|
174 |
|
|
void enc28j60SetBank(uint8_t address)
|
175 |
|
|
{
|
176 |
|
|
// set the bank (if needed)
|
177 |
|
|
if((address & BANK_MASK) != Enc28j60Bank)
|
178 |
|
|
{
|
179 |
|
|
// set the bank
|
180 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
|
181 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
|
182 |
|
|
Enc28j60Bank = (address & BANK_MASK);
|
183 |
|
|
}
|
184 |
|
|
}
|
185 |
|
|
|
186 |
|
|
uint8_t enc28j60Read(uint8_t address)
|
187 |
|
|
{
|
188 |
|
|
// set the bank
|
189 |
|
|
enc28j60SetBank(address);
|
190 |
|
|
// do the read
|
191 |
|
|
return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
|
192 |
|
|
}
|
193 |
|
|
|
194 |
|
|
void enc28j60Write(uint8_t address, uint8_t data)
|
195 |
|
|
{
|
196 |
|
|
// set the bank
|
197 |
|
|
enc28j60SetBank(address);
|
198 |
|
|
// do the write
|
199 |
|
|
enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
|
200 |
|
|
}
|
201 |
|
|
|
202 |
|
|
void enc28j60PhyWrite(uint8_t address, uint16_t data)
|
203 |
|
|
{
|
204 |
|
|
// set the PHY register address
|
205 |
|
|
enc28j60Write(MIREGADR, address);
|
206 |
|
|
// write the PHY data
|
207 |
|
|
enc28j60Write(MIWRL, data);
|
208 |
|
|
enc28j60Write(MIWRH, data>>8);
|
209 |
|
|
// wait until the PHY write completes
|
210 |
|
|
while(enc28j60Read(MISTAT) & MISTAT_BUSY){
|
211 |
|
|
_delay_us(15);
|
212 |
|
|
}
|
213 |
|
|
}
|
214 |
|
|
|
215 |
|
|
|
216 |
|
|
//Run configure_spi() to setup the SPI port before initializing the ethernet controller.
|
217 |
|
|
void enc28j60Init()
|
218 |
|
|
{
|
219 |
|
|
|
220 |
|
|
/* // initialize I/O
|
221 |
|
|
ENC28J60_CONTROL_DDR |= (1<<ENC28J60_CONTROL_CS);
|
222 |
|
|
ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
|
223 |
|
|
CSPASSIVE;
|
224 |
|
|
|
225 |
|
|
// Disable powersaving
|
226 |
|
|
PRR0 &= ~(1<<PRSPI);
|
227 |
|
|
|
228 |
|
|
// setup SPI I/O pins
|
229 |
|
|
// SCK should be low!
|
230 |
|
|
ENC28J60_SPI_PORT &= ~(1<<ENC28J60_SPI_SCK);
|
231 |
|
|
ENC28J60_SPI_DDR |= (1<<ENC28J60_SPI_SCK); // set SCK as output
|
232 |
|
|
ENC28J60_SPI_DDR &= ~(1<<ENC28J60_SPI_MISO); // set MISO as input
|
233 |
|
|
ENC28J60_SPI_DDR |= ~(1<<ENC28J60_SPI_MOSI); // set MOSI as output
|
234 |
|
|
ENC28J60_SPI_PORT &= ~(1<<ENC28J60_SPI_MOSI); // set MOSI low
|
235 |
|
|
ENC28J60_SPI_DDR |= ~(1<<ENC28J60_SPI_SS); // SS must be output for Master mode to work
|
236 |
|
|
// initialize SPI interface
|
237 |
|
|
// master mode
|
238 |
|
|
// select clock phase positive-going in middle of data
|
239 |
|
|
// select clock phase
|
240 |
|
|
// Data order MSB first
|
241 |
|
|
// switch to f/4 2X = f/2 bitrate
|
242 |
|
|
// No dual datarate
|
243 |
|
|
|
244 |
|
|
SPCR = (1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<DORD)|(0<<SPR0)|(1<<SPR1)|(0<<SPI2X)|(1<<SPE);
|
245 |
|
|
*/
|
246 |
|
|
// perform system reset
|
247 |
|
|
enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
|
248 |
|
|
_delay_ms(50);
|
249 |
|
|
// check CLKRDY bit to see if reset is complete
|
250 |
|
|
// The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
|
251 |
|
|
//while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
|
252 |
|
|
// do bank 0 stuff
|
253 |
|
|
// initialize receive buffer
|
254 |
|
|
// 16-bit transfers, must write low byte first
|
255 |
|
|
// set receive buffer start address
|
256 |
|
|
NextPacketPtr = RXSTART_INIT;
|
257 |
|
|
// Rx start
|
258 |
|
|
enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
|
259 |
|
|
enc28j60Write(ERXSTH, RXSTART_INIT>>8);
|
260 |
|
|
// set receive pointer address
|
261 |
|
|
enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
|
262 |
|
|
enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
|
263 |
|
|
// RX end
|
264 |
|
|
enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
|
265 |
|
|
enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
|
266 |
|
|
// TX start
|
267 |
|
|
enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
|
268 |
|
|
enc28j60Write(ETXSTH, TXSTART_INIT>>8);
|
269 |
|
|
// TX end
|
270 |
|
|
enc28j60Write(ETXNDL, TXSTOP_INIT&0xFF);
|
271 |
|
|
enc28j60Write(ETXNDH, TXSTOP_INIT>>8);
|
272 |
|
|
// do bank 1 stuff, packet filter:
|
273 |
|
|
// For broadcast packets we allow only ARP packtets
|
274 |
|
|
// All other packets should be unicast only for our mac (MAADR)
|
275 |
|
|
//
|
276 |
|
|
// The pattern to match on is therefore
|
277 |
|
|
// Type ETH.DST
|
278 |
|
|
// ARP BROADCAST
|
279 |
|
|
// 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
|
280 |
|
|
// in binary these poitions are:11 0000 0011 1111
|
281 |
|
|
// This is hex 303F->EPMM0=0x3f,EPMM1=0x30
|
282 |
|
|
enc28j60Write(ERXFCON, 0); //Disable packet filter
|
283 |
|
|
// enc28j60Write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);
|
284 |
|
|
// enc28j60Write(EPMM0, 0x3f);
|
285 |
|
|
// enc28j60Write(EPMM1, 0x30);
|
286 |
|
|
// enc28j60Write(EPMCSL, 0xf9);
|
287 |
|
|
// enc28j60Write(EPMCSH, 0xf7);
|
288 |
|
|
//
|
289 |
|
|
//
|
290 |
|
|
// do bank 2 stuff
|
291 |
|
|
// enable MAC receive
|
292 |
|
|
enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
|
293 |
|
|
// bring MAC out of reset
|
294 |
|
|
enc28j60Write(MACON2, 0x00);
|
295 |
|
|
// enable automatic padding to 60bytes and CRC operations
|
296 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
|
297 |
|
|
// set inter-frame gap (non-back-to-back)
|
298 |
|
|
enc28j60Write(MAIPGL, 0x12);
|
299 |
|
|
enc28j60Write(MAIPGH, 0x0C);
|
300 |
|
|
// set inter-frame gap (back-to-back)
|
301 |
|
|
enc28j60Write(MABBIPG, 0x12);
|
302 |
|
|
// Set the maximum packet size which the controller will accept
|
303 |
|
|
// Do not send packets longer than MAX_FRAMELEN:
|
304 |
|
|
enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);
|
305 |
|
|
enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
|
306 |
|
|
// do bank 3 stuff
|
307 |
|
|
// write MAC address
|
308 |
|
|
// NOTE: MAC address in ENC28J60 is byte-backward
|
309 |
|
|
enc28j60Write(MAADR5, ENC28J60_MAC0);
|
310 |
|
|
enc28j60Write(MAADR4, ENC28J60_MAC1);
|
311 |
|
|
enc28j60Write(MAADR3, ENC28J60_MAC2);
|
312 |
|
|
enc28j60Write(MAADR2, ENC28J60_MAC3);
|
313 |
|
|
enc28j60Write(MAADR1, ENC28J60_MAC4);
|
314 |
|
|
enc28j60Write(MAADR0, ENC28J60_MAC5);
|
315 |
|
|
// no loopback of transmitted frames
|
316 |
|
|
enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
|
317 |
|
|
// switch to bank 0
|
318 |
|
|
enc28j60SetBank(ECON1);
|
319 |
|
|
// enable interrutps
|
320 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
|
321 |
|
|
// enable packet reception
|
322 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
|
323 |
|
|
}
|
324 |
|
|
|
325 |
|
|
// read the revision of the chip:
|
326 |
|
|
uint8_t enc28j60getrev(void)
|
327 |
|
|
{
|
328 |
|
|
return(enc28j60Read(EREVID));
|
329 |
|
|
}
|
330 |
|
|
|
331 |
|
|
void enc28j60PacketSend(uint16_t len, uint8_t* packet)
|
332 |
|
|
{
|
333 |
|
|
// Set the write pointer to start of transmit buffer area
|
334 |
|
|
enc28j60Write(EWRPTL, TXSTART_INIT&0xFF);
|
335 |
|
|
enc28j60Write(EWRPTH, TXSTART_INIT>>8);
|
336 |
|
|
// Set the TXND pointer to correspond to the packet size given
|
337 |
|
|
enc28j60Write(ETXNDL, (TXSTART_INIT+len)&0xFF);
|
338 |
|
|
enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
|
339 |
|
|
// write per-packet control byte (0x00 means use macon3 settings)
|
340 |
|
|
enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
|
341 |
|
|
// copy the packet into the transmit buffer
|
342 |
|
|
enc28j60WriteBuffer(len, packet);
|
343 |
|
|
// send the contents of the transmit buffer onto the network
|
344 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
|
345 |
|
|
// Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
|
346 |
|
|
if( (enc28j60Read(EIR) & EIR_TXERIF) ){
|
347 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
|
348 |
|
|
}
|
349 |
|
|
}
|
350 |
|
|
|
351 |
|
|
void enc28j60PacketSendTwo(uint16_t len1, uint8_t* packet1, uint16_t len2, uint8_t* packet2)
|
352 |
|
|
{
|
353 |
|
|
//Errata: Transmit Logic reset
|
354 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST);
|
355 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST);
|
356 |
|
|
|
357 |
|
|
// Set the write pointer to start of transmit buffer area
|
358 |
|
|
enc28j60Write(EWRPTL, TXSTART_INIT&0xff);
|
359 |
|
|
enc28j60Write(EWRPTH, TXSTART_INIT>>8);
|
360 |
|
|
// Set the TXND pointer to correspond to the packet size given
|
361 |
|
|
enc28j60Write(ETXNDL, (TXSTART_INIT+len1+len2));
|
362 |
|
|
enc28j60Write(ETXNDH, (TXSTART_INIT+len1+len2)>>8);
|
363 |
|
|
|
364 |
|
|
// write per-packet control byte
|
365 |
|
|
enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
|
366 |
|
|
|
367 |
|
|
// copy the packet into the transmit buffer
|
368 |
|
|
enc28j60WriteBuffer(len1, packet1);
|
369 |
|
|
if(len2>0) enc28j60WriteBuffer(len2, packet2);
|
370 |
|
|
|
371 |
|
|
// send the contents of the transmit buffer onto the network
|
372 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
|
373 |
|
|
}
|
374 |
|
|
|
375 |
|
|
// Gets a packet from the network receive buffer, if one is available.
|
376 |
|
|
// The packet will by headed by an ethernet header.
|
377 |
|
|
// maxlen The maximum acceptable length of a retrieved packet.
|
378 |
|
|
// packet Pointer where packet data should be stored.
|
379 |
|
|
// Returns: Packet length in bytes if a packet was retrieved, zero otherwise.
|
380 |
|
|
uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet)
|
381 |
|
|
{
|
382 |
|
|
uint16_t rxstat;
|
383 |
|
|
uint16_t len;
|
384 |
|
|
// check if a packet has been received and buffered
|
385 |
|
|
//if( !(enc28j60Read(EIR) & EIR_PKTIF) ){
|
386 |
|
|
// The above does not work. See Rev. B4 Silicon Errata point 6.
|
387 |
|
|
if( enc28j60Read(EPKTCNT) ==0 ){
|
388 |
|
|
return(0);
|
389 |
|
|
}
|
390 |
|
|
|
391 |
|
|
// Set the read pointer to the start of the received packet
|
392 |
|
|
enc28j60Write(ERDPTL, (NextPacketPtr));
|
393 |
|
|
enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
|
394 |
|
|
// read the next packet pointer
|
395 |
|
|
NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
|
396 |
|
|
NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
|
397 |
|
|
// read the packet length (see datasheet page 43)
|
398 |
|
|
len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
|
399 |
|
|
len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
|
400 |
|
|
len-=4; //remove the CRC count
|
401 |
|
|
// read the receive status (see datasheet page 43)
|
402 |
|
|
rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
|
403 |
|
|
rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
|
404 |
|
|
// limit retrieve length
|
405 |
|
|
if (len>maxlen-1){
|
406 |
|
|
len=maxlen-1;
|
407 |
|
|
}
|
408 |
|
|
// check CRC and symbol errors (see datasheet page 44, table 7-3):
|
409 |
|
|
// The ERXFCON.CRCEN is set by default. Normally we should not
|
410 |
|
|
// need to check this.
|
411 |
|
|
if ((rxstat & 0x80)==0){
|
412 |
|
|
// invalid
|
413 |
|
|
len=0;
|
414 |
|
|
}else{
|
415 |
|
|
// copy the packet from the receive buffer
|
416 |
|
|
enc28j60ReadBuffer(len, packet);
|
417 |
|
|
}
|
418 |
|
|
// Move the RX read pointer to the start of the next received packet
|
419 |
|
|
// This frees the memory we just read out
|
420 |
|
|
enc28j60Write(ERXRDPTL, (NextPacketPtr));
|
421 |
|
|
enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
|
422 |
|
|
// decrement the packet counter indicate we are done with this packet
|
423 |
|
|
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
|
424 |
|
|
return(len);
|
425 |
|
|
}
|
426 |
|
|
|
427 |
|
|
|
428 |
|
|
/*struct igordev igordev_ethernet = {
|
429 |
|
|
.init = nicInit,
|
430 |
|
|
.deinit = nicDeinit,
|
431 |
|
|
.read = nicRead,
|
432 |
|
|
.write = nicWrite,
|
433 |
|
|
.read_status = nicReadStatus,
|
434 |
|
|
.write_status = nicWriteStatus,
|
435 |
|
|
.idata = &idata
|
436 |
|
|
};*/
|