enc28j60.c 21 KB

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