//***************************************************************************** // // lwiplib.c - lwIP TCP/IP Library Abstraction Layer. // // Copyright (c) 2008-2016 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 2.1.3.156 of the Tiva Utility Library. // //***************************************************************************** //***************************************************************************** // // Ensure that the lwIP compile time options are included first. // //***************************************************************************** #include #include #include "utils/lwiplib.h" //***************************************************************************** // // Ensure that ICMP checksum offloading is enabled; otherwise the TM4C129 // driver will not operate correctly. // //***************************************************************************** #ifndef LWIP_OFFLOAD_ICMP_CHKSUM #define LWIP_OFFLOAD_ICMP_CHKSUM 1 #endif //***************************************************************************** // // Include lwIP high-level API code. // //***************************************************************************** #include "third_party/lwip-2.0.0/src/api/api_lib.c" #include "third_party/lwip-2.0.0/src/api/api_msg.c" #include "third_party/lwip-2.0.0/src/api/err.c" #include "third_party/lwip-2.0.0/src/api/netbuf.c" #include "third_party/lwip-2.0.0/src/api/netdb.c" #include "third_party/lwip-2.0.0/src/api/netifapi.c" #include "third_party/lwip-2.0.0/src/api/sockets.c" #include "third_party/lwip-2.0.0/src/api/tcpip.c" //***************************************************************************** // // Include the core lwIP TCP/IP stack code. // //***************************************************************************** #include "third_party/lwip-2.0.0/src/core/def.c" #include "third_party/lwip-2.0.0/src/core/ipv4/dhcp.c" #include "third_party/lwip-2.0.0/src/core/inet_chksum.c" #include "third_party/lwip-2.0.0/src/core/dns.c" #include "third_party/lwip-2.0.0/src/core/init.c" #include "third_party/lwip-2.0.0/src/core/mem.c" #include "third_party/lwip-2.0.0/src/core/memp.c" #include "third_party/lwip-2.0.0/src/core/netif.c" #include "third_party/lwip-2.0.0/src/core/pbuf.c" #include "third_party/lwip-2.0.0/src/core/raw.c" #include "third_party/lwip-2.0.0/src/core/stats.c" #include "third_party/lwip-2.0.0/src/core/sys.c" #include "third_party/lwip-2.0.0/src/core/ip.c" #include "third_party/lwip-2.0.0/src/core/tcp.c" #include "third_party/lwip-2.0.0/src/core/tcp_in.c" #include "third_party/lwip-2.0.0/src/core/tcp_out.c" #include "third_party/lwip-2.0.0/src/core/timeouts.c" #include "third_party/lwip-2.0.0/src/core/udp.c" //***************************************************************************** // // Include the IPV4 code. // //***************************************************************************** #include "third_party/lwip-2.0.0/src/core/ipv4/autoip.c" #include "third_party/lwip-2.0.0/src/core/ipv4/etharp.c" #include "third_party/lwip-2.0.0/src/core/ipv4/icmp.c" #include "third_party/lwip-2.0.0/src/core/ipv4/igmp.c" //#include "third_party/lwip-2.0.0/src/core/ipv4/inet.c" //#include "third_party/lwip-2.0.0/src/core/ipv4/inet_chksum.c" #include "third_party/lwip-2.0.0/src/core/ipv4/ip4.c" #include "third_party/lwip-2.0.0/src/core/ipv4/ip4_addr.c" #include "third_party/lwip-2.0.0/src/core/ipv4/ip4_frag.c" //***************************************************************************** // // Include the IPV6 code. // Note: Code is experimental and not ready for use. // References are included for completeness. // //***************************************************************************** #if 0 #include "third_party/lwip-2.0.0/src/core/ipv6/icmp6.c" #include "third_party/lwip-2.0.0/src/core/ipv6/inet6.c" #include "third_party/lwip-2.0.0/src/core/ipv6/ip6.c" #include "third_party/lwip-2.0.0/src/core/ipv6/ip6_addr.c" #endif //***************************************************************************** // // Include the lwIP SNMP code. // //***************************************************************************** //#include "third_party/lwip-2.0.0/src/core/snmp/asn1_dec.c" //#include "third_party/lwip-2.0.0/src/core/snmp/asn1_enc.c" //#include "third_party/lwip-2.0.0/src/core/snmp/mib2.c" //#include "third_party/lwip-2.0.0/src/core/snmp/mib_structs.c" //#include "third_party/lwip-2.0.0/src/core/snmp/msg_in.c" //#include "third_party/lwip-2.0.0/src/core/snmp/msg_out.c" //***************************************************************************** // // Include the network interface code. // //***************************************************************************** #include "third_party/lwip-2.0.0/src/netif/ethernet.c" //#include "third_party/lwip-2.0.0/src/netif/lldp.c" //***************************************************************************** // // Include the network interface PPP code. // //***************************************************************************** #include "third_party/lwip-2.0.0/src/netif/ppp/auth.c" #include "third_party/lwip-2.0.0/src/netif/ppp/chap_ms.c" #include "third_party/lwip-2.0.0/src/netif/ppp/chap-md5.c" #include "third_party/lwip-2.0.0/src/netif/ppp/chap-new.c" //#include "third_party/lwip-2.0.0/src/netif/ppp/chpms.c" //#include "third_party/lwip-2.0.0/src/netif/ppp/fsm.c" #include "third_party/lwip-2.0.0/src/netif/ppp/ipcp.c" #include "third_party/lwip-2.0.0/src/netif/ppp/lcp.c" #include "third_party/lwip-2.0.0/src/netif/ppp/magic.c" #include "third_party/lwip-2.0.0/src/netif/ppp/polarssl/md5.c" //#include "third_party/lwip-2.0.0/src/netif/ppp/pap.c" #include "third_party/lwip-2.0.0/src/netif/ppp/ppp.c" #include "third_party/lwip-2.0.0/src/netif/ppp/pppoe.c" //#include "third_party/lwip-2.0.0/src/netif/ppp/randm.c" #include "third_party/lwip-2.0.0/src/netif/ppp/vj.c" //***************************************************************************** // // Include Tiva-specific lwIP interface/porting layer code. // //***************************************************************************** #include "third_party/lwip-2.0.0/ports/tiva-tm4c129/perf.c" #include "third_party/lwip-2.0.0/ports/tiva-tm4c129/sys_arch.c" #include "third_party/lwip-2.0.0/ports/tiva-tm4c129/netif/tiva-tm4c129.c" //***************************************************************************** // //! \addtogroup lwiplib_api //! @{ // //***************************************************************************** //***************************************************************************** // // The lwIP Library abstration layer provides for a host callback function to // be called periodically in the lwIP context. This is the timer interval, in // ms, for this periodic callback. If the timer interval is defined to 0 (the // default value), then no periodic host callback is performed. // //***************************************************************************** #ifndef HOST_TMR_INTERVAL #define HOST_TMR_INTERVAL 0 #else extern void lwIPHostTimerHandler(void); #endif //***************************************************************************** // // The link detect polling interval. // //***************************************************************************** #define LINK_TMR_INTERVAL 10 //***************************************************************************** // // Set the PHY configuration to the default (internal) option if necessary. // //***************************************************************************** #ifndef EMAC_PHY_CONFIG #define EMAC_PHY_CONFIG (EMAC_PHY_TYPE_INTERNAL | \ EMAC_PHY_INT_MDIX_EN | \ EMAC_PHY_AN_100B_T_FULL_DUPLEX) #endif //***************************************************************************** // // Driverlib headers needed for this library module. // //***************************************************************************** #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_nvic.h" #include "driverlib/debug.h" #include "driverlib/emac.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #if !NO_SYS #if RTOS_FREERTOS #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" #endif #if ((RTOS_FREERTOS) < 1) #error No RTOS is defined. Please define an RTOS. #endif #if ((RTOS_FREERTOS) > 1) #error More than one RTOS defined. Please define only one RTOS at a time. #endif #endif //***************************************************************************** // // The lwIP network interface structure for the Tiva Ethernet MAC. // //***************************************************************************** static struct netif g_sNetIF; //***************************************************************************** // // The application's interrupt handler for hardware timer events from the MAC. // //***************************************************************************** tHardwareTimerHandler g_pfnTimerHandler; //***************************************************************************** // // The local time for the lwIP Library Abstraction layer, used to support the // Host and lwIP periodic callback functions. // //***************************************************************************** #if NO_SYS uint32_t g_ui32LocalTimer = 0; #endif //***************************************************************************** // // The local time when the TCP timer was last serviced. // //***************************************************************************** #if NO_SYS static uint32_t g_ui32TCPTimer = 0; #endif //***************************************************************************** // // The local time when the HOST timer was last serviced. // //***************************************************************************** #if NO_SYS && HOST_TMR_INTERVAL static uint32_t g_ui32HostTimer = 0; #endif //***************************************************************************** // // The local time when the ARP timer was last serviced. // //***************************************************************************** #if NO_SYS && LWIP_ARP static uint32_t g_ui32ARPTimer = 0; #endif //***************************************************************************** // // The local time when the AutoIP timer was last serviced. // //***************************************************************************** #if NO_SYS && LWIP_AUTOIP static uint32_t g_ui32AutoIPTimer = 0; #endif //***************************************************************************** // // The local time when the DHCP Coarse timer was last serviced. // //***************************************************************************** #if NO_SYS && LWIP_DHCP static uint32_t g_ui32DHCPCoarseTimer = 0; #endif //***************************************************************************** // // The local time when the DHCP Fine timer was last serviced. // //***************************************************************************** #if NO_SYS && LWIP_DHCP static uint32_t g_ui32DHCPFineTimer = 0; #endif //***************************************************************************** // // The local time when the IP Reassembly timer was last serviced. // //***************************************************************************** #if NO_SYS && IP_REASSEMBLY static uint32_t g_ui32IPReassemblyTimer = 0; #endif //***************************************************************************** // // The local time when the IGMP timer was last serviced. // //***************************************************************************** #if NO_SYS && LWIP_IGMP static uint32_t g_ui32IGMPTimer = 0; #endif //***************************************************************************** // // The local time when the DNS timer was last serviced. // //***************************************************************************** #if NO_SYS && LWIP_DNS static uint32_t g_ui32DNSTimer = 0; #endif //***************************************************************************** // // The local time when the link detect timer was last serviced. // //***************************************************************************** #if NO_SYS && (LWIP_AUTOIP || LWIP_DHCP) static uint32_t g_ui32LinkTimer = 0; #endif //***************************************************************************** // // The default IP address acquisition mode. // //***************************************************************************** static uint32_t g_ui32IPMode = IPADDR_USE_STATIC; //***************************************************************************** // // The most recently detected link state. // //***************************************************************************** #if LWIP_AUTOIP || LWIP_DHCP static bool g_bLinkActive = false; #endif //***************************************************************************** // // The IP address to be used. This is used during the initialization of the // stack and when the interface configuration is changed. // //***************************************************************************** static uint32_t g_ui32IPAddr; //***************************************************************************** // // The netmask to be used. This is used during the initialization of the stack // and when the interface configuration is changed. // //***************************************************************************** static uint32_t g_ui32NetMask; //***************************************************************************** // // The gateway address to be used. This is used during the initialization of // the stack and when the interface configuration is changed. // //***************************************************************************** static uint32_t g_ui32GWAddr; //***************************************************************************** // // The stack size for the interrupt task. // //***************************************************************************** #if !NO_SYS #define STACKSIZE_LWIPINTTASK 128 #endif //***************************************************************************** // // The handle for the "queue" (semaphore) used to signal the interrupt task // from the interrupt handler. // //***************************************************************************** #if !NO_SYS static xQueueHandle g_pInterrupt; #endif //***************************************************************************** // // This task handles reading packets from the Ethernet controller and supplying // them to the TCP/IP thread. // //***************************************************************************** #if !NO_SYS static void lwIPInterruptTask(void *pvArg) { // // Loop forever. // while(1) { // // Wait until the semaphore has been signaled. // while(xQueueReceive(g_pInterrupt, &pvArg, portMAX_DELAY) != pdPASS) { } // // Processes any packets waiting to be sent or received. // tivaif_interrupt(&g_sNetIF, (uint32_t)pvArg); // // Re-enable the Ethernet interrupts. // MAP_EMACIntEnable(EMAC0_BASE, (EMAC_INT_RECEIVE | EMAC_INT_TRANSMIT | EMAC_INT_TX_STOPPED | EMAC_INT_RX_NO_BUFFER | EMAC_INT_RX_STOPPED | EMAC_INT_PHY)); } } #endif //***************************************************************************** // // This function performs a periodic check of the link status and responds // appropriately if it has changed. // //***************************************************************************** #if LWIP_AUTOIP || LWIP_DHCP static void lwIPLinkDetect(void) { bool bHaveLink; ip_addr_t ip_addr; ip_addr_t net_mask; ip_addr_t gw_addr; // // See if there is an active link. // bHaveLink = MAP_EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMSR) & EPHY_BMSR_LINKSTAT; // // Return without doing anything else if the link state hasn't changed. // if(bHaveLink == g_bLinkActive) { return; } // // Save the new link state. // g_bLinkActive = bHaveLink; // // Clear any address information from the network interface. // ip_addr.addr = 0; net_mask.addr = 0; gw_addr.addr = 0; netif_set_addr(&g_sNetIF, &ip_addr, &net_mask, &gw_addr); // // See if there is a link now. // if(bHaveLink) { // // Start DHCP, if enabled. // #if LWIP_DHCP if(g_ui32IPMode == IPADDR_USE_DHCP) { dhcp_start(&g_sNetIF); } #endif // // Start AutoIP, if enabled and DHCP is not. // #if LWIP_AUTOIP if(g_ui32IPMode == IPADDR_USE_AUTOIP) { autoip_start(&g_sNetIF); } #endif } else { // // Stop DHCP, if enabled. // #if LWIP_DHCP if(g_ui32IPMode == IPADDR_USE_DHCP) { dhcp_stop(&g_sNetIF); } #endif // // Stop AutoIP, if enabled and DHCP is not. // #if LWIP_AUTOIP if(g_ui32IPMode == IPADDR_USE_AUTOIP) { autoip_stop(&g_sNetIF); } #endif } } #endif //***************************************************************************** // // This function services all of the lwIP periodic timers, including TCP and // Host timers. This should be called from the lwIP context, which may be // the Ethernet interrupt (in the case of a non-RTOS system) or the lwIP // thread, in the event that an RTOS is used. // //***************************************************************************** #if NO_SYS static void lwIPServiceTimers(void) { // // Service the host timer. // #if HOST_TMR_INTERVAL if((g_ui32LocalTimer - g_ui32HostTimer) >= HOST_TMR_INTERVAL) { g_ui32HostTimer = g_ui32LocalTimer; lwIPHostTimerHandler(); } #endif // // Service the ARP timer. // #if LWIP_ARP if((g_ui32LocalTimer - g_ui32ARPTimer) >= ARP_TMR_INTERVAL) { g_ui32ARPTimer = g_ui32LocalTimer; etharp_tmr(); } #endif // // Service the TCP timer. // #if LWIP_TCP if((g_ui32LocalTimer - g_ui32TCPTimer) >= TCP_TMR_INTERVAL) { g_ui32TCPTimer = g_ui32LocalTimer; tcp_tmr(); } #endif // // Service the AutoIP timer. // #if LWIP_AUTOIP if((g_ui32LocalTimer - g_ui32AutoIPTimer) >= AUTOIP_TMR_INTERVAL) { g_ui32AutoIPTimer = g_ui32LocalTimer; autoip_tmr(); } #endif // // Service the DCHP Coarse Timer. // #if LWIP_DHCP if((g_ui32LocalTimer - g_ui32DHCPCoarseTimer) >= DHCP_COARSE_TIMER_MSECS) { g_ui32DHCPCoarseTimer = g_ui32LocalTimer; dhcp_coarse_tmr(); } #endif // // Service the DCHP Fine Timer. // #if LWIP_DHCP if((g_ui32LocalTimer - g_ui32DHCPFineTimer) >= DHCP_FINE_TIMER_MSECS) { g_ui32DHCPFineTimer = g_ui32LocalTimer; dhcp_fine_tmr(); } #endif // // Service the IP Reassembly Timer // #if IP_REASSEMBLY if((g_ui32LocalTimer - g_ui32IPReassemblyTimer) >= IP_TMR_INTERVAL) { g_ui32IPReassemblyTimer = g_ui32LocalTimer; ip_reass_tmr(); } #endif // // Service the IGMP Timer // #if LWIP_IGMP if((g_ui32LocalTimer - g_ui32IGMPTimer) >= IGMP_TMR_INTERVAL) { g_ui32IGMPTimer = g_ui32LocalTimer; igmp_tmr(); } #endif // // Service the DNS Timer // #if LWIP_DNS if((g_ui32LocalTimer - g_ui32DNSTimer) >= DNS_TMR_INTERVAL) { g_ui32DNSTimer = g_ui32LocalTimer; dns_tmr(); } #endif // // Service the link timer. // #if LWIP_AUTOIP || LWIP_DHCP if((g_ui32LocalTimer - g_ui32LinkTimer) >= LINK_TMR_INTERVAL) { g_ui32LinkTimer = g_ui32LocalTimer; lwIPLinkDetect(); } #endif } #endif //***************************************************************************** // // Handles the timeout for the host callback function timer when using a RTOS. // //***************************************************************************** #if !NO_SYS && HOST_TMR_INTERVAL static void lwIPPrivateHostTimer(void *pvArg) { // // Call the application-supplied host timer callback function. // lwIPHostTimerHandler(); // // Re-schedule the host timer callback function timeout. // sys_timeout(HOST_TMR_INTERVAL, lwIPPrivateHostTimer, NULL); } #endif //***************************************************************************** // // Handles the timeout for the link detect timer when using a RTOS. // //***************************************************************************** #if !NO_SYS && (LWIP_AUTOIP || LWIP_DHCP) static void lwIPPrivateLinkTimer(void *pvArg) { // // Perform the link detection. // lwIPLinkDetect(); // // Re-schedule the link detect timer timeout. // sys_timeout(LINK_TMR_INTERVAL, lwIPPrivateLinkTimer, NULL); } #endif //***************************************************************************** // // Completes the initialization of lwIP. This is directly called when not // using a RTOS and provided as a callback to the TCP/IP thread when using a // RTOS. // //***************************************************************************** static void lwIPPrivateInit(void *pvArg) { ip_addr_t ip_addr; ip_addr_t net_mask; ip_addr_t gw_addr; // // If not using a RTOS, initialize the lwIP stack. // #if NO_SYS lwip_init(); #endif // // If using a RTOS, create a queue (to be used as a semaphore) to signal // the Ethernet interrupt task from the Ethernet interrupt handler. // #if !NO_SYS #if RTOS_FREERTOS g_pInterrupt = xQueueCreate(1, sizeof(void *)); #endif #endif // // If using a RTOS, create the Ethernet interrupt task. // #if !NO_SYS #if RTOS_FREERTOS xTaskCreate(lwIPInterruptTask, (signed portCHAR *)"eth_int", STACKSIZE_LWIPINTTASK, 0, tskIDLE_PRIORITY + 1, 0); #endif #endif // // Setup the network address values. // if(g_ui32IPMode == IPADDR_USE_STATIC) { ip_addr.addr = htonl(g_ui32IPAddr); net_mask.addr = htonl(g_ui32NetMask); gw_addr.addr = htonl(g_ui32GWAddr); } else { ip_addr.addr = 0; net_mask.addr = 0; gw_addr.addr = 0; } // // Create, configure and add the Ethernet controller interface with // default settings. ip_input should be used to send packets directly to // the stack when not using a RTOS and tcpip_input should be used to send // packets to the TCP/IP thread's queue when using a RTOS. // #if NO_SYS netif_add(&g_sNetIF, &ip_addr, &net_mask, &gw_addr, NULL, tivaif_init, ip_input); #else netif_add(&g_sNetIF, &ip_addr, &net_mask, &gw_addr, NULL, tivaif_init, tcpip_input); #endif netif_set_default(&g_sNetIF); // // Bring the interface up. // netif_set_up(&g_sNetIF); // // Setup a timeout for the host timer callback function if using a RTOS. // #if !NO_SYS && HOST_TMR_INTERVAL sys_timeout(HOST_TMR_INTERVAL, lwIPPrivateHostTimer, NULL); #endif // // Setup a timeout for the link detect callback function if using a RTOS. // #if !NO_SYS && (LWIP_AUTOIP || LWIP_DHCP) sys_timeout(LINK_TMR_INTERVAL, lwIPPrivateLinkTimer, NULL); #endif } //***************************************************************************** // //! Initializes the lwIP TCP/IP stack. //! //! \param ui32SysClkHz is the current system clock rate in Hz. //! \param pui8MAC is a pointer to a six byte array containing the MAC //! address to be used for the interface. //! \param ui32IPAddr is the IP address to be used (static). //! \param ui32NetMask is the network mask to be used (static). //! \param ui32GWAddr is the Gateway address to be used (static). //! \param ui32IPMode is the IP Address Mode. \b IPADDR_USE_STATIC will force //! static IP addressing to be used, \b IPADDR_USE_DHCP will force DHCP with //! fallback to Link Local (Auto IP), while \b IPADDR_USE_AUTOIP will force //! Link Local only. //! //! This function performs initialization of the lwIP TCP/IP stack for the //! Ethernet MAC, including DHCP and/or AutoIP, as configured. //! //! \return None. // //***************************************************************************** void lwIPInit(uint32_t ui32SysClkHz, const uint8_t *pui8MAC, uint32_t ui32IPAddr, uint32_t ui32NetMask, uint32_t ui32GWAddr, uint32_t ui32IPMode) { // // Check the parameters. // #if LWIP_DHCP && LWIP_AUTOIP ASSERT((ui32IPMode == IPADDR_USE_STATIC) || (ui32IPMode == IPADDR_USE_DHCP) || (ui32IPMode == IPADDR_USE_AUTOIP)); #elif LWIP_DHCP ASSERT((ui32IPMode == IPADDR_USE_STATIC) || (ui32IPMode == IPADDR_USE_DHCP)); #elif LWIP_AUTOIP ASSERT((ui32IPMode == IPADDR_USE_STATIC) || (ui32IPMode == IPADDR_USE_AUTOIP)); #else ASSERT(ui32IPMode == IPADDR_USE_STATIC); #endif // // Enable the ethernet peripheral. // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0); MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0); // // Enable the internal PHY if it's present and we're being // asked to use it. // if((EMAC_PHY_CONFIG & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_INTERNAL) { // // We've been asked to configure for use with the internal // PHY. Is it present? // if(MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_EPHY0)) { // // Yes - enable and reset it. // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0); MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0); } else { // // Internal PHY is not present on this part so hang here. // while(1) { } } } // // Wait for the MAC to come out of reset. // while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0)) { } // // Configure for use with whichever PHY the user requires. // EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_CONFIG); // // Reset the MAC. // //MAP_EMACReset(EMAC0_BASE); // // Initialize the MAC and set the DMA mode. // MAP_EMACInit(EMAC0_BASE, ui32SysClkHz, EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4, 0); // // Set MAC configuration options. // MAP_EMACConfigSet(EMAC0_BASE, (EMAC_CONFIG_FULL_DUPLEX | //EMAC_CONFIG_100MBPS | EMAC_CONFIG_CHECKSUM_OFFLOAD | EMAC_CONFIG_7BYTE_PREAMBLE | EMAC_CONFIG_IF_GAP_96BITS | EMAC_CONFIG_USE_MACADDR0 | EMAC_CONFIG_SA_FROM_DESCRIPTOR | EMAC_CONFIG_BO_LIMIT_1024), (EMAC_MODE_RX_STORE_FORWARD | EMAC_MODE_TX_STORE_FORWARD | EMAC_MODE_TX_THRESHOLD_64_BYTES | EMAC_MODE_RX_THRESHOLD_64_BYTES), 0); // // Program the hardware with its MAC address (for filtering). // MAP_EMACAddrSet(EMAC0_BASE, 0, (uint8_t *)pui8MAC); // // Save the network configuration for later use by the private // initialization. // g_ui32IPMode = ui32IPMode; g_ui32IPAddr = ui32IPAddr; g_ui32NetMask = ui32NetMask; g_ui32GWAddr = ui32GWAddr; // // Initialize lwIP. The remainder of initialization is done immediately if // not using a RTOS and it is deferred to the TCP/IP thread's context if // using a RTOS. // #if NO_SYS lwIPPrivateInit(0); #else tcpip_init(lwIPPrivateInit, 0); #endif } //***************************************************************************** // //! Registers an interrupt callback function to handle the IEEE-1588 timer. //! //! \param pfnTimerFunc points to a function which is called whenever the //! Ethernet MAC reports an interrupt relating to the IEEE-1588 hardware timer. //! //! This function allows an application to register a handler for all //! interrupts generated by the IEEE-1588 hardware timer in the Ethernet MAC. //! To allow minimal latency timer handling, the callback function provided //! will be called in interrupt context, regardless of whether or not lwIP is //! configured to operate with an RTOS. In an RTOS environment, the callback //! function is responsible for ensuring that all processing it performs is //! compatible with the low level interrupt context it is called in. //! //! The callback function takes two parameters. The first is the base address //! of the MAC reporting the timer interrupt and the second is the timer //! interrupt status as reported by EMACTimestampIntStatus(). Note that //! EMACTimestampIntStatus() causes the timer interrupt sources to be cleared //! so the application should not call EMACTimestampIntStatus() within the //! handler. //! //! \return None. // //***************************************************************************** void lwIPTimerCallbackRegister(tHardwareTimerHandler pfnTimerFunc) { // // Remember the callback function address passed. // g_pfnTimerHandler = pfnTimerFunc; } //***************************************************************************** // //! Handles periodic timer events for the lwIP TCP/IP stack. //! //! \param ui32TimeMS is the incremental time for this periodic interrupt. //! //! This function will update the local timer by the value in \e ui32TimeMS. //! If the system is configured for use without an RTOS, an Ethernet interrupt //! will be triggered to allow the lwIP periodic timers to be serviced in the //! Ethernet interrupt. //! //! \return None. // //***************************************************************************** #if NO_SYS void lwIPTimer(uint32_t ui32TimeMS) { // // Increment the lwIP Ethernet timer. // g_ui32LocalTimer += ui32TimeMS; // // Generate an Ethernet interrupt. This will perform the actual work // of checking the lwIP timers and taking the appropriate actions. This is // needed since lwIP is not re-entrant, and this allows all lwIP calls to // be placed inside the Ethernet interrupt handler ensuring that all calls // into lwIP are coming from the same context, preventing any reentrancy // issues. Putting all the lwIP calls in the Ethernet interrupt handler // avoids the use of mutexes to avoid re-entering lwIP. // HWREG(NVIC_SW_TRIG) |= INT_EMAC0 - 16; } #endif //***************************************************************************** // //! Handles Ethernet interrupts for the lwIP TCP/IP stack. //! //! This function handles Ethernet interrupts for the lwIP TCP/IP stack. At //! the lowest level, all receive packets are placed into a packet queue for //! processing at a higher level. Also, the transmit packet queue is checked //! and packets are drained and transmitted through the Ethernet MAC as needed. //! If the system is configured without an RTOS, additional processing is //! performed at the interrupt level. The packet queues are processed by the //! lwIP TCP/IP code, and lwIP periodic timers are serviced (as needed). //! //! \return None. // //***************************************************************************** void lwIPEthernetIntHandler(void) { uint32_t ui32Status; uint32_t ui32TimerStatus; #if !NO_SYS portBASE_TYPE xWake; #endif // // Read and Clear the interrupt. // ui32Status = EMACIntStatus(EMAC0_BASE, true); #if EEE_SUPPORT if(ui32Status & EMAC_INT_LPI) { EMACLPIStatus(EMAC0_BASE); } #endif // // If the PMT mode exit status bit is set then enable the MAC transmit // and receive paths, read the PMT status to clear the interrupt and // clear the interrupt flag. // if(ui32Status & EMAC_INT_POWER_MGMNT) { MAP_EMACTxEnable(EMAC0_BASE); MAP_EMACRxEnable(EMAC0_BASE); EMACPowerManagementStatusGet(EMAC0_BASE); ui32Status &= ~(EMAC_INT_POWER_MGMNT); } // // If the interrupt really came from the Ethernet and not our // timer, clear it. // if(ui32Status) { MAP_EMACIntClear(EMAC0_BASE, ui32Status); } // // Check to see whether a hardware timer interrupt has been reported. // if(ui32Status & EMAC_INT_TIMESTAMP) { // // Yes - read and clear the timestamp interrupt status. // ui32TimerStatus = EMACTimestampIntStatus(EMAC0_BASE); // // If a timer interrupt handler has been registered, call it. // if(g_pfnTimerHandler) { g_pfnTimerHandler(EMAC0_BASE, ui32TimerStatus); } } // // The handling of the interrupt is different based on the use of a RTOS. // #if NO_SYS // // No RTOS is being used. If a transmit/receive interrupt was active, // run the low-level interrupt handler. // if(ui32Status) { tivaif_interrupt(&g_sNetIF, ui32Status); } // // Service the lwIP timers. // lwIPServiceTimers(); #else // // A RTOS is being used. Signal the Ethernet interrupt task. // xQueueSendFromISR(g_pInterrupt, (void *)&ui32Status, &xWake); // // Disable the Ethernet interrupts. Since the interrupts have not been // handled, they are not asserted. Once they are handled by the Ethernet // interrupt task, it will re-enable the interrupts. // MAP_EMACIntDisable(EMAC0_BASE, (EMAC_INT_RECEIVE | EMAC_INT_TRANSMIT | EMAC_INT_TX_STOPPED | EMAC_INT_RX_NO_BUFFER | EMAC_INT_RX_STOPPED | EMAC_INT_PHY)); // // Potentially task switch as a result of the above queue write. // #if RTOS_FREERTOS if(xWake == pdTRUE) { portYIELD_FROM_ISR(true); } #endif #endif } //***************************************************************************** // //! Returns the IP address for this interface. //! //! This function will read and return the currently assigned IP address for //! the Stellaris Ethernet interface. //! //! \return Returns the assigned IP address for this interface. // //***************************************************************************** uint32_t lwIPLocalIPAddrGet(void) { #if LWIP_AUTOIP || LWIP_DHCP if(g_bLinkActive) { return((uint32_t)g_sNetIF.ip_addr.addr); } else { return(0xffffffff); } #else return((uint32_t)g_sNetIF.ip_addr.addr); #endif } //***************************************************************************** // //! Returns the network mask for this interface. //! //! This function will read and return the currently assigned network mask for //! the Stellaris Ethernet interface. //! //! \return the assigned network mask for this interface. // //***************************************************************************** uint32_t lwIPLocalNetMaskGet(void) { return((uint32_t)g_sNetIF.netmask.addr); } //***************************************************************************** // //! Returns the gateway address for this interface. //! //! This function will read and return the currently assigned gateway address //! for the Stellaris Ethernet interface. //! //! \return the assigned gateway address for this interface. // //***************************************************************************** uint32_t lwIPLocalGWAddrGet(void) { return((uint32_t)g_sNetIF.gw.addr); } //***************************************************************************** // //! Returns the local MAC/HW address for this interface. //! //! \param pui8MAC is a pointer to an array of bytes used to store the MAC //! address. //! //! This function will read the currently assigned MAC address into the array //! passed in \e pui8MAC. //! //! \return None. // //***************************************************************************** void lwIPLocalMACGet(uint8_t *pui8MAC) { MAP_EMACAddrGet(EMAC0_BASE, 0, pui8MAC); } //***************************************************************************** // // Completes the network configuration change. This is directly called when // not using a RTOS and provided as a callback to the TCP/IP thread when using // a RTOS. // //***************************************************************************** static void lwIPPrivateNetworkConfigChange(void *pvArg) { uint32_t ui32IPMode; ip_addr_t ip_addr; ip_addr_t net_mask; ip_addr_t gw_addr; // // Get the new address mode. // ui32IPMode = (uint32_t)pvArg; // // Setup the network address values. // if(ui32IPMode == IPADDR_USE_STATIC) { ip_addr.addr = htonl(g_ui32IPAddr); net_mask.addr = htonl(g_ui32NetMask); gw_addr.addr = htonl(g_ui32GWAddr); } #if LWIP_DHCP || LWIP_AUTOIP else { ip_addr.addr = 0; net_mask.addr = 0; gw_addr.addr = 0; } #endif // // Switch on the current IP Address Aquisition mode. // switch(g_ui32IPMode) { // // Static IP // case IPADDR_USE_STATIC: { // // Set the new address parameters. This will change the address // configuration in lwIP, and if necessary, will reset any links // that are active. This is valid for all three modes. // netif_set_addr(&g_sNetIF, &ip_addr, &net_mask, &gw_addr); // // If we are going to DHCP mode, then start the DHCP server now. // #if LWIP_DHCP if((ui32IPMode == IPADDR_USE_DHCP) && g_bLinkActive) { dhcp_start(&g_sNetIF); } #endif // // If we are going to AutoIP mode, then start the AutoIP process // now. // #if LWIP_AUTOIP if((ui32IPMode == IPADDR_USE_AUTOIP) && g_bLinkActive) { autoip_start(&g_sNetIF); } #endif // // And we're done. // break; } // // DHCP (with AutoIP fallback). // #if LWIP_DHCP case IPADDR_USE_DHCP: { // // If we are going to static IP addressing, then disable DHCP and // force the new static IP address. // if(ui32IPMode == IPADDR_USE_STATIC) { dhcp_stop(&g_sNetIF); netif_set_addr(&g_sNetIF, &ip_addr, &net_mask, &gw_addr); } // // If we are going to AUTO IP addressing, then disable DHCP, set // the default addresses, and start AutoIP. // #if LWIP_AUTOIP else if(ui32IPMode == IPADDR_USE_AUTOIP) { dhcp_stop(&g_sNetIF); netif_set_addr(&g_sNetIF, &ip_addr, &net_mask, &gw_addr); if(g_bLinkActive) { autoip_start(&g_sNetIF); } } #endif break; } #endif // // AUTOIP // #if LWIP_AUTOIP case IPADDR_USE_AUTOIP: { // // If we are going to static IP addressing, then disable AutoIP and // force the new static IP address. // if(ui32IPMode == IPADDR_USE_STATIC) { autoip_stop(&g_sNetIF); netif_set_addr(&g_sNetIF, &ip_addr, &net_mask, &gw_addr); } // // If we are going to DHCP addressing, then disable AutoIP, set the // default addresses, and start dhcp. // #if LWIP_DHCP else if(ui32IPMode == IPADDR_USE_DHCP) { autoip_stop(&g_sNetIF); netif_set_addr(&g_sNetIF, &ip_addr, &net_mask, &gw_addr); if(g_bLinkActive) { dhcp_start(&g_sNetIF); } } #endif break; } #endif } // // Bring the interface up. // netif_set_up(&g_sNetIF); // // Save the new mode. // g_ui32IPMode = ui32IPMode; } //***************************************************************************** // //! Change the configuration of the lwIP network interface. //! //! \param ui32IPAddr is the new IP address to be used (static). //! \param ui32NetMask is the new network mask to be used (static). //! \param ui32GWAddr is the new Gateway address to be used (static). //! \param ui32IPMode is the IP Address Mode. \b IPADDR_USE_STATIC 0 will //! force static IP addressing to be used, \b IPADDR_USE_DHCP will force DHCP //! with fallback to Link Local (Auto IP), while \b IPADDR_USE_AUTOIP will //! force Link Local only. //! //! This function will evaluate the new configuration data. If necessary, the //! interface will be brought down, reconfigured, and then brought back up //! with the new configuration. //! //! \return None. // //***************************************************************************** void lwIPNetworkConfigChange(uint32_t ui32IPAddr, uint32_t ui32NetMask, uint32_t ui32GWAddr, uint32_t ui32IPMode) { // // Check the parameters. // #if LWIP_DHCP && LWIP_AUTOIP ASSERT((ui32IPMode == IPADDR_USE_STATIC) || (ui32IPMode == IPADDR_USE_DHCP) || (ui32IPMode == IPADDR_USE_AUTOIP)); #elif LWIP_DHCP ASSERT((ui32IPMode == IPADDR_USE_STATIC) || (ui32IPMode == IPADDR_USE_DHCP)); #elif LWIP_AUTOIP ASSERT((ui32IPMode == IPADDR_USE_STATIC) || (ui32IPMode == IPADDR_USE_AUTOIP)); #else ASSERT(ui32IPMode == IPADDR_USE_STATIC); #endif // // Save the network configuration for later use by the private network // configuration change. // g_ui32IPAddr = ui32IPAddr; g_ui32NetMask = ui32NetMask; g_ui32GWAddr = ui32GWAddr; // // Complete the network configuration change. The remainder is done // immediately if not using a RTOS and it is deferred to the TCP/IP // thread's context if using a RTOS. // #if NO_SYS lwIPPrivateNetworkConfigChange((void *)ui32IPMode); #else tcpip_callback(lwIPPrivateNetworkConfigChange, (void *)ui32IPMode); #endif } void lwIPLLDPSend(void) { //lldp_raw(&g_sNetIF); } //*****************************************************************************// // Close the Doxygen group. //! @} // //*****************************************************************************