1 /******************************************************************************
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 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Based on the enc28j60.c file from the AVRlib library by Pascal Stang.
9 * For AVRlib See http://www.procyonengineering.com/
10 * Used with explicit permission of Pascal Stang.
11 *
12 * Title: Microchip ENC28J60 Ethernet Interface Driver
13 * Chip type : ATMEGA88 with ENC28J60
14 *******************************************************************************/
15
16 #include "ENC28J60.H"
17 #include "SPI.H"
18
19 static u8 Enc28j60Bank;
20 static u16 NextPacketPtr;
21
22 /*
23 * º¯ÊýÃû£ºenc28j60ReadOp
24 * ÃèÊö £º¶Á¿ØÖƼĴæÆ÷
25 * ÊäÈë £º¶ÁÖ¸ÁµØÖ·
26 * Êä³ö £º¼Ä´æÆ÷ÄÚÈÝ
27 */
28 u8 enc28j60ReadOp(u8 op, u8 address)
29 {
30 u8 dat = 0;
31
32 ENC28J60_CSL();
33
34 dat = op | (address & ADDR_MASK);
35 ENC_SPI_ReadWrite(dat);
36 dat = ENC_SPI_ReadWrite(0xFF);
37 // do dummy read if needed (for mac and mii, see datasheet page 29)
38 if (address & 0x80)
39 {
40 dat = ENC_SPI_ReadWrite(0xFF);
41 }
42 // release CS
43 ENC28J60_CSH();
44 return dat;
45 }
46
47 /*
48 * º¯ÊýÃû£ºenc28j60WriteOp
49 * ÃèÊö £ºÏòÒÔÌ«Íø¿ØÖÆÆ÷дÈëÃüÁî
50 * ÊäÈë £ºÎÞ
51 * Êä³ö £ºÎÞ
52 */
53 void enc28j60WriteOp(u8 op, u8 address, u8 data)
54 {
55 u8 dat = 0;
56
57 ENC28J60_CSL();
58 // issue write command
59 dat = op | (address & ADDR_MASK);
60 ENC_SPI_ReadWrite(dat);
61 // write data
62 dat = data;
63 ENC_SPI_ReadWrite(dat);
64 ENC28J60_CSH();
65 }
66
67 /*
68 * º¯ÊýÃû£ºenc28j60ReadBuffer
69 * ÃèÊö £º¶ÁÈ¡bufferµÄÊý¾Ý
70 * ÊäÈë £ºÊý¾Ý³¤¶È£¬´æ·ÅÊý¾ÝµÄÖ¸Õë
71 * Êä³ö £ºÎÞ
72 */
73 void enc28j60ReadBuffer(u16 len, u8* data)
74 {
75 ENC28J60_CSL();
76 // issue read command
77 ENC_SPI_ReadWrite(ENC28J60_READ_BUF_MEM);
78 while (len--)
79 {
80 *data++ = (u8) ENC_SPI_ReadWrite(0);
81 }
82 *data = '\0';
83 ENC28J60_CSH();
84 }
85
86 /*
87 * º¯ÊýÃû£ºenc28j60WriteBuffer
88 * ÃèÊö £ºÏòbufferдÈëÊý¾Ý
89 * ÊäÈë £ºÊý¾Ý³¤¶È£¬´æ·ÅÊý¾ÝµÄÖ¸Õë
90 * Êä³ö £ºÎÞ
91 */
92 void enc28j60WriteBuffer(u16 len, u8* data)
93 {
94 ENC28J60_CSL();
95 // issue write command
96 ENC_SPI_ReadWrite(ENC28J60_WRITE_BUF_MEM);
97
98 while (len--)
99 {
100 ENC_SPI_ReadWrite(*data++);
101 }
102 ENC28J60_CSH();
103 }
104
105 /*
106 * º¯ÊýÃû£ºenc28j60SetBank
107 * ÃèÊö £ºÑ¡¶¨½«Òª²Ù×÷µÄbank
108 * ÊäÈë £º´øÓÐbankÆÁ±ÎÓòµÄ²ÎÊý
109 * Êä³ö £ºÎÞ
110 */
111 void enc28j60SetBank(u8 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 /*
124 * º¯ÊýÃû£ºenc28j60Read
125 * ÃèÊö £º¶ÁÈ¡¿ØÖƼĴæÆ÷µÄÄÚÈÝ
126 * ÊäÈë £º¿ØÖƼĴæÆ÷µÄµØÖ·
127 * Êä³ö £ºÎÞ
128 */
129 u8 enc28j60Read(u8 address)
130 {
131 // set the bank
132 enc28j60SetBank(address);
133 // do the read
134 return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);
135 }
136
137
138 /*
139 * º¯ÊýÃû£ºenc28j60Write
140 * ÃèÊö £ºÐ´ÈëÊý¾Ýµ½¿ØÖƼĴæÆ÷
141 * ÊäÈë £º¿ØÖƼĴæÆ÷µÄµØÖ·£¬ÃüÁî
142 * Êä³ö £ºÎÞ
143 */
144 void enc28j60Write(u8 address, u8 data)
145 {
146 // set the bank
147 enc28j60SetBank(address);
148 // do the write
149 enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);
150 }
151
152 /*
153 * º¯ÊýÃû£ºenc28j60PhyWrite
154 * ÃèÊö £ºÏòphyдÈë¿ØÖƲÎÊý
155 * ÊäÈë £º¼Ä´æÆ÷µÄµØÖ·£¬ÃüÁî
156 * Êä³ö £ºÎÞ
157 */
158 void enc28j60PhyWrite(u8 address, u16 data)
159 {
160 // set the PHY register address
161 enc28j60Write(MIREGADR, address);
162 // write the PHY data
163 enc28j60Write(MIWRL, data);
164 enc28j60Write(MIWRH, data >> 8);
165 // wait until the PHY write completes
166 while (enc28j60Read(MISTAT) & MISTAT_BUSY)
167 {
168 //Del_10us(1);
169 //_nop_();
170 }
171 }
172
173 /*
174 * º¯ÊýÃû£ºenc28j60clkout
175 * ÃèÊö £ºÉèÖÃÊä³öʱÖÓ
176 * ÊäÈë £ºÊ±ÖÓ²ÎÊý
177 * Êä³ö £ºÎÞ
178 */
179 void enc28j60clkout(u8 clk)
180 {
181 //setup clkout: 2 is 12.5MHz:
182 enc28j60Write(ECOCON, clk & 0x7);
183 }
184
185 /*
186 * º¯ÊýÃû£ºenc28j60Init
187 * ÃèÊö £º³õʼ»¯ÒÔÌ«Íø¿ØÖÆÆ÷
188 * ÊäÈë £ºÎÞ
189 * Êä³ö £ºÎÞ
190 */
191 void enc28j60Init(u8 * macaddr)
192 {
193
194 ENC28J60_RSTH();
195 ENC28J60_CSH();
196 enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
197 // Del_1ms(250);
198 // check CLKRDY bit to see if reset is complete
199 // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.
200 //while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));
201 // do bank 0 stuff
202 // initialize receive buffer
203 // 16-bit transfers, must write low byte first
204 // set receive buffer start address
205 NextPacketPtr = RXSTART_INIT;
206 // Rx start
207 enc28j60Write(ERXSTL, RXSTART_INIT & 0xFF);
208 enc28j60Write(ERXSTH, RXSTART_INIT >> 8);
209 // set receive pointer address
210 enc28j60Write(ERXRDPTL, RXSTART_INIT & 0xFF);
211 enc28j60Write(ERXRDPTH, RXSTART_INIT >> 8);
212 // RX end
213 enc28j60Write(ERXNDL, RXSTOP_INIT & 0xFF);
214 enc28j60Write(ERXNDH, RXSTOP_INIT >> 8);
215 // TX start
216 enc28j60Write(ETXSTL, TXSTART_INIT & 0xFF);
217 enc28j60Write(ETXSTH, TXSTART_INIT >> 8);
218 // TX end
219 enc28j60Write(ETXNDL, TXSTOP_INIT & 0xFF);
220 enc28j60Write(ETXNDH, TXSTOP_INIT >> 8);
221 // do bank 1 stuff, packet filter:
222 // For broadcast packets we allow only ARP packtets
223 // All other packets should be unicast only for our mac (MAADR)
224 //
225 // The pattern to match on is therefore
226 // Type ETH.DST
227 // ARP BROADCAST
228 // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
229 // in binary these poitions are:11 0000 0011 1111
230 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
231 enc28j60Write(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);
232 enc28j60Write(EPMM0, 0x3f);
233 enc28j60Write(EPMM1, 0x30);
234 enc28j60Write(EPMCSL, 0xf9);
235 enc28j60Write(EPMCSH, 0xf7);
236 //
237 //
238 // do bank 2 stuff
239 // enable MAC receive
240 enc28j60Write(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);
241 // bring MAC out of reset
242 enc28j60Write(MACON2, 0x00);
243 // enable automatic padding to 60bytes and CRC operations
244 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX );//MACON3_HFRMLEN
245 // set inter-frame gap (non-back-to-back)
246 enc28j60Write(MAIPGL, 0x12);
247 enc28j60Write(MAIPGH, 0x0C);
248 // set inter-frame gap (back-to-back)
249 enc28j60Write(MABBIPG, 0x12);
250 // Set the maximum packet size which the controller will accept
251 // Do not send packets longer than MAX_FRAMELEN:
252 enc28j60Write(MAMXFLL, MAX_FRAMELEN & 0xFF);
253 enc28j60Write(MAMXFLH, MAX_FRAMELEN >> 8);
254 // do bank 3 stuff
255 // write MAC address
256 // NOTE: MAC address in ENC28J60 is byte-backward
257 enc28j60Write(MAADR5, macaddr[0]);
258 enc28j60Write(MAADR4, macaddr[1]);
259 enc28j60Write(MAADR3, macaddr[2]);
260 enc28j60Write(MAADR2, macaddr[3]);
261 enc28j60Write(MAADR1, macaddr[4]);
262 enc28j60Write(MAADR0, macaddr[5]);
263
264
265
266 enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);
267
268
269 // no loopback of transmitted frames
270 enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);
271 // switch to bank 0
272 enc28j60SetBank(ECON1);
273 // enable interrutps
274 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);
275 // enable packet reception
276 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
277 }
278
279 // read the revision of the chip:
280
281 u8 enc28j60getrev(void)
282 {
283 return(enc28j60Read(EREVID));
284 }
285
286 /*
287 * º¯ÊýÃû£ºenc28j60PacketSend
288 * ÃèÊö £º·¢ËÍÒ»¸öÊý¾Ý°ü
289 * ÊäÈë £ºÊý¾Ý°ü³¤¶È£¬Ö¸ÏòÊý¾Ý°üµÄÖ¸Õë
290 * Êä³ö £ºÎÞ
291 */
292 void enc28j60PacketSend(u16 len, u8* packet)
293 {
294 // Set the write pointer to start of transmit buffer area
295 enc28j60Write(EWRPTL, TXSTART_INIT & 0xFF);
296 enc28j60Write(EWRPTH, TXSTART_INIT >> 8);
297
298 // Set the TXND pointer to correspond to the packet size given
299 enc28j60Write(ETXNDL, (TXSTART_INIT + len) & 0xFF);
300 enc28j60Write(ETXNDH, (TXSTART_INIT + len) >> 8);
301
302 // write per-packet control byte (0x00 means use macon3 settings)
303 enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
304
305 // copy the packet into the transmit buffer
306 enc28j60WriteBuffer(len, packet);
307
308 // send the contents of the transmit buffer onto the network
309 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
310
311 // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
312 if ((enc28j60Read(EIR) & EIR_TXERIF))
313 {
314 enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
315 }
316 }
317
318 /*-----------------------------------------------------------------
319 Gets a packet from the network receive buffer, if one is available.
320 The packet will by headed by an ethernet header.
321 maxlen The maximum acceptable length of a retrieved packet.
322 packet Pointer where packet data should be stored.
323 Returns: Packet length in bytes if a packet was retrieved, zero otherwise.
324 -------------------------------------------------------------------*/
325 u16 enc28j60PacketReceive(u16 maxlen, u8* packet)
326 {
327 u16 rxstat;
328 u16 len;
329
330 // check if a packet has been received and buffered
331 //if( !(enc28j60Read(EIR) & EIR_PKTIF) ){
332 // The above does not work. See Rev. B4 Silicon Errata point 6.
333 if (enc28j60Read(EPKTCNT) == 0)
334 {
335 return(0);
336 }
337
338 // Set the read pointer to the start of the received packet
339 enc28j60Write(ERDPTL, (NextPacketPtr));
340 enc28j60Write(ERDPTH, (NextPacketPtr) >> 8);
341
342 // read the next packet pointer
343 NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
344 NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
345
346 // read the packet length (see datasheet page 43)
347 len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
348 len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
349
350 len -= 4; //remove the CRC count
351 // read the receive status (see datasheet page 43)
352 rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
353 rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;
354 // limit retrieve length
355 if (len > maxlen - 1)
356 {
357 len = maxlen - 1;
358 }
359
360 // check CRC and symbol errors (see datasheet page 44, table 7-3):
361 // The ERXFCON.CRCEN is set by default. Normally we should not
362 // need to check this.
363 if ((rxstat & 0x80) == 0)
364 {
365 // invalid
366 len = 0;
367 }
368 else
369 {
370 // copy the packet from the receive buffer
371 enc28j60ReadBuffer(len, packet);
372 }
373 // Move the RX read pointer to the start of the next received packet
374 // This frees the memory we just read out
375 enc28j60Write(ERXRDPTL, (NextPacketPtr));
376 enc28j60Write(ERXRDPTH, (NextPacketPtr) >> 8);
377
378 // decrement the packet counter indicate we are done with this packet
379 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
380 return(len);
381 }