?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

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

Powered by WebSVN v2.8.3