?? enc28j60.lst
字號:
1 .file "enc28j60.c"
2 __SREG__ = 0x3f
3 __SP_H__ = 0x3e
4 __SP_L__ = 0x3d
5 __CCP__ = 0x34
6 __tmp_reg__ = 0
7 __zero_reg__ = 1
8 .global __do_copy_data
9 .global __do_clear_bss
11 .text
12 .Ltext0:
95 .global enc28j60_read_buffer
97 enc28j60_read_buffer:
1:io/enc28j60.c **** /*
2:io/enc28j60.c **** ,-----------------------------------------------------------------------------------------.
3:io/enc28j60.c **** | io/enc28j60
4:io/enc28j60.c **** |-----------------------------------------------------------------------------------------
5:io/enc28j60.c **** | this file implements the driver for the microchip enc28j60 ethernet controller
6:io/enc28j60.c **** | - some ideas are based on the enc28j60 driver of the procyon avrlib ;)
8:io/enc28j60.c **** | BUGS:
9:io/enc28j60.c **** | - sometimes enc28j60 is not correctly initialised (not receiving any packets)
10:io/enc28j60.c **** |
11:io/enc28j60.c **** | Author : {{removed according to contest rules}}
12:io/enc28j60.c **** | -> circuitcellar.com avr design contest 2006
13:io/enc28j60.c **** | -> Entry #AT2616
14:io/enc28j60.c **** |
15:io/enc28j60.c **** |-----------------------------------------------------------------------------------------
16:io/enc28j60.c **** | License:
17:io/enc28j60.c **** | This program is free software; you can redistribute it and/or modify it under
18:io/enc28j60.c **** | the terms of the GNU General Public License as published by the Free Software
19:io/enc28j60.c **** | Foundation; either version 2 of the License, or (at your option) any later
20:io/enc28j60.c **** | version.
21:io/enc28j60.c **** | This program is distributed in the hope that it will be useful, but
22:io/enc28j60.c **** |
23:io/enc28j60.c **** | WITHOUT ANY WARRANTY;
24:io/enc28j60.c **** |
25:io/enc28j60.c **** | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
26:io/enc28j60.c **** | PURPOSE. See the GNU General Public License for more details.
27:io/enc28j60.c **** |
28:io/enc28j60.c **** | You should have received a copy of the GNU General Public License along with
29:io/enc28j60.c **** | this program; if not, write to the Free Software Foundation, Inc., 51
30:io/enc28j60.c **** | Franklin St, Fifth Floor, Boston, MA 02110, USA
31:io/enc28j60.c **** |
32:io/enc28j60.c **** | http://www.gnu.de/gpl-ger.html
33:io/enc28j60.c **** `-----------------------------------------------------------------------------------------*/
34:io/enc28j60.c **** #include "enc28j60.h"
35:io/enc28j60.c ****
36:io/enc28j60.c **** //ACTIVATE DEBUG by editing this file:
37:io/enc28j60.c **** #include "debug.h"
38:io/enc28j60.c ****
39:io/enc28j60.c **** volatile unsigned char enc28j60_current_bank;
40:io/enc28j60.c **** volatile unsigned int enc28j60_next_packet_ptr;
41:io/enc28j60.c **** unsigned char enc28j60_revision;
42:io/enc28j60.c **** #include <avr/pgmspace.h>
43:io/enc28j60.c ****
44:io/enc28j60.c **** //store enc28j60 config in program memory
45:io/enc28j60.c **** //syntax: <REGx>, <REGVALx>, <REGy>, <REGVALy>,...
46:io/enc28j60.c **** unsigned char enc28j60_config[] PROGMEM = {
47:io/enc28j60.c **** //setup bank0 (config stored in progmem, see above)
48:io/enc28j60.c **** //tx buffer:
49:io/enc28j60.c **** ENC28J60_REG_ETXSTL, lo8(ENC28J60_TX_BUFFER_START), //start lo
50:io/enc28j60.c **** ENC28J60_REG_ETXSTH, hi8(ENC28J60_TX_BUFFER_START), //start hi
51:io/enc28j60.c **** ENC28J60_REG_ETXNDL, lo8(ENC28J60_TX_BUFFER_END ), //end lo
52:io/enc28j60.c **** ENC28J60_REG_ETXNDH, hi8(ENC28J60_TX_BUFFER_END ), //end hi
53:io/enc28j60.c **** //rx buffer
54:io/enc28j60.c **** ENC28J60_REG_ERXSTL, lo8(ENC28J60_RX_BUFFER_START), //start lo
55:io/enc28j60.c **** ENC28J60_REG_ERXSTH, hi8(ENC28J60_RX_BUFFER_START), //start hi
56:io/enc28j60.c **** ENC28J60_REG_ERXNDL, lo8(ENC28J60_RX_BUFFER_END ), //end lo
57:io/enc28j60.c **** ENC28J60_REG_ERXNDH, hi8(ENC28J60_RX_BUFFER_END ), //end hi
58:io/enc28j60.c **** //rx ptr:
59:io/enc28j60.c **** //ENC28J60_REG_ERDPTL, lo8(ENC28J60_RX_BUFFER_START+1),
60:io/enc28j60.c **** //ENC28J60_REG_ERDPTH, hi8(ENC28J60_RX_BUFFER_START+1),
61:io/enc28j60.c ****
62:io/enc28j60.c **** //setup bank2: (see microchip datasheet p.36)
63:io/enc28j60.c **** //1.) clear the MARST bit in MACON2.
64:io/enc28j60.c **** ENC28J60_REG_MACON2, 0x00,
65:io/enc28j60.c **** //2.) mac rx enable, activate pause control frame support
66:io/enc28j60.c **** ENC28J60_REG_MACON1, ((1<<ENC28J60_BIT_MARXEN)|(1<<ENC28J60_BIT_RXPAUS)|(1<<ENC28J60_BIT_TXPAUS))
67:io/enc28j60.c **** //3.) setup MACON3: auto padding of small packets, add crc, enable frame length check:
68:io/enc28j60.c **** ENC28J60_REG_MACON3, ((1<<ENC28J60_BIT_PADCFG0)|(1<<ENC28J60_BIT_TXCRCEN)|(1<<ENC28J60_BIT_FRMLNE
69:io/enc28j60.c **** //4.) dont set up MACON4 (use default)
70:io/enc28j60.c **** //5.) setup maximum framelenght to 1518:
71:io/enc28j60.c **** ENC28J60_REG_MAMXFLL, lo8(1518),
72:io/enc28j60.c **** ENC28J60_REG_MAMXFLH, hi8(1518),
73:io/enc28j60.c **** //6.) set up back-to-back gap: 0x15 for full duplex / 0x12 for half duplex
74:io/enc28j60.c **** ENC28J60_REG_MABBIPG, 0x12, //half duplex
75:io/enc28j60.c **** //7.) setup non-back-to-back gap: use 0x12
76:io/enc28j60.c **** ENC28J60_REG_MAIPGL, 0x12,
77:io/enc28j60.c **** //8.) setup non-back-to-back gap high byte: 0x0C for half duplex:
78:io/enc28j60.c **** ENC28J60_REG_MAIPGH, 0x0C, //half duplex
79:io/enc28j60.c **** //9.) dont change MACLCON1+2 / MACLCON2 might be changed for networks with long wires !
80:io/enc28j60.c ****
81:io/enc28j60.c **** //setup bank3:
82:io/enc28j60.c **** //10.) programm mac address: BYTE BACKWARD !
83:io/enc28j60.c **** ENC28J60_REG_MAADR5, NIC_MAC0,
84:io/enc28j60.c **** ENC28J60_REG_MAADR4, NIC_MAC1,
85:io/enc28j60.c **** ENC28J60_REG_MAADR3, NIC_MAC2,
86:io/enc28j60.c **** ENC28J60_REG_MAADR2, NIC_MAC3,
87:io/enc28j60.c **** ENC28J60_REG_MAADR1, NIC_MAC4,
88:io/enc28j60.c **** ENC28J60_REG_MAADR0, NIC_MAC5
89:io/enc28j60.c **** };
90:io/enc28j60.c ****
91:io/enc28j60.c ****
92:io/enc28j60.c **** //initialise spi & enc28j60
93:io/enc28j60.c **** void enc28j60_init(void){
94:io/enc28j60.c **** unsigned char i;
95:io/enc28j60.c ****
96:io/enc28j60.c **** //set bank to invalid value -> bank set will update in any case:
97:io/enc28j60.c **** enc28j60_current_bank = 0xFF;
98:io/enc28j60.c ****
99:io/enc28j60.c **** //set up port directions:
100:io/enc28j60.c **** ENC28J60_DDR |= (1<<ENC28J60_PIN_CS)|(1<<ENC28J60_PIN_RESET);
101:io/enc28j60.c ****
102:io/enc28j60.c **** //deselect enc28j60:
103:io/enc28j60.c **** ENC28J60_CS_HI();
104:io/enc28j60.c ****
105:io/enc28j60.c **** //SPI init
106:io/enc28j60.c **** // initialize I/O
107:io/enc28j60.c **** PORTB |= (1<<7); //sck = hi
108:io/enc28j60.c ****
109:io/enc28j60.c **** //spi = output
110:io/enc28j60.c **** //mega8//DDRB |= (1<<2)|(1<<3)|(1<<5); //SS,MOSI,SCK = OUT
111:io/enc28j60.c **** DDRB |= (1<<4)|(1<<5)|(1<<7); //SS,MOSI,SCK = OUT
112:io/enc28j60.c **** DDRB &= ~(1<<6); //MISO = IN
113:io/enc28j60.c ****
114:io/enc28j60.c **** //SPI init:
115:io/enc28j60.c **** // - master mode
116:io/enc28j60.c **** // - positive clock phase
117:io/enc28j60.c **** // - msb first
118:io/enc28j60.c **** // - maximum SPI speed (fosc/2)
119:io/enc28j60.c **** // - enable spi
120:io/enc28j60.c **** SPCR = (0<<CPOL)|(1<<MSTR)|(0<<DORD)|(0<<SPR1)|(0<<SPR0)|(1<<SPE);
121:io/enc28j60.c **** SPSR = (1<<SPI2X);
122:io/enc28j60.c ****
123:io/enc28j60.c **** //reset enc28j60:
124:io/enc28j60.c **** ENC28J60_RESET_LO();
125:io/enc28j60.c **** _delay_ms(10);
126:io/enc28j60.c **** ENC28J60_RESET_HI();
127:io/enc28j60.c ****
128:io/enc28j60.c **** //after reset we have to wait at least 50us !
129:io/enc28j60.c **** _delay_us(60);
130:io/enc28j60.c **** //workaround for bad chip revisions: wait >1ms (wait 10ms...)
131:io/enc28j60.c **** _delay_ms(10);
132:io/enc28j60.c ****
133:io/enc28j60.c **** //wait for ready flag
134:io/enc28j60.c **** while(!(enc28j60_read_address(ENC28J60_REG_ESTAT) & 0x01)){};
135:io/enc28j60.c ****
136:io/enc28j60.c **** //set up rx pointer:
137:io/enc28j60.c **** enc28j60_next_packet_ptr = ENC28J60_RX_BUFFER_START;
138:io/enc28j60.c **** //enc28j60_next_packet_ptr = 0x0602;
139:io/enc28j60.c ****
140:io/enc28j60.c **** //copy config from progmem to enc28j60:
141:io/enc28j60.c **** for(i=0; i<2*22; i+=2){
142:io/enc28j60.c **** enc28j60_write_address(pgm_read_byte(&enc28j60_config[i+0]),pgm_read_byte(&enc28j60_config[i+1]))
143:io/enc28j60.c **** }
144:io/enc28j60.c ****
145:io/enc28j60.c **** //setup phy:
146:io/enc28j60.c **** enc28j60_write_phy(ENC28J60_PHY_PHCON2, (1<<ENC28J60_BIT_HDLDIS)); //=no loopback of transmitted f
147:io/enc28j60.c ****
148:io/enc28j60.c **** //enable interrups
149:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_EIE, (1<<6)|(1<<7));
150:io/enc28j60.c ****
151:io/enc28j60.c **** //enable rx
152:io/enc28j60.c **** //enc28j60_write_address(ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_RXEN));
153:io/enc28j60.c **** enc28j60_spi_write_word(ENC28J60_OP_BFS|ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_RXEN));
154:io/enc28j60.c ****
155:io/enc28j60.c **** //set up leds: LEDA: link status, LEDB: RX&TX activity
156:io/enc28j60.c **** enc28j60_write_phy(ENC28J60_PHY_PHLCON, 0x0472);
157:io/enc28j60.c ****
158:io/enc28j60.c **** //read silicon revision
159:io/enc28j60.c **** enc28j60_revision = enc28j60_read_address(ENC28J60_REG_EREVID);
160:io/enc28j60.c **** }
161:io/enc28j60.c ****
162:io/enc28j60.c **** void enc28j60_send_packet(unsigned char *buffer, unsigned int len){
163:io/enc28j60.c **** unsigned int tmp;
164:io/enc28j60.c **** //still sending ?
165:io/enc28j60.c **** //wait max 50*10 = 500ms:
166:io/enc28j60.c **** for(tmp=0; tmp<50; tmp++){
167:io/enc28j60.c **** if (!(enc28j60_read_address(ENC28J60_REG_ECON1) & (1<<ENC28J60_BIT_TXRTS))){
168:io/enc28j60.c **** //send finished -> tx packet
169:io/enc28j60.c **** break;
170:io/enc28j60.c **** }
171:io/enc28j60.c **** //tx not finished yet, wait 10ms
172:io/enc28j60.c **** _delay_ms(10);
173:io/enc28j60.c **** }
174:io/enc28j60.c ****
175:io/enc28j60.c **** //send anyway...
176:io/enc28j60.c ****
177:io/enc28j60.c **** //setup write pointer:
178:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_EWRPTL, (ENC28J60_TX_BUFFER_START&0xFF));
179:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_EWRPTH, (ENC28J60_TX_BUFFER_START)>>8);
180:io/enc28j60.c ****
181:io/enc28j60.c **** //set tx end pointer to [start+len]:
182:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_ETXNDL, (ENC28J60_TX_BUFFER_START+len)&0xFF);
183:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_ETXNDH, (ENC28J60_TX_BUFFER_START+len)>>8);
184:io/enc28j60.c ****
185:io/enc28j60.c **** //start buffer write command
186:io/enc28j60.c **** enc28j60_spi_write_word(ENC28J60_OP_WRITE_BUF_MEM, 0x00);
187:io/enc28j60.c ****
188:io/enc28j60.c **** //copy buffer to enc28j60:
189:io/enc28j60.c **** enc28j60_write_buffer(buffer, len);
190:io/enc28j60.c ****
191:io/enc28j60.c **** //bad silicon workaround:
192:io/enc28j60.c **** //reset tx logic:
193:io/enc28j60.c **** enc28j60_spi_write_word(ENC28J60_OP_BFS | ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_TXRST));
194:io/enc28j60.c **** enc28j60_spi_write_word(ENC28J60_OP_BFC | ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_TXRST));
195:io/enc28j60.c ****
196:io/enc28j60.c **** //activate transmission
197:io/enc28j60.c **** enc28j60_spi_write_word(ENC28J60_OP_BFS | ENC28J60_REG_ECON1, (1<<ENC28J60_BIT_TXRTS)|(1<<ENC28J60
198:io/enc28j60.c **** }
199:io/enc28j60.c ****
200:io/enc28j60.c **** unsigned int enc28j60_receive_packet(unsigned char *buffer, unsigned int maxlen){
201:io/enc28j60.c **** unsigned int rxstat;
202:io/enc28j60.c **** unsigned int len;
203:io/enc28j60.c ****
204:io/enc28j60.c **** #if ENC_DEBUG
205:io/enc28j60.c **** unsigned int pktcnt = enc28j60_read_address(ENC28J60_REG_EPKTCNT);
206:io/enc28j60.c **** if (CLOCK_TEST_FLAG(CLOCK_SEC) || pktcnt != 0){
207:io/enc28j60.c **** softuart_puts_progmem("ENC : pktcnt ");
208:io/enc28j60.c **** softuart_put_uint16(pktcnt);
209:io/enc28j60.c **** softuart_puts_progmem(" pktflag ");
210:io/enc28j60.c **** if ((enc28j60_read_address(ENC28J60_REG_EIR) & (1<<ENC28J60_BIT_PKTIF)))
211:io/enc28j60.c **** softuart_putc('1');
212:io/enc28j60.c **** else
213:io/enc28j60.c **** softuart_putc('0');
214:io/enc28j60.c **** softuart_putnewline();
215:io/enc28j60.c **** }
216:io/enc28j60.c **** #endif
217:io/enc28j60.c ****
218:io/enc28j60.c **** //packet in buffer ?
219:io/enc28j60.c **** if ((enc28j60_read_address(ENC28J60_REG_EIR) & (1<<ENC28J60_BIT_PKTIF)) == 0){
220:io/enc28j60.c **** //double check!
221:io/enc28j60.c **** //errata says that PKTIF does not work as it should
222:io/enc28j60.c **** //->check packetcount too:
223:io/enc28j60.c **** if (enc28j60_read_address(ENC28J60_REG_EPKTCNT) == 0)
224:io/enc28j60.c **** return 0;
225:io/enc28j60.c **** }
226:io/enc28j60.c ****
227:io/enc28j60.c **** //set read pointer to next packet;
228:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_ERDPTL, (enc28j60_next_packet_ptr));
229:io/enc28j60.c **** enc28j60_write_address(ENC28J60_REG_ERDPTH, (enc28j60_next_packet_ptr)>>8);
230:io/enc28j60.c **** #if ENC_DEBUG
231:io/enc28j60.c **** softuart_puts_progmem("ENC : nptr <= ");
232:io/enc28j60.c **** softuart_put_uint16(enc28j60_next_packet_ptr);
233:io/enc28j60.c **** softuart_putnewline();
234:io/enc28j60.c **** #endif
235:io/enc28j60.c ****
236:io/enc28j60.c **** //now read the transmit status vector
237:io/enc28j60.c **** //read next packet ptr
238:io/enc28j60.c **** enc28j60_next_packet_ptr = enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0);
239:io/enc28j60.c **** enc28j60_next_packet_ptr |= enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0)<<8;
240:io/enc28j60.c **** #if ENC_DEBUG
241:io/enc28j60.c **** softuart_puts_progmem("ENC : nptr read: ");
242:io/enc28j60.c **** softuart_put_uint16(enc28j60_next_packet_ptr);
243:io/enc28j60.c **** softuart_putnewline();
244:io/enc28j60.c **** #endif
245:io/enc28j60.c ****
246:io/enc28j60.c **** //read packet length
247:io/enc28j60.c **** len = enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0);
248:io/enc28j60.c **** len |= enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0)<<8;
249:io/enc28j60.c ****
250:io/enc28j60.c **** //read rx stat
251:io/enc28j60.c **** rxstat = enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0);
252:io/enc28j60.c **** rxstat |= enc28j60_spi_read_byte(ENC28J60_OP_READ_BUF_MEM, 0)<<8;
253:io/enc28j60.c ****
255:io/enc28j60.c **** if (len>maxlen)
256:io/enc28j60.c **** len = maxlen;
257:io/enc28j60.c ****
258:io/enc28j60.c **** //tranfer packet from enc28j60 to our buffer
259:io/enc28j60.c **** enc28j60_read_buffer(buffer,len);
260:io/enc28j60.c ****
261:io/enc28j60.c **** //mark packet as processed (free mem)
262:io/enc28j60.c ****
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -