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

Subversion Repositories igor

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

powered by: WebSVN 2.1.0

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