Dear LWIP Community,
I am Timothy, currently working on a project involving LWIP. I recently updated
the LWIP headers from version 1.4.1 to 2.2.0 and have encountered multiple
errors that I'm struggling to resolve. These errors are primarily in lwiplib.c
and related files, and I would greatly appreciate any guidance or advice you
can provide.
Here are the details of the issues I'm facing:
-
Error #137 in lwiplib.c (Path: /NetworkModule/utils):
- Struct "ip_addr" has no field "addr" at lines 739, 740, 741, 745, 746, 747,
1174, 1198, 1245, 1246, and 1247.
-
Error #137 in .ccsproject (External Location:
C:\ti5\third_party\lwip-1.4.1\src\core):
- Struct "udp_pcb" has no field "lwip_recv" at line 404 (File: udp.c).
- Struct "tcp_pcb" has no field "lwip_recv" at lines 501, 541, 1568, and 1581
(File: tcp.c).
- Struct "tcp_pcb_listen" has no field "lwip_accept" at lines 956 and 667
(File: tcp_in.c).
-
Error #56-D and #29 in .ccsproject (External Location:
C:\ti5\third_party\lwip-1.4.1\src\core):
- Too many arguments in invocation of macro "recv" at line 404 (File: udp.c).
- Expected an expression at line 1428 (File: tcp.c).
- Too few arguments in invocation of macro "poll" at line 1428 (File: tcp.c).
I have attempted to troubleshoot these issues by reviewing the documentation
and searching for similar problems faced by others, but I haven't found a clear
solution yet.
Any help or pointers on how to address these errors would be immensely helpful.
I am especially interested in understanding if these are known issues when
upgrading from LWIP 1.4.1 to 2.2.0, and if there are any specific changes or
considerations I should be aware of.
Thank you in advance for your time and assistance. Your expertise and advice
are invaluable to me and others facing similar challenges.
Best,
Timothy
//*****************************************************************************
//
// lwiplib.h - Prototypes for the lwIP library wrapper API.
//
// Copyright (c) 2008-2020 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.2.0.295 of the Tiva Utility Library.
//
//*****************************************************************************
#ifndef __LWIPLIB_H__
#define __LWIPLIB_H__
//*****************************************************************************
//
// If building with a C++ compiler, make all of the definitions in this header
// have a C binding.
//
//*****************************************************************************
#ifdef __cplusplus
extern "C"
{
#endif
//*****************************************************************************
//
// lwIP Options
//
//*****************************************************************************
#include "lwip/opt.h"
//*****************************************************************************
//
// Ensure that AUTOIP COOP option is configured correctly.
//
//*****************************************************************************
#undef LWIP_DHCP_AUTOIP_COOP
#define LWIP_DHCP_AUTOIP_COOP ((LWIP_DHCP) && (LWIP_AUTOIP))
//*****************************************************************************
//
// lwIP API Header Files
//
//*****************************************************************************
#include <stdint.h>
#include "lwip/api.h"
#include "lwip/netifapi.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
#include "lwip/tcpip.h"
#include "lwip/sockets.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
#include "lwip/def.h"
//#include "lwip/tcp_impl.h"
#include "lwip/timers.h"
#include "lwip/priv/tcp_priv.h"
//#include "lwip/timeouts.h"
//*****************************************************************************
//
// IP Address Acquisition Modes
//
//*****************************************************************************
#define IPADDR_USE_STATIC 0
#define IPADDR_USE_DHCP 1
#define IPADDR_USE_AUTOIP 2
//*****************************************************************************
//
// Hardware timer interrupt callback function type (available only when running
// on TM4C parts). This function is called in interrupt context whenever the
// Ethernet MAC reports an interrupt from the IEEE-1588 timestamping
// timer. The first parameter is the base address of the MAC and the second
// is the interrupt status as reported via EthMACTimestampIntStatus.
//
//*****************************************************************************
typedef void (* tHardwareTimerHandler)(uint32_t ui32Base,
uint32_t ui32IntStatus);
//*****************************************************************************
//
// lwIP Abstraction Layer API
//
//*****************************************************************************
extern void lwIPInit(uint32_t ui32SysClkHz, const uint8_t *pui8Mac,
uint32_t ui32IPAddr, uint32_t ui32NetMask,
uint32_t ui32GWAddr, uint32_t ui32IPMode);
extern void lwIPTimerCallbackRegister(tHardwareTimerHandler pfnTimerFunc);
extern void lwIPTimer(uint32_t ui32TimeMS);
extern void lwIPEthernetIntHandler(void);
extern uint32_t lwIPLocalIPAddrGet(void);
extern uint32_t lwIPLocalNetMaskGet(void);
extern uint32_t lwIPLocalGWAddrGet(void);
extern void lwIPLocalMACGet(uint8_t *pui8Mac);
extern void lwIPNetworkConfigChange(uint32_t ui32IPAddr, uint32_t ui32NetMask,
uint32_t ui32GWAddr, uint32_t ui32IPMode);
extern uint32_t lwIPAcceptUDPPort(uint16_t ui16Port);
//*****************************************************************************
//
// Mark the end of the C bindings section for C++ compilers.
//
//*****************************************************************************
#ifdef __cplusplus
}
#endif
#endif // __LWIPLIB_H__
//*****************************************************************************
//
// lwiplib.c - lwIP TCP/IP Library Abstraction Layer.
//
// Copyright (c) 2008-2020 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.2.0.295 of the Tiva Utility Library.
//
//*****************************************************************************
//*****************************************************************************
//
// Ensure that the lwIP compile time options are included first.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#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-1.4.1/src/api/api_lib.c"
#include "third_party/lwip-1.4.1/src/api/api_msg.c"
#include "third_party/lwip-1.4.1/src/api/err.c"
#include "third_party/lwip-1.4.1/src/api/netbuf.c"
#include "third_party/lwip-1.4.1/src/api/netdb.c"
#include "third_party/lwip-1.4.1/src/api/netifapi.c"
#include "third_party/lwip-1.4.1/src/api/sockets.c"
#include "third_party/lwip-1.4.1/src/api/tcpip.c"
//*****************************************************************************
//
// Include the core lwIP TCP/IP stack code.
//
//*****************************************************************************
#include "third_party/lwip-1.4.1/src/core/def.c"
#include "third_party/lwip-1.4.1/src/core/dhcp.c"
#include "third_party/lwip-1.4.1/src/core/dns.c"
#include "third_party/lwip-1.4.1/src/core/init.c"
#include "third_party/lwip-1.4.1/src/core/mem.c"
#include "third_party/lwip-1.4.1/src/core/memp.c"
#include "third_party/lwip-1.4.1/src/core/netif.c"
#include "third_party/lwip-1.4.1/src/core/pbuf.c"
#include "third_party/lwip-1.4.1/src/core/raw.c"
#include "third_party/lwip-1.4.1/src/core/stats.c"
#include "third_party/lwip-1.4.1/src/core/sys.c"
#include "third_party/lwip-1.4.1/src/core/tcp.c"
#include "third_party/lwip-1.4.1/src/core/tcp_in.c"
#include "third_party/lwip-1.4.1/src/core/tcp_out.c"
#include "third_party/lwip-1.4.1/src/core/timers.c"
#include "third_party/lwip-1.4.1/src/core/timeouts.c"
#include "third_party/lwip-1.4.1/src/core/udp.c"
//*****************************************************************************
//
// Include the IPV4 code.
//
//*****************************************************************************
#include "third_party/lwip-1.4.1/src/core/ipv4/autoip.c"
#include "third_party/lwip-1.4.1/src/core/ipv4/icmp.c"
#include "third_party/lwip-1.4.1/src/core/ipv4/igmp.c"
#include "third_party/lwip-1.4.1/src/core/ipv4/inet.c"
#include "third_party/lwip-1.4.1/src/core/ipv4/inet_chksum.c"
#include "third_party/lwip-1.4.1/src/core/ipv4/ip4.c"
#include "third_party/lwip-1.4.1/src/core/ipv4/ip4_addr.c"
#include "third_party/lwip-1.4.1/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-1.4.1/src/core/ipv6/icmp6.c"
#include "third_party/lwip-1.4.1/src/core/ipv6/inet6.c"
#include "third_party/lwip-1.4.1/src/core/ipv6/ip6.c"
#include "third_party/lwip-1.4.1/src/core/ipv6/ip6_addr.c"
#endif
//*****************************************************************************
//
// Include the lwIP SNMP code.
//
//*****************************************************************************
#include "third_party/lwip-1.4.1/src/core/snmp/asn1_dec.c"
#include "third_party/lwip-1.4.1/src/core/snmp/asn1_enc.c"
#include "third_party/lwip-1.4.1/src/core/snmp/mib2.c"
#include "third_party/lwip-1.4.1/src/core/snmp/mib_structs.c"
#include "third_party/lwip-1.4.1/src/core/snmp/msg_in.c"
#include "third_party/lwip-1.4.1/src/core/snmp/msg_out.c"
//*****************************************************************************
//
// Include the network interface code.
//
//*****************************************************************************
#include "third_party/lwip-1.4.1/src/netif/etharp.c"
//*****************************************************************************
//
// Include the network interface PPP code.
//
//*****************************************************************************
#include "third_party/lwip-1.4.1/src/netif/ppp/auth.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/chap.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/chpms.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/fsm.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/ipcp.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/lcp.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/magic.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/md5.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/pap.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/ppp.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/ppp_oe.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/randm.c"
#include "third_party/lwip-1.4.1/src/netif/ppp/vj.c"
//*****************************************************************************
//
// Include Tiva-specific lwIP interface/porting layer code.
//
//*****************************************************************************
#include "third_party/lwip-1.4.1/ports/tiva-tm4c129/perf.c"
#include "third_party/lwip-1.4.1/ports/tiva-tm4c129/sys_arch.c"
#include "third_party/lwip-1.4.1/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;
struct ip_addr ip_addr;
struct ip_addr net_mask;
struct ip_addr 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)
{
struct ip_addr ip_addr;
struct ip_addr net_mask;
struct ip_addr 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);
//
// 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_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;
struct ip_addr ip_addr;
struct ip_addr net_mask;
struct ip_addr 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
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users