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

Subversion Repositories igor

[/] [igor/] [trunk/] [avr/] [premade/] [net/] [enc28j60.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 atypic
/*! \file enc28j60.c \brief Microchip ENC28J60 Ethernet Interface Driver. */
2
//*****************************************************************************
3
//
4
// File Name    : 'enc28j60.c'
5
// Title                : Microchip ENC28J60 Ethernet Interface Driver
6
// Author               : Pascal Stang (c)2005
7
// Created              : 9/22/2005
8
// Revised              : 9/22/2005
9
// Version              : 0.1
10
// Target MCU   : Atmel AVR series
11
// Editor Tabs  : 4
12
//
13
// Description  : This driver provides initialization and transmit/receive
14
//      functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY.
15
// This chip is novel in that it is a full MAC+PHY interface all in a 28-pin
16
// chip, using an SPI interface to the host processor.
17
//
18
//*****************************************************************************
19
 
20
#include "avr/io.h"
21
 
22
#include "global.h"
23
#include "timer.h"
24
#include "rprintf.h"
25
 
26
#include "enc28j60.h"
27
/*
28
#ifdef SPDR0
29
        #define SPDR    SPDR0
30
        #define SPCR    SPCR0
31
        #define SPSR    SPSR0
32
 
33
        #define SPIF    SPIF0
34
        #define MSTR    MSTR0
35
        #define CPOL    CPOL0
36
 
37
        #define DORD    DORD0
38
        #define SPR0    SPR00
39
        #define SPR1    SPR01
40
        #define SPI2X   SPI2X0
41
        #define SPE             SPE0
42
#endif
43
*/
44
// include configuration
45
#include "enc28j60conf.h"
46
 
47
u08 Enc28j60Bank;
48
u16 NextPacketPtr;
49
 
50
void nicInit(void)
51
{
52
        enc28j60Init();
53
}
54
 
55
void nicSend(unsigned int len, unsigned char* packet)
56
{
57
        enc28j60PacketSend(len, packet);
58
}
59
 
60
unsigned int nicPoll(unsigned int maxlen, unsigned char* packet)
61
{
62
        return enc28j60PacketReceive(maxlen, packet);
63
}
64
 
65
void nicGetMacAddress(u08* macaddr)
66
{
67
        // read MAC address registers
68
        // NOTE: MAC address in ENC28J60 is byte-backward
69
        *macaddr++ = enc28j60Read(MAADR5);
70
        *macaddr++ = enc28j60Read(MAADR4);
71
        *macaddr++ = enc28j60Read(MAADR3);
72
        *macaddr++ = enc28j60Read(MAADR2);
73
        *macaddr++ = enc28j60Read(MAADR1);
74
        *macaddr++ = enc28j60Read(MAADR0);
75
}
76
 
77
void nicSetMacAddress(u08* macaddr)
78
{
79
        // write MAC address
80
        // NOTE: MAC address in ENC28J60 is byte-backward
81
        enc28j60Write(MAADR5, *macaddr++);
82
        enc28j60Write(MAADR4, *macaddr++);
83
        enc28j60Write(MAADR3, *macaddr++);
84
        enc28j60Write(MAADR2, *macaddr++);
85
        enc28j60Write(MAADR1, *macaddr++);
86
        enc28j60Write(MAADR0, *macaddr++);
87
}
88
 
89
void nicRegDump(void)
90
{
91
        enc28j60RegDump();
92
}
93
 
94
/*
95
void ax88796SetupPorts(void)
96
{
97
#if NIC_CONNECTION == MEMORY_MAPPED
98
        // enable external SRAM interface - no wait states
99
        sbi(MCUCR, SRE);
100
//      sbi(MCUCR, SRW10);
101
//      sbi(XMCRA, SRW00);
102
//      sbi(XMCRA, SRW01);
103
//      sbi(XMCRA, SRW11);
104
#else
105
        // set address port to output
106
        AX88796_ADDRESS_DDR = AX88796_ADDRESS_MASK;
107
 
108
        // set data port to input with pull-ups
109
        AX88796_DATA_DDR = 0x00;
110
        AX88796_DATA_PORT = 0xFF;
111
 
112
        // initialize the control port read and write pins to de-asserted
113
        sbi( AX88796_CONTROL_PORT, AX88796_CONTROL_READPIN );
114
        sbi( AX88796_CONTROL_PORT, AX88796_CONTROL_WRITEPIN );
115
        // set the read and write pins to output
116
        sbi( AX88796_CONTROL_DDR, AX88796_CONTROL_READPIN );
117
        sbi( AX88796_CONTROL_DDR, AX88796_CONTROL_WRITEPIN );
118
#endif
119
        // set reset pin to output
120
        sbi( AX88796_RESET_DDR, AX88796_RESET_PIN );
121
}
122
*/
123
 
124
u08 enc28j60ReadOp(u08 op, u08 address)
125
{
126
        u08 data;
127
 
128
        // assert CS
129
        ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
130
 
131
        // issue read command
132
        SPDR = op | (address & ADDR_MASK);
133
        while(!(SPSR & (1<<SPIF)));
134
        // read data
135
        SPDR = 0x00;
136
        while(!(SPSR & (1<<SPIF)));
137
        // do dummy read if needed
138
        if(address & 0x80)
139
        {
140
                SPDR = 0x00;
141
                while(!(inb(SPSR) & (1<<SPIF)));
142
        }
143
        data = SPDR;
144
 
145
        // release CS
146
        ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
147
 
148
        return data;
149
}
150
 
151
void enc28j60WriteOp(u08 op, u08 address, u08 data)
152
{
153
        // assert CS
154
        ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
155
 
156
        // issue write command
157
        SPDR = op | (address & ADDR_MASK);
158
        while(!(SPSR & (1<<SPIF)));
159
        // write data
160
        SPDR = data;
161
        while(!(SPSR & (1<<SPIF)));
162
 
163
        // release CS
164
        ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
165
}
166
 
167
void enc28j60ReadBuffer(u16 len, u08* data)
168
{
169
        // assert CS
170
        ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
171
 
172
        // issue read command
173
        SPDR = ENC28J60_READ_BUF_MEM;
174
        while(!(SPSR & (1<<SPIF)));
175
        while(len--)
176
        {
177
                // read data
178
                SPDR = 0x00;
179
                while(!(SPSR & (1<<SPIF)));
180
                *data++ = SPDR;
181
        }
182
        // release CS
183
        ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
184
}
185
 
186
void enc28j60WriteBuffer(u16 len, u08* data)
187
{
188
        // assert CS
189
        ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS);
190
 
191
        // issue write command
192
        SPDR = ENC28J60_WRITE_BUF_MEM;
193
        while(!(SPSR & (1<<SPIF)));
194
        while(len--)
195
        {
196
                // write data
197
                SPDR = *data++;
198
                while(!(SPSR & (1<<SPIF)));
199
        }
200
        // release CS
201
        ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS);
