luminaryif.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. //*****************************************************************************
  2. //
  3. // luminaryif.c - Ethernet Interface File for lwIP TCP/IP Stack
  4. //
  5. //*****************************************************************************
  6. #include <inc/hw_memmap.h>
  7. #include <inc/hw_types.h>
  8. #include <inc/hw_ints.h>
  9. #include <inc/hw_ethernet.h>
  10. #include <driverlib/ethernet.h>
  11. #include <driverlib/interrupt.h>
  12. #include <driverlib/sysctl.h>
  13. #include <driverlib/gpio.h>
  14. #include <driverlib/flash.h>
  15. #include <netif/ethernetif.h>
  16. #include "lwipopts.h"
  17. #include "luminaryif.h"
  18. #define MAX_ADDR_LEN 6
  19. struct net_device
  20. {
  21. /* inherit from ethernet device */
  22. struct eth_device parent;
  23. /* interface address info. */
  24. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
  25. };
  26. static struct net_device luminaryif_dev_entry;
  27. static struct net_device *luminaryif_dev =&luminaryif_dev_entry;
  28. static struct rt_semaphore tx_sem;
  29. //*****************************************************************************
  30. //
  31. // Sanity Check: This module will NOT work if the following defines
  32. // are incorrect.
  33. //
  34. //*****************************************************************************
  35. #if (PBUF_LINK_HLEN != 16)
  36. #error "Incorrect PBUF_LINK_HLEN specified!"
  37. #endif
  38. #if (ETH_PAD_SIZE != 2)
  39. #error "Incorrect ETH_PAD_SIZE specified!"
  40. #endif
  41. #if (PBUF_POOL_BUFSIZE % 4)
  42. #error "PBUF_POOL_BUFSIZE must be modulo 4!"
  43. #endif
  44. /* RT-Thread Device Interface */
  45. /* initialize the interface */
  46. //*****************************************************************************
  47. //
  48. // Low-Level initialization function for the Ethernet Controller.
  49. //
  50. //*****************************************************************************
  51. rt_err_t luminaryif_init(rt_device_t dev)
  52. {
  53. unsigned long ulTemp;
  54. //
  55. // Disable all Ethernet Interrupts.
  56. //
  57. EthernetIntDisable(ETH_BASE, (ETH_INT_PHY | ETH_INT_MDIO | ETH_INT_RXER |
  58. ETH_INT_RXOF | ETH_INT_TX | ETH_INT_TXER |
  59. ETH_INT_RX));
  60. ulTemp = EthernetIntStatus(ETH_BASE, false);
  61. EthernetIntClear(ETH_BASE, ulTemp);
  62. //
  63. // Initialize the Ethernet Controller.
  64. //
  65. EthernetInitExpClk(ETH_BASE, SysCtlClockGet());
  66. //
  67. // Configure the Ethernet Controller for normal operation.
  68. // - Enable TX Duplex Mode
  69. // - Enable TX Padding
  70. // - Enable TX CRC Generation
  71. // - Enable reception of multicast packets
  72. //
  73. EthernetConfigSet(ETH_BASE, (ETH_CFG_TX_DPLXEN |
  74. ETH_CFG_TX_CRCEN | ETH_CFG_TX_PADEN | ETH_CFG_RX_AMULEN));
  75. //
  76. // Enable the Ethernet Controller transmitter and receiver.
  77. //
  78. EthernetEnable(ETH_BASE);
  79. //
  80. // Enable the Ethernet Interrupt handler.
  81. //
  82. IntEnable(INT_ETH);
  83. //
  84. // Enable Ethernet TX and RX Packet Interrupts.
  85. //
  86. EthernetIntEnable(ETH_BASE, ETH_INT_RX | ETH_INT_TX);
  87. return RT_EOK;
  88. }
  89. void luminaryif_isr(void)
  90. {
  91. unsigned long ulTemp;
  92. //
  93. // Read and Clear the interrupt.
  94. //
  95. ulTemp = EthernetIntStatus(ETH_BASE, false);
  96. EthernetIntClear(ETH_BASE, ulTemp);
  97. //
  98. // Check to see if an RX Interrupt has occured.
  99. //
  100. if(ulTemp & ETH_INT_RX)
  101. {
  102. //
  103. // Indicate that a packet has been received.
  104. //
  105. rt_err_t result;
  106. /* a frame has been received */
  107. result = eth_device_ready((struct eth_device*)&(luminaryif_dev->parent));
  108. if(result != RT_EOK) rt_set_errno(-RT_ERROR);
  109. //
  110. // Disable Ethernet RX Interrupt.
  111. //
  112. EthernetIntDisable(ETH_BASE, ETH_INT_RX);
  113. }
  114. if(ulTemp & ETH_INT_TX)
  115. {
  116. /* A frame has been transmitted. */
  117. rt_sem_release(&tx_sem);
  118. }
  119. }
  120. /* control the interface */
  121. rt_err_t luminaryif_control(rt_device_t dev, int cmd, void *args)
  122. {
  123. switch(cmd)
  124. {
  125. case NIOCTL_GADDR:
  126. /* get mac address */
  127. if(args) rt_memcpy(args, luminaryif_dev_entry.dev_addr, 6);
  128. else return -RT_ERROR;
  129. break;
  130. default :
  131. break;
  132. }
  133. return RT_EOK;
  134. }
  135. /* Open the ethernet interface */
  136. rt_err_t luminaryif_open(rt_device_t dev, rt_uint16_t oflag)
  137. {
  138. return RT_EOK;
  139. }
  140. /* Close the interface */
  141. rt_err_t luminaryif_close(rt_device_t dev)
  142. {
  143. return RT_EOK;
  144. }
  145. /* Read */
  146. rt_size_t luminaryif_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  147. {
  148. rt_set_errno(-RT_ENOSYS);
  149. return 0;
  150. }
  151. /* Write */
  152. rt_size_t luminaryif_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  153. {
  154. rt_set_errno(-RT_ENOSYS);
  155. return 0;
  156. }
  157. //****************************************************************************
  158. //
  159. // Low-Level transmit routine. Should do the actual transmission of the
  160. // packet. The packet is contained in the pbuf that is passed to the function.
  161. // This pbuf might be chained.
  162. //
  163. //****************************************************************************
  164. rt_err_t luminaryif_tx(rt_device_t dev, struct pbuf *p)
  165. {
  166. int iBuf;
  167. unsigned char *pucBuf;
  168. unsigned long *pulBuf;
  169. struct pbuf *q;
  170. int iGather;
  171. unsigned long ulGather;
  172. unsigned char *pucGather;
  173. unsigned long ulTemp;
  174. /* lock tx operation */
  175. rt_sem_take(&tx_sem, RT_WAITING_FOREVER);
  176. //
  177. // Wait for space available in the TX FIFO.
  178. //
  179. while(!EthernetSpaceAvail(ETH_BASE))
  180. {
  181. }
  182. //
  183. // Fill in the first two bytes of the payload data (configured as padding
  184. // with ETH_PAD_SIZE = 2) with the total length of the payload data
  185. // (minus the Ethernet MAC layer header).
  186. //
  187. *((unsigned short *)(p->payload)) = p->tot_len - 16;
  188. //
  189. // Initialize the gather register.
  190. //
  191. iGather = 0;
  192. pucGather = (unsigned char *)&ulGather;
  193. ulGather = 0;
  194. //
  195. // Copy data from the pbuf(s) into the TX Fifo.
  196. //
  197. for(q = p; q != NULL; q = q->next)
  198. {
  199. //
  200. // Intialize a char pointer and index to the pbuf payload data.
  201. //
  202. pucBuf = (unsigned char *)q->payload;
  203. iBuf = 0;
  204. //
  205. // If the gather buffer has leftover data from a previous pbuf
  206. // in the chain, fill it up and write it to the Tx FIFO.
  207. //
  208. while((iBuf < q->len) && (iGather != 0))
  209. {
  210. //
  211. // Copy a byte from the pbuf into the gather buffer.
  212. //
  213. pucGather[iGather] = pucBuf[iBuf++];
  214. //
  215. // Increment the gather buffer index modulo 4.
  216. //
  217. iGather = ((iGather + 1) % 4);
  218. }
  219. //
  220. // If the gather index is 0 and the pbuf index is non-zero,
  221. // we have a gather buffer to write into the Tx FIFO.
  222. //
  223. if((iGather == 0) && (iBuf != 0))
  224. {
  225. HWREG(ETH_BASE + MAC_O_DATA) = ulGather;
  226. ulGather = 0;
  227. }
  228. //
  229. // Copy words of pbuf data into the Tx FIFO, but don't go past
  230. // the end of the pbuf.
  231. //
  232. if((iBuf % 4) != 0)
  233. {
  234. while((iBuf + 4) <= q->len)
  235. {
  236. ulTemp = (pucBuf[iBuf++] << 0);
  237. ulTemp |= (pucBuf[iBuf++] << 8);
  238. ulTemp |= (pucBuf[iBuf++] << 16);
  239. ulTemp |= (pucBuf[iBuf++] << 24);
  240. HWREG(ETH_BASE + MAC_O_DATA) = ulTemp;
  241. }
  242. }
  243. else
  244. {
  245. //
  246. // Initialze a long pointer into the pbuf for 32-bit access.
  247. //
  248. pulBuf = (unsigned long *)&pucBuf[iBuf];
  249. while((iBuf + 4) <= q->len)
  250. {
  251. HWREG(ETH_BASE + MAC_O_DATA) = *pulBuf++;
  252. iBuf += 4;
  253. }
  254. }
  255. //
  256. // Check if leftover data in the pbuf and save it in the gather
  257. // buffer for the next time.
  258. //
  259. while(iBuf < q->len)
  260. {
  261. //
  262. // Copy a byte from the pbuf into the gather buffer.
  263. //
  264. pucGather[iGather] = pucBuf[iBuf++];
  265. //
  266. // Increment the gather buffer index modulo 4.
  267. //
  268. iGather = ((iGather + 1) % 4);
  269. }
  270. }
  271. //
  272. // Send any leftover data to the FIFO.
  273. //
  274. HWREG(ETH_BASE + MAC_O_DATA) = ulGather;
  275. //
  276. // Wakeup the transmitter.
  277. //
  278. HWREG(ETH_BASE + MAC_O_TR) = MAC_TR_NEWTX;
  279. #if LINK_STATS
  280. lwip_stats.link.xmit++;
  281. #endif
  282. return(ERR_OK);
  283. }
  284. //*****************************************************************************
  285. //
  286. // Low-Level receive routine. Should allocate a pbuf and transfer the bytes
  287. // of the incoming packet from the interface into the pbuf.
  288. //
  289. //*****************************************************************************
  290. struct pbuf * luminaryif_rx(rt_device_t dev)
  291. {
  292. struct pbuf *p, *q;
  293. u16_t len;
  294. unsigned long ulTemp;
  295. int i;
  296. unsigned long *ptr;
  297. if(!EthernetPacketAvail(ETH_BASE))
  298. {
  299. //
  300. // Enable Ethernet RX Interrupt.
  301. //
  302. EthernetIntEnable(ETH_BASE, ETH_INT_RX);
  303. return(NULL);
  304. }
  305. //
  306. // Obtain the size of the packet and put it into the "len" variable.
  307. // Note: The length returned in the FIFO length position includes the
  308. // two bytes for the length + the 4 bytes for the FCS.
  309. //
  310. ulTemp = HWREG(ETH_BASE + MAC_O_DATA);
  311. len = ulTemp & 0xFFFF;
  312. //
  313. // We allocate a pbuf chain of pbufs from the pool.
  314. //
  315. p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
  316. if(p != NULL)
  317. {
  318. //
  319. // Place the first word into the first pbuf location.
  320. //
  321. *(unsigned long *)p->payload = ulTemp;
  322. p->payload = (char *)(p->payload) + 4;
  323. p->len -= 4;
  324. //
  325. // Process all but the last buffer in the pbuf chain.
  326. //
  327. q = p;
  328. while(q != NULL)
  329. {
  330. //
  331. // Setup a byte pointer into the payload section of the pbuf.
  332. //
  333. ptr = q->payload;
  334. //
  335. // Read data from FIFO into the current pbuf
  336. // (assume pbuf length is modulo 4)
  337. //
  338. for(i = 0; i < q->len; i += 4)
  339. {
  340. *ptr++ = HWREG(ETH_BASE + MAC_O_DATA);
  341. }
  342. //
  343. // Link in the next pbuf in the chain.
  344. //
  345. q = q->next;
  346. }
  347. //
  348. // Restore the first pbuf parameters to their original values.
  349. //
  350. p->payload = (char *)(p->payload) - 4;
  351. p->len += 4;
  352. #if LINK_STATS
  353. lwip_stats.link.recv++;
  354. #endif
  355. }
  356. else
  357. {
  358. //
  359. // Just read all of the remaining data from the FIFO and dump it.
  360. //
  361. for(i = 4; i < len; i+=4)
  362. {
  363. ulTemp = HWREG(ETH_BASE + MAC_O_DATA);
  364. }
  365. #if LINK_STATS
  366. lwip_stats.link.memerr++;
  367. lwip_stats.link.drop++;
  368. #endif
  369. //
  370. // Enable Ethernet RX Interrupt.
  371. //
  372. EthernetIntEnable(ETH_BASE, ETH_INT_RX);
  373. }
  374. return(p);
  375. }
  376. int rt_hw_luminaryif_init(void)
  377. {
  378. rt_err_t result;
  379. unsigned long ulUser0, ulUser1;
  380. /* Enable and Reset the Ethernet Controller. */
  381. SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
  382. SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
  383. /*
  384. Enable Port F for Ethernet LEDs.
  385. LED0 Bit 3 Output
  386. LED1 Bit 2 Output
  387. */
  388. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  389. GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3, GPIO_DIR_MODE_HW);
  390. GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3,
  391. GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
  392. FlashUserSet(0x12345678, 0x12345678);
  393. /* Configure the hardware MAC address */
  394. FlashUserGet(&ulUser0, &ulUser1);
  395. if((ulUser0 == 0xffffffff) || (ulUser1 == 0xffffffff))
  396. {
  397. rt_kprintf("Fatal error in geting MAC address\n");
  398. }
  399. /* init rt-thread device interface */
  400. luminaryif_dev_entry.parent.parent.init = luminaryif_init;
  401. luminaryif_dev_entry.parent.parent.open = luminaryif_open;
  402. luminaryif_dev_entry.parent.parent.close = luminaryif_close;
  403. luminaryif_dev_entry.parent.parent.read = luminaryif_read;
  404. luminaryif_dev_entry.parent.parent.write = luminaryif_write;
  405. luminaryif_dev_entry.parent.parent.control = luminaryif_control;
  406. luminaryif_dev_entry.parent.eth_rx = luminaryif_rx;
  407. luminaryif_dev_entry.parent.eth_tx = luminaryif_tx;
  408. /*
  409. Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
  410. address needed to program the hardware registers, then program the MAC
  411. address into the Ethernet Controller registers.
  412. */
  413. luminaryif_dev_entry.dev_addr[0] = ((ulUser0 >> 0) & 0xff);
  414. luminaryif_dev_entry.dev_addr[1] = ((ulUser0 >> 8) & 0xff);
  415. luminaryif_dev_entry.dev_addr[2] = ((ulUser0 >> 16) & 0xff);
  416. luminaryif_dev_entry.dev_addr[3] = ((ulUser1 >> 0) & 0xff);
  417. luminaryif_dev_entry.dev_addr[4] = ((ulUser1 >> 8) & 0xff);
  418. luminaryif_dev_entry.dev_addr[5] = ((ulUser1 >> 16) & 0xff);
  419. /* Program the hardware with it's MAC address (for filtering). */
  420. EthernetMACAddrSet(ETH_BASE, luminaryif_dev_entry.dev_addr);
  421. rt_sem_init(&tx_sem, "emac", 1, RT_IPC_FLAG_FIFO);
  422. result = eth_device_init(&(luminaryif_dev->parent), "E0");
  423. return result;
  424. }