enc28j60.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /*
  2. * File : enc28j60.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2009-05-05 Bernard the first version
  13. */
  14. #include "enc28j60.h"
  15. #include <netif/ethernetif.h>
  16. #include <stm32f10x.h>
  17. #include <stm32f10x_spi.h>
  18. #define MAX_ADDR_LEN 6
  19. #define CSACTIVE GPIOB->BRR = GPIO_Pin_12;
  20. #define CSPASSIVE GPIOB->BSRR = GPIO_Pin_12;
  21. struct net_device
  22. {
  23. /* inherit from ethernet device */
  24. struct eth_device parent;
  25. /* interface address info. */
  26. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
  27. };
  28. static struct net_device enc28j60_dev_entry;
  29. static struct net_device *enc28j60_dev =&enc28j60_dev_entry;
  30. static rt_uint8_t Enc28j60Bank;
  31. static rt_uint16_t NextPacketPtr;
  32. static struct rt_semaphore lock_sem;
  33. void _delay_us(rt_uint32_t us)
  34. {
  35. rt_uint32_t len;
  36. for (;us > 0; us --)
  37. for (len = 0; len < 20; len++ );
  38. }
  39. void delay_ms(rt_uint32_t ms)
  40. {
  41. rt_uint32_t len;
  42. for (;ms > 0; ms --)
  43. for (len = 0; len < 100; len++ );
  44. }
  45. rt_uint8_t spi_read_op(rt_uint8_t op, rt_uint8_t address)
  46. {
  47. int temp=0;
  48. CSACTIVE;
  49. SPI_I2S_SendData(SPI2, (op | (address & ADDR_MASK)));
  50. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  51. SPI_I2S_ReceiveData(SPI2);
  52. SPI_I2S_SendData(SPI2, 0x00);
  53. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  54. // do dummy read if needed (for mac and mii, see datasheet page 29)
  55. if(address & 0x80)
  56. {
  57. SPI_I2S_ReceiveData(SPI2);
  58. SPI_I2S_SendData(SPI2, 0x00);
  59. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  60. }
  61. // release CS
  62. temp=SPI_I2S_ReceiveData(SPI2);
  63. // for(t=0;t<20;t++);
  64. CSPASSIVE;
  65. return (temp);
  66. }
  67. void spi_write_op(rt_uint8_t op, rt_uint8_t address, rt_uint8_t data)
  68. {
  69. rt_uint32_t level;
  70. level = rt_hw_interrupt_disable();
  71. CSACTIVE;
  72. SPI_I2S_SendData(SPI2, op | (address & ADDR_MASK));
  73. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  74. SPI_I2S_SendData(SPI2,data);
  75. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  76. CSPASSIVE;
  77. rt_hw_interrupt_enable(level);
  78. }
  79. void enc28j60_set_bank(rt_uint8_t address)
  80. {
  81. // set the bank (if needed)
  82. if((address & BANK_MASK) != Enc28j60Bank)
  83. {
  84. // set the bank
  85. spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0));
  86. spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5);
  87. Enc28j60Bank = (address & BANK_MASK);
  88. }
  89. }
  90. rt_uint8_t spi_read(rt_uint8_t address)
  91. {
  92. // set the bank
  93. enc28j60_set_bank(address);
  94. // do the read
  95. return spi_read_op(ENC28J60_READ_CTRL_REG, address);
  96. }
  97. void spi_read_buffer(rt_uint8_t* data, rt_size_t len)
  98. {
  99. CSACTIVE;
  100. SPI_I2S_SendData(SPI2,ENC28J60_READ_BUF_MEM);
  101. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  102. SPI_I2S_ReceiveData(SPI2);
  103. while(len)
  104. {
  105. len--;
  106. SPI_I2S_SendData(SPI2,0x00) ;
  107. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  108. *data= SPI_I2S_ReceiveData(SPI2);
  109. data++;
  110. }
  111. CSPASSIVE;
  112. }
  113. void spi_write(rt_uint8_t address, rt_uint8_t data)
  114. {
  115. // set the bank
  116. enc28j60_set_bank(address);
  117. // do the write
  118. spi_write_op(ENC28J60_WRITE_CTRL_REG, address, data);
  119. }
  120. void enc28j60_phy_write(rt_uint8_t address, rt_uint16_t data)
  121. {
  122. // set the PHY register address
  123. spi_write(MIREGADR, address);
  124. // write the PHY data
  125. spi_write(MIWRL, data);
  126. spi_write(MIWRH, data>>8);
  127. // wait until the PHY write completes
  128. while(spi_read(MISTAT) & MISTAT_BUSY)
  129. {
  130. _delay_us(15);
  131. }
  132. }
  133. // read upper 8 bits
  134. rt_uint16_t enc28j60_phy_read(rt_uint8_t address)
  135. {
  136. // Set the right address and start the register read operation
  137. spi_write(MIREGADR, address);
  138. spi_write(MICMD, MICMD_MIIRD);
  139. _delay_us(15);
  140. // wait until the PHY read completes
  141. while(spi_read(MISTAT) & MISTAT_BUSY);
  142. // reset reading bit
  143. spi_write(MICMD, 0x00);
  144. return (spi_read(MIRDH));
  145. }
  146. void enc28j60_clkout(rt_uint8_t clk)
  147. {
  148. //setup clkout: 2 is 12.5MHz:
  149. spi_write(ECOCON, clk & 0x7);
  150. }
  151. rt_inline rt_uint32_t enc28j60_interrupt_disable()
  152. {
  153. rt_uint32_t level;
  154. /* switch to bank 0 */
  155. enc28j60_set_bank(EIE);
  156. /* get last interrupt level */
  157. level = spi_read(EIE);
  158. /* disable interrutps */
  159. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIE, level);
  160. return level;
  161. }
  162. rt_inline void enc28j60_interrupt_enable(rt_uint32_t level)
  163. {
  164. /* switch to bank 0 */
  165. enc28j60_set_bank(EIE);
  166. spi_write_op(ENC28J60_BIT_FIELD_SET, EIE, level);
  167. }
  168. /*
  169. * Access the PHY to determine link status
  170. */
  171. static rt_bool_t enc28j60_check_link_status()
  172. {
  173. rt_uint16_t reg;
  174. int duplex;
  175. reg = enc28j60_phy_read(PHSTAT2);
  176. duplex = reg & PHSTAT2_DPXSTAT;
  177. if (reg & PHSTAT2_LSTAT)
  178. {
  179. /* on */
  180. return RT_TRUE;
  181. }
  182. else
  183. {
  184. /* off */
  185. return RT_FALSE;
  186. }
  187. }
  188. #ifdef RT_USING_FINSH
  189. /*
  190. * Debug routine to dump useful register contents
  191. */
  192. static void enc28j60(void)
  193. {
  194. rt_kprintf("-- enc28j60 registers:\n");
  195. rt_kprintf("HwRevID: 0x%02x\n", spi_read(EREVID));
  196. rt_kprintf("Cntrl: ECON1 ECON2 ESTAT EIR EIE\n");
  197. rt_kprintf(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",spi_read(ECON1), spi_read(ECON2), spi_read(ESTAT), spi_read(EIR), spi_read(EIE));
  198. rt_kprintf("MAC : MACON1 MACON3 MACON4\n");
  199. rt_kprintf(" 0x%02x 0x%02x 0x%02x\n", spi_read(MACON1), spi_read(MACON3), spi_read(MACON4));
  200. rt_kprintf("Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL\n");
  201. rt_kprintf(" 0x%04x 0x%04x 0x%04x 0x%04x ",
  202. (spi_read(ERXSTH) << 8) | spi_read(ERXSTL),
  203. (spi_read(ERXNDH) << 8) | spi_read(ERXNDL),
  204. (spi_read(ERXWRPTH) << 8) | spi_read(ERXWRPTL),
  205. (spi_read(ERXRDPTH) << 8) | spi_read(ERXRDPTL));
  206. rt_kprintf("0x%02x 0x%02x 0x%04x\n", spi_read(ERXFCON), spi_read(EPKTCNT),
  207. (spi_read(MAMXFLH) << 8) | spi_read(MAMXFLL));
  208. rt_kprintf("Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP\n");
  209. rt_kprintf(" 0x%04x 0x%04x 0x%02x 0x%02x 0x%02x\n",
  210. (spi_read(ETXSTH) << 8) | spi_read(ETXSTL),
  211. (spi_read(ETXNDH) << 8) | spi_read(ETXNDL),
  212. spi_read(MACLCON1), spi_read(MACLCON2), spi_read(MAPHSUP));
  213. }
  214. #include <finsh.h>
  215. FINSH_FUNCTION_EXPORT(enc28j60, dump enc28j60 registers);
  216. #endif
  217. /*
  218. * RX handler
  219. * ignore PKTIF because is unreliable! (look at the errata datasheet)
  220. * check EPKTCNT is the suggested workaround.
  221. * We don't need to clear interrupt flag, automatically done when
  222. * enc28j60_hw_rx() decrements the packet counter.
  223. */
  224. void enc28j60_isr()
  225. {
  226. /* Variable definitions can be made now. */
  227. volatile rt_uint32_t eir, pk_counter;
  228. volatile rt_bool_t rx_activiated;
  229. rx_activiated = RT_FALSE;
  230. /* get EIR */
  231. eir = spi_read(EIR);
  232. // rt_kprintf("eir: 0x%08x\n", eir);
  233. do
  234. {
  235. /* errata #4, PKTIF does not reliable */
  236. pk_counter = spi_read(EPKTCNT);
  237. if (pk_counter)
  238. {
  239. /* a frame has been received */
  240. eth_device_ready((struct eth_device*)&(enc28j60_dev->parent));
  241. // switch to bank 0
  242. enc28j60_set_bank(EIE);
  243. // disable rx interrutps
  244. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIE, EIE_PKTIE);
  245. }
  246. /* clear PKTIF */
  247. if (eir & EIR_PKTIF)
  248. {
  249. enc28j60_set_bank(EIR);
  250. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_PKTIF);
  251. rx_activiated = RT_TRUE;
  252. }
  253. /* clear DMAIF */
  254. if (eir & EIR_DMAIF)
  255. {
  256. enc28j60_set_bank(EIR);
  257. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_DMAIF);
  258. }
  259. /* LINK changed handler */
  260. if ( eir & EIR_LINKIF)
  261. {
  262. enc28j60_check_link_status();
  263. /* read PHIR to clear the flag */
  264. enc28j60_phy_read(PHIR);
  265. enc28j60_set_bank(EIR);
  266. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_LINKIF);
  267. }
  268. if (eir & EIR_TXIF)
  269. {
  270. /* A frame has been transmitted. */
  271. enc28j60_set_bank(EIR);
  272. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXIF);
  273. }
  274. /* TX Error handler */
  275. if ((eir & EIR_TXERIF) != 0)
  276. {
  277. spi_write_op(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF);
  278. }
  279. eir = spi_read(EIR);
  280. // rt_kprintf("inner eir: 0x%08x\n", eir);
  281. } while ((rx_activiated != RT_TRUE && eir != 0));
  282. }
  283. /* RT-Thread Device Interface */
  284. /* initialize the interface */
  285. rt_err_t enc28j60_init(rt_device_t dev)
  286. {
  287. CSPASSIVE;
  288. // perform system reset
  289. spi_write_op(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
  290. delay_ms(50);
  291. NextPacketPtr = RXSTART_INIT;
  292. // Rx start
  293. spi_write(ERXSTL, RXSTART_INIT&0xFF);
  294. spi_write(ERXSTH, RXSTART_INIT>>8);
  295. // set receive pointer address
  296. spi_write(ERXRDPTL, RXSTOP_INIT&0xFF);
  297. spi_write(ERXRDPTH, RXSTOP_INIT>>8);
  298. // RX end
  299. spi_write(ERXNDL, RXSTOP_INIT&0xFF);
  300. spi_write(ERXNDH, RXSTOP_INIT>>8);
  301. // TX start
  302. spi_write(ETXSTL, TXSTART_INIT&0xFF);
  303. spi_write(ETXSTH, TXSTART_INIT>>8);
  304. // set transmission pointer address
  305. spi_write(EWRPTL, TXSTART_INIT&0xFF);
  306. spi_write(EWRPTH, TXSTART_INIT>>8);
  307. // TX end
  308. spi_write(ETXNDL, TXSTOP_INIT&0xFF);
  309. spi_write(ETXNDH, TXSTOP_INIT>>8);
  310. // do bank 1 stuff, packet filter:
  311. // For broadcast packets we allow only ARP packtets
  312. // All other packets should be unicast only for our mac (MAADR)
  313. //
  314. // The pattern to match on is therefore
  315. // Type ETH.DST
  316. // ARP BROADCAST
  317. // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9
  318. // in binary these poitions are:11 0000 0011 1111
  319. // This is hex 303F->EPMM0=0x3f,EPMM1=0x30
  320. spi_write(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_BCEN);
  321. // do bank 2 stuff
  322. // enable MAC receive
  323. spi_write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
  324. // enable automatic padding to 60bytes and CRC operations
  325. // spi_write_op(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
  326. spi_write_op(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
  327. // bring MAC out of reset
  328. // set inter-frame gap (back-to-back)
  329. // spi_write(MABBIPG, 0x12);
  330. spi_write(MABBIPG, 0x15);
  331. spi_write(MACON4, MACON4_DEFER);
  332. spi_write(MACLCON2, 63);
  333. // set inter-frame gap (non-back-to-back)
  334. spi_write(MAIPGL, 0x12);
  335. spi_write(MAIPGH, 0x0C);
  336. // Set the maximum packet size which the controller will accept
  337. // Do not send packets longer than MAX_FRAMELEN:
  338. spi_write(MAMXFLL, MAX_FRAMELEN&0xFF);
  339. spi_write(MAMXFLH, MAX_FRAMELEN>>8);
  340. // do bank 3 stuff
  341. // write MAC address
  342. // NOTE: MAC address in ENC28J60 is byte-backward
  343. spi_write(MAADR0, enc28j60_dev->dev_addr[5]);
  344. spi_write(MAADR1, enc28j60_dev->dev_addr[4]);
  345. spi_write(MAADR2, enc28j60_dev->dev_addr[3]);
  346. spi_write(MAADR3, enc28j60_dev->dev_addr[2]);
  347. spi_write(MAADR4, enc28j60_dev->dev_addr[1]);
  348. spi_write(MAADR5, enc28j60_dev->dev_addr[0]);
  349. /* output off */
  350. spi_write(ECOCON, 0x00);
  351. // enc28j60_phy_write(PHCON1, 0x00);
  352. enc28j60_phy_write(PHCON1, PHCON1_PDPXMD); // full duplex
  353. // no loopback of transmitted frames
  354. enc28j60_phy_write(PHCON2, PHCON2_HDLDIS);
  355. enc28j60_set_bank(ECON2);
  356. spi_write_op(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_AUTOINC);
  357. // switch to bank 0
  358. enc28j60_set_bank(ECON1);
  359. // enable interrutps
  360. spi_write_op(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE|EIR_TXIF);
  361. // enable packet reception
  362. spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
  363. /* clock out */
  364. // enc28j60_clkout(2);
  365. enc28j60_phy_write(PHLCON, 0xD76); //0x476
  366. delay_ms(20);
  367. return RT_EOK;
  368. }
  369. /* control the interface */
  370. rt_err_t enc28j60_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  371. {
  372. switch(cmd)
  373. {
  374. case NIOCTL_GADDR:
  375. /* get mac address */
  376. if(args) rt_memcpy(args, enc28j60_dev_entry.dev_addr, 6);
  377. else return -RT_ERROR;
  378. break;
  379. default :
  380. break;
  381. }
  382. return RT_EOK;
  383. }
  384. /* Open the ethernet interface */
  385. rt_err_t enc28j60_open(rt_device_t dev, rt_uint16_t oflag)
  386. {
  387. return RT_EOK;
  388. }
  389. /* Close the interface */
  390. rt_err_t enc28j60_close(rt_device_t dev)
  391. {
  392. return RT_EOK;
  393. }
  394. /* Read */
  395. rt_size_t enc28j60_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  396. {
  397. rt_set_errno(-RT_ENOSYS);
  398. return 0;
  399. }
  400. /* Write */
  401. rt_size_t enc28j60_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  402. {
  403. rt_set_errno(-RT_ENOSYS);
  404. return 0;
  405. }
  406. /* ethernet device interface */
  407. /*
  408. * Transmit packet.
  409. */
  410. rt_err_t enc28j60_tx( rt_device_t dev, struct pbuf* p)
  411. {
  412. struct pbuf* q;
  413. rt_uint32_t len;
  414. rt_uint8_t* ptr;
  415. rt_uint32_t level;
  416. // rt_kprintf("tx pbuf: 0x%08x, total len %d\n", p, p->tot_len);
  417. /* lock enc28j60 */
  418. rt_sem_take(&lock_sem, RT_WAITING_FOREVER);
  419. /* disable enc28j60 interrupt */
  420. level = enc28j60_interrupt_disable();
  421. // Set the write pointer to start of transmit buffer area
  422. spi_write(EWRPTL, TXSTART_INIT&0xFF);
  423. spi_write(EWRPTH, TXSTART_INIT>>8);
  424. // Set the TXND pointer to correspond to the packet size given
  425. spi_write(ETXNDL, (TXSTART_INIT+ p->tot_len + 1)&0xFF);
  426. spi_write(ETXNDH, (TXSTART_INIT+ p->tot_len + 1)>>8);
  427. // write per-packet control byte (0x00 means use macon3 settings)
  428. spi_write_op(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
  429. for (q = p; q != NULL; q = q->next)
  430. {
  431. CSACTIVE;
  432. SPI_I2S_SendData(SPI2, ENC28J60_WRITE_BUF_MEM);
  433. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  434. len = q->len;
  435. ptr = q->payload;
  436. while(len)
  437. {
  438. SPI_I2S_SendData(SPI2,*ptr) ;
  439. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);;
  440. ptr++;
  441. len--;
  442. }
  443. CSPASSIVE;
  444. }
  445. // send the contents of the transmit buffer onto the network
  446. spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
  447. // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.
  448. if( (spi_read(EIR) & EIR_TXERIF) )
  449. {
  450. spi_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);
  451. }
  452. /* enable enc28j60 interrupt */
  453. enc28j60_interrupt_enable(level);
  454. rt_sem_release(&lock_sem);
  455. return RT_EOK;
  456. }
  457. struct pbuf *enc28j60_rx(rt_device_t dev)
  458. {
  459. struct pbuf* p;
  460. rt_uint32_t len;
  461. rt_uint16_t rxstat;
  462. rt_uint32_t pk_counter;
  463. rt_uint32_t level;
  464. p = RT_NULL;
  465. /* lock enc28j60 */
  466. rt_sem_take(&lock_sem, RT_WAITING_FOREVER);
  467. /* disable enc28j60 interrupt */
  468. level = enc28j60_interrupt_disable();
  469. pk_counter = spi_read(EPKTCNT);
  470. if (pk_counter)
  471. {
  472. // Set the read pointer to the start of the received packet
  473. spi_write(ERDPTL, (NextPacketPtr));
  474. spi_write(ERDPTH, (NextPacketPtr)>>8);
  475. // read the next packet pointer
  476. NextPacketPtr = spi_read_op(ENC28J60_READ_BUF_MEM, 0);
  477. NextPacketPtr |= spi_read_op(ENC28J60_READ_BUF_MEM, 0)<<8;
  478. // read the packet length (see datasheet page 43)
  479. len = spi_read_op(ENC28J60_READ_BUF_MEM, 0); //0x54
  480. len |= spi_read_op(ENC28J60_READ_BUF_MEM, 0) <<8; //5554
  481. len-=4; //remove the CRC count
  482. // read the receive status (see datasheet page 43)
  483. rxstat = spi_read_op(ENC28J60_READ_BUF_MEM, 0);
  484. rxstat |= ((rt_uint16_t)spi_read_op(ENC28J60_READ_BUF_MEM, 0))<<8;
  485. // check CRC and symbol errors (see datasheet page 44, table 7-3):
  486. // The ERXFCON.CRCEN is set by default. Normally we should not
  487. // need to check this.
  488. if ((rxstat & 0x80)==0)
  489. {
  490. // invalid
  491. len=0;
  492. }
  493. else
  494. {
  495. /* allocation pbuf */
  496. p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
  497. if (p != RT_NULL)
  498. {
  499. rt_uint8_t* data;
  500. struct pbuf* q;
  501. for (q = p; q != RT_NULL; q= q->next)
  502. {
  503. data = q->payload;
  504. len = q->len;
  505. CSACTIVE;
  506. SPI_I2S_SendData(SPI2,ENC28J60_READ_BUF_MEM);
  507. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  508. SPI_I2S_ReceiveData(SPI2);
  509. while(len)
  510. {
  511. len--;
  512. SPI_I2S_SendData(SPI2,0x00) ;
  513. while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY)==SET);
  514. *data= SPI_I2S_ReceiveData(SPI2);
  515. data++;
  516. }
  517. CSPASSIVE;
  518. }
  519. }
  520. }
  521. // Move the RX read pointer to the start of the next received packet
  522. // This frees the memory we just read out
  523. spi_write(ERXRDPTL, (NextPacketPtr));
  524. spi_write(ERXRDPTH, (NextPacketPtr)>>8);
  525. // decrement the packet counter indicate we are done with this packet
  526. spi_write_op(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
  527. }
  528. else
  529. {
  530. // switch to bank 0
  531. enc28j60_set_bank(ECON1);
  532. // enable packet reception
  533. spi_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
  534. level |= EIE_PKTIE;
  535. }
  536. /* enable enc28j60 interrupt */
  537. enc28j60_interrupt_enable(level);
  538. rt_sem_release(&lock_sem);
  539. return p;
  540. }
  541. static void RCC_Configuration(void)
  542. {
  543. /* enable spi2 clock */
  544. RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  545. /* enable gpiob port clock */
  546. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
  547. }
  548. static void NVIC_Configuration(void)
  549. {
  550. NVIC_InitTypeDef NVIC_InitStructure;
  551. /* Configure one bit for preemption priority */
  552. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  553. /* Enable the EXTI0 Interrupt */
  554. NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  555. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  556. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  557. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  558. NVIC_Init(&NVIC_InitStructure);
  559. }
  560. static void GPIO_Configuration()
  561. {
  562. GPIO_InitTypeDef GPIO_InitStructure;
  563. EXTI_InitTypeDef EXTI_InitStructure;
  564. /* configure PB0 as external interrupt */
  565. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  566. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  567. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
  568. GPIO_Init(GPIOB, &GPIO_InitStructure);
  569. /* Configure SPI2 pins: SCK, MISO and MOSI ----------------------------*/
  570. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  571. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  572. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  573. GPIO_Init(GPIOB, &GPIO_InitStructure);
  574. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  575. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  576. GPIO_Init(GPIOB, &GPIO_InitStructure);
  577. /* Connect ENC28J60 EXTI Line to GPIOB Pin 0 */
  578. GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
  579. /* Configure ENC28J60 EXTI Line to generate an interrupt on falling edge */
  580. EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  581. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  582. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  583. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  584. EXTI_Init(&EXTI_InitStructure);
  585. /* Clear the Key Button EXTI line pending bit */
  586. EXTI_ClearITPendingBit(EXTI_Line0);
  587. }
  588. static void SetupSPI (void)
  589. {
  590. SPI_InitTypeDef SPI_InitStructure;
  591. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  592. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  593. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  594. SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  595. SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  596. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  597. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  598. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  599. SPI_InitStructure.SPI_CRCPolynomial = 7;
  600. SPI_Init(SPI2, &SPI_InitStructure);
  601. SPI_Cmd(SPI2, ENABLE);
  602. }
  603. void rt_hw_enc28j60_init()
  604. {
  605. /* configuration PB5 as INT */
  606. RCC_Configuration();
  607. NVIC_Configuration();
  608. GPIO_Configuration();
  609. SetupSPI();
  610. /* init rt-thread device interface */
  611. enc28j60_dev_entry.parent.parent.init = enc28j60_init;
  612. enc28j60_dev_entry.parent.parent.open = enc28j60_open;
  613. enc28j60_dev_entry.parent.parent.close = enc28j60_close;
  614. enc28j60_dev_entry.parent.parent.read = enc28j60_read;
  615. enc28j60_dev_entry.parent.parent.write = enc28j60_write;
  616. enc28j60_dev_entry.parent.parent.control = enc28j60_control;
  617. enc28j60_dev_entry.parent.eth_rx = enc28j60_rx;
  618. enc28j60_dev_entry.parent.eth_tx = enc28j60_tx;
  619. /* Update MAC address */
  620. enc28j60_dev_entry.dev_addr[0] = 0x00;
  621. enc28j60_dev_entry.dev_addr[1] = 0x30;
  622. enc28j60_dev_entry.dev_addr[2] = 0x6c;
  623. enc28j60_dev_entry.dev_addr[3] = 0x11;
  624. enc28j60_dev_entry.dev_addr[4] = 0x22;
  625. enc28j60_dev_entry.dev_addr[5] = 0x33;
  626. rt_sem_init(&lock_sem, "lock", 1, RT_IPC_FLAG_FIFO);
  627. eth_device_init(&(enc28j60_dev->parent), "e0");
  628. }