202
}
203
 
204
void enc28j60SetBank(u08 address)
205
{
206
        // set the bank (if needed)
207
        if((address & BANK_MASK) != Enc28j60Bank)
208
        {
209
                // set the bank
210
                enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
211
                enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
212
                Enc28j60Bank = (address & BANK_MASK);
213
        }
214
}
215
 
216
u08 enc28j60Read(u08 address)
217
{
218
        // set the bank
219
        enc28j60SetBank(address);
220
        // do the read
221
        return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
222
}
223
 
224
void enc28j60Write(u08 address, u08 data)
225
{
226
        // set the bank
227
        enc28j60SetBank(address);
228
        // do the write
229
        enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
230
}
231
 
232
u16 enc28j60PhyRead(u08 address)
233
{
234
        u16 data;
235
 
236
        // Set the right address and start the register read operation
237
        enc28j60Write(MIREGADR, address);
238
        enc28j60Write(MICMD, MICMD_MIIRD);
239
 
240
        // wait until the PHY read completes
241
        while(enc28j60Read(MISTAT) & MISTAT_BUSY);
242
 
243
        // quit reading
244
        enc28j60Write(MICMD, 0x00);
245
 
246
        // get data value
247
        data  = enc28j60Read(MIRDL);
248
        data |= enc28j60Read(MIRDH);
249
        // return the data
250
        return data;
251
}
252
 
253
void enc28j60PhyWrite(u08 address, u16 data)
254
{
255
        // set the PHY register address
256
        enc28j60Write(MIREGADR, address);
257
 
258
        // write the PHY data
259
        enc28j60Write(MIWRL, data);
260
        enc28j60Write(MIWRH, data>>8);
261
 
262
        // wait until the PHY write completes
263
        while(enc28j60Read(MISTAT) & MISTAT_BUSY);
264
}
265
 
266
void enc28j60Init(void)
267
{
268
        // initialize I/O
269
        sbi(ENC28J60_CONTROL_DDR, ENC28J60_CONTROL_CS);
270
        sbi(ENC28J60_CONTROL_PORT, ENC28J60_CONTROL_CS);
271
 
272
        // setup SPI I/O pins
273
        // SCK should be low!
274
        cbi(ENC28J60_SPI_PORT, ENC28J60_SPI_SCK);       // set SCK hi
275
        sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SCK);        // set SCK as output
276
        cbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MISO);       // set MISO as input
277
        sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MOSI);       // set MOSI as output
278
        sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SS);         // SS must be output for Master mode to work
279
        // initialize SPI interface
280
        // master mode
281
        sbi(SPCR, MSTR);
282
        // select clock phase positive-going in middle of data
283
        cbi(SPCR, CPOL);
284
        // select clock phase
285
        cbi(SPCR, CPHA);
286
        // Data order MSB first
287
        cbi(SPCR,DORD);
288
        // switch to f/4 2X = f/2 bitrate
289
        cbi(SPCR, SPR0);
290
        sbi(SPCR, SPR1);
291
        // No dual datarate
292
        cbi(SPSR, SPI2X);
293
        // enable SPI
294
        sbi(SPCR, SPE);
295
 
296
        // perform system reset
297
        enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
298
        // check CLKRDY bit to see if reset is complete
299
        delay_us(50);
300
        while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
301
 
302
        // do bank 0 stuff
303
        // initialize receive buffer
304
        // 16-bit transfers, must write low byte first
305
        // set receive buffer start address
306
        NextPacketPtr = RXSTART_INIT;
307
        enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
308
        enc28j60Write(ERXSTH, RXSTART_INIT>>8);
309
        // set receive pointer address
310
        enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
311
        enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);
312
        // set receive buffer end
313
        // ERXND defaults to 0x1FFF (end of ram)
314
        enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
315
        enc28j60Write(ERXNDH, RXSTOP_INIT>>8);
316
        // set transmit buffer start
317
        // ETXST defaults to 0x0000 (beginnging of ram)
318
        enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
319
        enc28j60Write(ETXSTH, TXSTART_INIT>>8);
320
 
321
        // do bank 2 stuff
322
        // enable MAC receive
323
        enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
324
        // bring MAC out of reset
325
        enc28j60Write(MACON2, 0x00);
326
        // enable automatic padding and CRC operations
327
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
328
//      enc28j60Write(MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
329
        // set inter-frame gap (non-back-to-back)
330
        enc28j60Write(MAIPGL, 0x12);
331
        enc28j60Write(MAIPGH, 0x0C);
332
        // set inter-frame gap (back-to-back)
333
        enc28j60Write(MABBIPG, 0x12);
334
        // Set the maximum packet size which the controller will accept
335
        enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);
336
        enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);
337
 
338
        // do bank 3 stuff
339
        // write MAC address
340
        // NOTE: MAC address in ENC28J60 is byte-backward
341
        enc28j60Write(MAADR5, ENC28J60_MAC0);
342
        enc28j60Write(MAADR4, ENC28J60_MAC1);
343
        enc28j60Write(MAADR3, ENC28J60_MAC2);
344
        enc28j60Write(MAADR2, ENC28J60_MAC3);
345
        enc28j60Write(MAADR1, ENC28J60_MAC4);
346
        enc28j60Write(MAADR0, ENC28J60_MAC5);
347
 
348
        // no loopback of transmitted frames
349
        enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
350
 
351
        // switch to bank 0
352
        enc28j60SetBank(ECON1);
353
        // enable interrutps
354
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
355
        // enable packet reception
