123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- //*****************************************************************************
- //
- // luminaryif.c - Ethernet Interface File for lwIP TCP/IP Stack
- //
- //*****************************************************************************
- #include <inc/hw_memmap.h>
- #include <inc/hw_types.h>
- #include <inc/hw_ints.h>
- #include <inc/hw_ethernet.h>
- #include <driverlib/ethernet.h>
- #include <driverlib/interrupt.h>
- #include <driverlib/sysctl.h>
- #include <driverlib/gpio.h>
- #include <driverlib/flash.h>
- #include <netif/ethernetif.h>
- #include "lwipopts.h"
- #include "luminaryif.h"
- #define MAX_ADDR_LEN 6
- struct net_device
- {
- /* inherit from ethernet device */
- struct eth_device parent;
- /* interface address info. */
- rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
- };
- static struct net_device luminaryif_dev_entry;
- static struct net_device *luminaryif_dev =&luminaryif_dev_entry;
- static struct rt_semaphore tx_sem;
- //*****************************************************************************
- //
- // Sanity Check: This module will NOT work if the following defines
- // are incorrect.
- //
- //*****************************************************************************
- #if (PBUF_LINK_HLEN != 16)
- #error "Incorrect PBUF_LINK_HLEN specified!"
- #endif
- #if (ETH_PAD_SIZE != 2)
- #error "Incorrect ETH_PAD_SIZE specified!"
- #endif
- #if (PBUF_POOL_BUFSIZE % 4)
- #error "PBUF_POOL_BUFSIZE must be modulo 4!"
- #endif
- /* RT-Thread Device Interface */
- /* initialize the interface */
- //*****************************************************************************
- //
- // Low-Level initialization function for the Ethernet Controller.
- //
- //*****************************************************************************
- rt_err_t luminaryif_init(rt_device_t dev)
- {
- unsigned long ulTemp;
- //
- // Disable all Ethernet Interrupts.
- //
- EthernetIntDisable(ETH_BASE, (ETH_INT_PHY | ETH_INT_MDIO | ETH_INT_RXER |
- ETH_INT_RXOF | ETH_INT_TX | ETH_INT_TXER |
- ETH_INT_RX));
- ulTemp = EthernetIntStatus(ETH_BASE, false);
- EthernetIntClear(ETH_BASE, ulTemp);
- //
- // Initialize the Ethernet Controller.
- //
- EthernetInitExpClk(ETH_BASE, SysCtlClockGet());
- //
- // Configure the Ethernet Controller for normal operation.
- // - Enable TX Duplex Mode
- // - Enable TX Padding
- // - Enable TX CRC Generation
- //
- EthernetConfigSet(ETH_BASE, (ETH_CFG_TX_DPLXEN |
- ETH_CFG_TX_CRCEN | ETH_CFG_TX_PADEN));
- //
- // Enable the Ethernet Controller transmitter and receiver.
- //
- EthernetEnable(ETH_BASE);
- //
- // Enable the Ethernet Interrupt handler.
- //
- IntEnable(INT_ETH);
- //
- // Enable Ethernet TX and RX Packet Interrupts.
- //
- EthernetIntEnable(ETH_BASE, ETH_INT_RX | ETH_INT_TX);
- return RT_EOK;
- }
- void luminaryif_isr(void)
- {
- unsigned long ulTemp;
- //
- // Read and Clear the interrupt.
- //
- ulTemp = EthernetIntStatus(ETH_BASE, false);
- EthernetIntClear(ETH_BASE, ulTemp);
- //
- // Check to see if an RX Interrupt has occured.
- //
- if(ulTemp & ETH_INT_RX)
- {
- //
- // Indicate that a packet has been received.
- //
- rt_err_t result;
- /* a frame has been received */
- result = eth_device_ready((struct eth_device*)&(luminaryif_dev->parent));
- if(result != RT_EOK) rt_set_errno(-RT_ERROR);
- //
- // Disable Ethernet RX Interrupt.
- //
- EthernetIntDisable(ETH_BASE, ETH_INT_RX);
- }
- if(ulTemp & ETH_INT_TX)
- {
- /* A frame has been transmitted. */
- rt_sem_release(&tx_sem);
- }
- }
- /* control the interface */
- rt_err_t luminaryif_control(rt_device_t dev, rt_uint8_t cmd, void *args)
- {
- switch(cmd)
- {
- case NIOCTL_GADDR:
- /* get mac address */
- if(args) rt_memcpy(args, luminaryif_dev_entry.dev_addr, 6);
- else return -RT_ERROR;
- break;
- default :
- break;
- }
- return RT_EOK;
- }
- /* Open the ethernet interface */
- rt_err_t luminaryif_open(rt_device_t dev, rt_uint16_t oflag)
- {
- return RT_EOK;
- }
- /* Close the interface */
- rt_err_t luminaryif_close(rt_device_t dev)
- {
- return RT_EOK;
- }
- /* Read */
- rt_size_t luminaryif_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
- {
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- /* Write */
- rt_size_t luminaryif_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
- {
- rt_set_errno(-RT_ENOSYS);
- return 0;
- }
- //****************************************************************************
- //
- // Low-Level transmit routine. Should do the actual transmission of the
- // packet. The packet is contained in the pbuf that is passed to the function.
- // This pbuf might be chained.
- //
- //****************************************************************************
- rt_err_t luminaryif_tx(rt_device_t dev, struct pbuf *p)
- {
- int iBuf;
- unsigned char *pucBuf;
- unsigned long *pulBuf;
- struct pbuf *q;
- int iGather;
- unsigned long ulGather;
- unsigned char *pucGather;
- unsigned long ulTemp;
- /* lock tx operation */
- rt_sem_take(&tx_sem, RT_WAITING_FOREVER);
- //
- // Wait for space available in the TX FIFO.
- //
- while(!EthernetSpaceAvail(ETH_BASE))
- {
- }
- //
- // Fill in the first two bytes of the payload data (configured as padding
- // with ETH_PAD_SIZE = 2) with the total length of the payload data
- // (minus the Ethernet MAC layer header).
- //
- *((unsigned short *)(p->payload)) = p->tot_len - 16;
- //
- // Initialize the gather register.
- //
- iGather = 0;
- pucGather = (unsigned char *)&ulGather;
- ulGather = 0;
- //
- // Copy data from the pbuf(s) into the TX Fifo.
- //
- for(q = p; q != NULL; q = q->next)
- {
- //
- // Intialize a char pointer and index to the pbuf payload data.
- //
- pucBuf = (unsigned char *)q->payload;
- iBuf = 0;
- //
- // If the gather buffer has leftover data from a previous pbuf
- // in the chain, fill it up and write it to the Tx FIFO.
- //
- while((iBuf < q->len) && (iGather != 0))
- {
- //
- // Copy a byte from the pbuf into the gather buffer.
- //
- pucGather[iGather] = pucBuf[iBuf++];
- //
- // Increment the gather buffer index modulo 4.
- //
- iGather = ((iGather + 1) % 4);
- }
- //
- // If the gather index is 0 and the pbuf index is non-zero,
- // we have a gather buffer to write into the Tx FIFO.
- //
- if((iGather == 0) && (iBuf != 0))
- {
- HWREG(ETH_BASE + MAC_O_DATA) = ulGather;
- ulGather = 0;
- }
- //
- // Copy words of pbuf data into the Tx FIFO, but don't go past
- // the end of the pbuf.
- //
- if((iBuf % 4) != 0)
- {
- while((iBuf + 4) <= q->len)
- {
- ulTemp = (pucBuf[iBuf++] << 0);
- ulTemp |= (pucBuf[iBuf++] << 8);
- ulTemp |= (pucBuf[iBuf++] << 16);
- ulTemp |= (pucBuf[iBuf++] << 24);
- HWREG(ETH_BASE + MAC_O_DATA) = ulTemp;
- }
- }
- else
- {
- //
- // Initialze a long pointer into the pbuf for 32-bit access.
- //
- pulBuf = (unsigned long *)&pucBuf[iBuf];
- while((iBuf + 4) <= q->len)
- {
- HWREG(ETH_BASE + MAC_O_DATA) = *pulBuf++;
- iBuf += 4;
- }
- }
- //
- // Check if leftover data in the pbuf and save it in the gather
- // buffer for the next time.
- //
- while(iBuf < q->len)
- {
- //
- // Copy a byte from the pbuf into the gather buffer.
- //
- pucGather[iGather] = pucBuf[iBuf++];
- //
- // Increment the gather buffer index modulo 4.
- //
- iGather = ((iGather + 1) % 4);
- }
- }
- //
- // Send any leftover data to the FIFO.
- //
- HWREG(ETH_BASE + MAC_O_DATA) = ulGather;
- //
- // Wakeup the transmitter.
- //
- HWREG(ETH_BASE + MAC_O_TR) = MAC_TR_NEWTX;
- #if LINK_STATS
- lwip_stats.link.xmit++;
- #endif
- return(ERR_OK);
- }
- //*****************************************************************************
- //
- // Low-Level receive routine. Should allocate a pbuf and transfer the bytes
- // of the incoming packet from the interface into the pbuf.
- //
- //*****************************************************************************
- struct pbuf * luminaryif_rx(rt_device_t dev)
- {
- struct pbuf *p, *q;
- u16_t len;
- unsigned long ulTemp;
- int i;
- unsigned long *ptr;
- if(!EthernetPacketAvail(ETH_BASE))
- {
- //
- // Enable Ethernet RX Interrupt.
- //
- EthernetIntEnable(ETH_BASE, ETH_INT_RX);
- return(NULL);
- }
- //
- // Obtain the size of the packet and put it into the "len" variable.
- // Note: The length returned in the FIFO length position includes the
- // two bytes for the length + the 4 bytes for the FCS.
- //
- ulTemp = HWREG(ETH_BASE + MAC_O_DATA);
- len = ulTemp & 0xFFFF;
- //
- // We allocate a pbuf chain of pbufs from the pool.
- //
- p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
- if(p != NULL)
- {
- //
- // Place the first word into the first pbuf location.
- //
- *(unsigned long *)p->payload = ulTemp;
- p->payload = (char *)(p->payload) + 4;
- p->len -= 4;
- //
- // Process all but the last buffer in the pbuf chain.
- //
- q = p;
- while(q != NULL)
- {
- //
- // Setup a byte pointer into the payload section of the pbuf.
- //
- ptr = q->payload;
- //
- // Read data from FIFO into the current pbuf
- // (assume pbuf length is modulo 4)
- //
- for(i = 0; i < q->len; i += 4)
- {
- *ptr++ = HWREG(ETH_BASE + MAC_O_DATA);
- }
- //
- // Link in the next pbuf in the chain.
- //
- q = q->next;
- }
- //
- // Restore the first pbuf parameters to their original values.
- //
- p->payload = (char *)(p->payload) - 4;
- p->len += 4;
- #if LINK_STATS
- lwip_stats.link.recv++;
- #endif
- }
- else
- {
- //
- // Just read all of the remaining data from the FIFO and dump it.
- //
- for(i = 4; i < len; i+=4)
- {
- ulTemp = HWREG(ETH_BASE + MAC_O_DATA);
- }
- #if LINK_STATS
- lwip_stats.link.memerr++;
- lwip_stats.link.drop++;
- #endif
- }
- return(p);
- }
- int rt_hw_luminaryif_init(void)
- {
- rt_err_t result;
- unsigned long ulUser0, ulUser1;
- /* Enable and Reset the Ethernet Controller. */
- SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
- SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
- /*
- Enable Port F for Ethernet LEDs.
- LED0 Bit 3 Output
- LED1 Bit 2 Output
- */
- SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
- /* GPIODirModeSet and GPIOPadConfigSet */
- GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);
- GPIOPinConfigure(GPIO_PF2_LED1);
- GPIOPinConfigure(GPIO_PF3_LED0);
- FlashUserSet(0x00371200, 0x00563412); /* OUI:00-12-37 (hex) Texas Instruments, only for test */
- /* Configure the hardware MAC address */
- FlashUserGet(&ulUser0, &ulUser1);
- if((ulUser0 == 0xffffffff) || (ulUser1 == 0xffffffff))
- {
- rt_kprintf("Fatal error in geting MAC address\n");
- }
- /* init rt-thread device interface */
- luminaryif_dev_entry.parent.parent.init = luminaryif_init;
- luminaryif_dev_entry.parent.parent.open = luminaryif_open;
- luminaryif_dev_entry.parent.parent.close = luminaryif_close;
- luminaryif_dev_entry.parent.parent.read = luminaryif_read;
- luminaryif_dev_entry.parent.parent.write = luminaryif_write;
- luminaryif_dev_entry.parent.parent.control = luminaryif_control;
- luminaryif_dev_entry.parent.eth_rx = luminaryif_rx;
- luminaryif_dev_entry.parent.eth_tx = luminaryif_tx;
- /*
- Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
- address needed to program the hardware registers, then program the MAC
- address into the Ethernet Controller registers.
- */
- luminaryif_dev_entry.dev_addr[0] = ((ulUser0 >> 0) & 0xff);
- luminaryif_dev_entry.dev_addr[1] = ((ulUser0 >> 8) & 0xff);
- luminaryif_dev_entry.dev_addr[2] = ((ulUser0 >> 16) & 0xff);
- luminaryif_dev_entry.dev_addr[3] = ((ulUser1 >> 0) & 0xff);
- luminaryif_dev_entry.dev_addr[4] = ((ulUser1 >> 8) & 0xff);
- luminaryif_dev_entry.dev_addr[5] = ((ulUser1 >> 16) & 0xff);
- /* Program the hardware with it's MAC address (for filtering). */
- EthernetMACAddrSet(ETH_BASE, luminaryif_dev_entry.dev_addr);
- rt_sem_init(&tx_sem, "emac", 1, RT_IPC_FLAG_FIFO);
- result = eth_device_init(&(luminaryif_dev->parent), "E0");
- return result;
- }
|