OpenCores
URL https://opencores.org/ocsvn/igor/igor/trunk

Subversion Repositories igor

[/] [igor/] [trunk/] [avr/] [eth-test/] [dev/] [enc28j60.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
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
};*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.