356
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
357
/*
358
        enc28j60PhyWrite(PHLCON, 0x0AA2);
359
 
360
        // setup duplex ----------------------
361
 
362
        // Disable receive logic and abort any packets currently being transmitted
363
        enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS|ECON1_RXEN);
364
 
365
        {
366
                u16 temp;
367
                // Set the PHY to the proper duplex mode
368
                temp = enc28j60PhyRead(PHCON1);
369
                temp &= ~PHCON1_PDPXMD;
370
                enc28j60PhyWrite(PHCON1, temp);
371
                // Set the MAC to the proper duplex mode
372
                temp = enc28j60Read(MACON3);
373
                temp &= ~MACON3_FULDPX;
374
                enc28j60Write(MACON3, temp);
375
        }
376
 
377
        // Set the back-to-back inter-packet gap time to IEEE specified
378
        // requirements.  The meaning of the MABBIPG value changes with the duplex
379
        // state, so it must be updated in this function.
380
        // In full duplex, 0x15 represents 9.6us; 0x12 is 9.6us in half duplex
381
        //enc28j60Write(MABBIPG, DuplexState ? 0x15 : 0x12);
382
 
383
        // Reenable receive logic
384
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
385
 
386
        // setup duplex ----------------------
387
*/
388
}
389
 
390
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
391
{
392
        // Set the write pointer to start of transmit buffer area
393
        enc28j60Write(EWRPTL, TXSTART_INIT);
394
        enc28j60Write(EWRPTH, TXSTART_INIT>>8);
395
        // Set the TXND pointer to correspond to the packet size given
396
        enc28j60Write(ETXNDL, (TXSTART_INIT+len));
397
        enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
398
 
399
        // write per-packet control byte
400
        enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
401
 
402
        // copy the packet into the transmit buffer
403
        enc28j60WriteBuffer(len, packet);
404
 
405
        // send the contents of the transmit buffer onto the network
406
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
407
}
408
 
409
unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet)
410
{
411
        u16 rxstat;
412
        u16 len;
413
 
414
        // check if a packet has been received and buffered
415
//      if( !(enc28j60Read(EIR) & EIR_PKTIF) )
416
        if( !enc28j60Read(EPKTCNT) )
417
                return 0;
418
 
419
        // Make absolutely certain that any previous packet was discarded       
420
        //if( WasDiscarded == FALSE)
421
        //      MACDiscardRx();
422
 
423
        // Set the read pointer to the start of the received packet
424
        enc28j60Write(ERDPTL, (NextPacketPtr));
425
        enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
426
        // read the next packet pointer
427
        NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
428
        NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
429
        // read the packet length
430
        len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
431
        len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
432
        // read the receive status
433
        rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
434
        rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
435
 
436
        // limit retrieve length
437
        // (we reduce the MAC-reported length by 4 to remove the CRC)
438
        len = MIN(len, maxlen);
439
 
440
        // copy the packet from the receive buffer
441
        enc28j60ReadBuffer(len, packet);
442
 
443
        // Move the RX read pointer to the start of the next received packet
444
        // This frees the memory we just read out
445
        enc28j60Write(ERXRDPTL, (NextPacketPtr));
446
        enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
447
 
448
        // decrement the packet counter indicate we are done with this packet
449
        enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
450
 
451
        return len;
452
}
453
 
454
void enc28j60ReceiveOverflowRecover(void)
455
{
456
        // receive buffer overflow handling procedure
457
 
458
        // recovery completed
459
}
460
 
461
void enc28j60RegDump(void)
462
{
463
//      unsigned char macaddr[6];
464
//      result = ax88796Read(TR);
465
 
466
//      rprintf("Media State: ");
467
//      if(!(result & AUTOD))
468
//              rprintf("Autonegotiation\r\n");
469
//      else if(result & RST_B)
470
//              rprintf("PHY in Reset   \r\n");
471
//      else if(!(result & RST_10B))
472
//              rprintf("10BASE-T       \r\n");
473
//      else if(!(result & RST_TXB))
474
//              rprintf("100BASE-T      \r\n");
475
 
476
        rprintf("RevID: 0x%x\r\n", enc28j60Read(EREVID));
477
 
478
        rprintfProgStrM("Cntrl: ECON1 ECON2 ESTAT  EIR  EIE\r\n");
479
        rprintfProgStrM("         ");
480
        rprintfu08(enc28j60Read(ECON1));
481
        rprintfProgStrM("    ");
482
        rprintfu08(enc28j60Read(ECON2));
483
        rprintfProgStrM("    ");
484
        rprintfu08(enc28j60Read(ESTAT));
485
        rprintfProgStrM("    ");
486
        rprintfu08(enc28j60Read(EIR));
487
        rprintfProgStrM("   ");
488
        rprintfu08(enc28j60Read(EIE));
489
        rprintfCRLF();
490
 
491
        rprintfProgStrM("MAC  : MACON1  MACON2  MACON3  MACON4  MAC-Address\r\n");
492
        rprintfProgStrM("        0x");
493
        rprintfu08(enc28j60Read(MACON1));
494
        rprintfProgStrM("    0x");
495
        rprintfu08(enc28j60Read(MACON2));
496
        rprintfProgStrM("    0x");
497
        rprintfu08(enc28j60Read(MACON3));
498
        rprintfProgStrM("    0x");
499
        rprintfu08(enc28j60Read(MACON4));
500
        rprintfProgStrM("   ");
501
        rprintfu08(enc28j60Read(MAADR5));
502
        rprintfu08(enc28j60Read(MAADR4));
503
        rprintfu08(enc28j60Read(MAADR3));
504
        rprintfu08(enc28j60Read(MAADR2));
505
        rprintfu08(enc28j60Read(MAADR1));
506
        rprintfu08(enc28j60Read(MAADR0));
507
        rprintfCRLF();
508
 
509
        rprintfProgStrM("Rx   : ERXST  ERXND  ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL\r\n");
510
        rprintfProgStrM("       0x");
511
        rprintfu08(enc28j60Read(ERXSTH));
512
        rprintfu08(enc28j60Read(ERXSTL));
513
        rprintfProgStrM(" 0x");
514
        rprintfu08(enc28j60Read(ERXNDH));
515
        rprintfu08(enc28j60Read(ERXNDL));
516
        rprintfProgStrM("  0x");
517
        rprintfu08(enc28j60Read(ERXWRPTH));
518
        rprintfu08(enc28j60Read(ERXWRPTL));
519
        rprintfProgStrM("  0x");
520
        rprintfu08(enc28j60Read(ERXRDPTH));
521
        rprintfu08(enc28j60Read(ERXRDPTL));
522
        rprintfProgStrM("   0x");
523
        rprintfu08(enc28j60Read(ERXFCON));
524
        rprintfProgStrM("    0x");
525
        rprintfu08(enc28j60Read(EPKTCNT));
526
        rprintfProgStrM("  0x");
527
        rprintfu08(enc28j60Read(MAMXFLH));
528
        rprintfu08(enc28j60Read(MAMXFLL));
529
        rprintfCRLF();
530
 
531
        rprintfProgStrM("Tx   : ETXST  ETXND  MACLCON1 MACLCON2 MAPHSUP\r\n");
532
        rprintfProgStrM("       0x");
533
        rprintfu08(enc28j60Read(ETXSTH));
534
        rprintfu08(enc28j60Read(ETXSTL));
535
        rprintfProgStrM(" 0x");
536
        rprintfu08(enc28j60Read(ETXNDH));
537
        rprintfu08(enc28j60Read(ETXNDL));
538
        rprintfProgStrM("   0x");
539
        rprintfu08(enc28j60Read(MACLCON1));
540
        rprintfProgStrM("     0x");
541
        rprintfu08(enc28j60Read(MACLCON2));
542
        rprintfProgStrM("     0x");
543
        rprintfu08(enc28j60Read(MAPHSUP));
544
        rprintfCRLF();
545
 
546
        rprintfProgStrM("EREVID\r\n");
547
        rprintfProgStrM("       0x");
548
        rprintfu08(enc28j60Read(EREVID));
549
 
550
        delay_ms(25);
551
}
552
 
553
 
554
 

powered by: WebSVN 2.1.0

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