Chapter 168. lwIP Direct Ethernet Device Driver
Table of Contents
168.1. Introduction
This chapter provides a simple description of the basic requirements for a low-level, hardware specific, lwIP-direct ethernet driver.
Using a lwIP-direct driver provides benefits in performance and smaller code- and memory-footprints. It also allows for the potential for zero-copy UDP support and reduced (single) copy TCP support depending on the hardware available. The main disadvantage over the standard ethernet driver world is the lack of RedBoot network debugging support.
The high-level driver implemented by this package (which is only code, without state of its own) is used to provide a common interface for lwIP to either a lwIP-specific direct driver (as described in this chapter), or via a wrapper interface to a standard generic ethernet driver (covered by Section 167.1, “Generic Ethernet API”).
Unlike the generic ethernet (standard) device driver support the
lwIP device driver interface uses a fixed namespace between the
lwIP and driver layers. Normally only a single driver instance
exists for a lwIP configured world, so the use of a fixed namespace
is, in reality, not an issue since lwIP is designed for
lightweight, low resource, deeply-embedded systems. If a target
platform really does provide more than one distinct ethernet
hardware implementation, requiring completely different hardware
drivers, then a wrapper layer conforming to the
“direct” driver interface is provided when the
option CYGFUN_IO_ETH_DRIVERS_LWIP_DRIVER_DIRECT_MULTI
is configured. This implements a per-driver descriptor interface
between the individual low-level hardware interfaces for the
platform and this common Ethernet I/O package.
Normally a direct driver implementation will also provide a driver
specific header file which is referenced from the lwIP CDL
option CYGBLD_LWIP_HW_DRIVER_OVERRIDE_HEADER
. The
CDL covering the direct driver package should explicitly set the
value to the required header file name. Similarly when support is
configured for multiple direct drivers, the CDL
option CYGBLD_LWIP_VARIANT_OVERRIDE_HEADER
can
be used to reference a header providing any needed
platform/variant/driver specific features.
These header files can be used to provide access to prototypes and
manifests needed to support specific lwIP features as required. For
example, if the hardware driver uses DMA, and requires timely
support for re-using PBUFs once lwIP has finished processing them,
then the ECOS_LWIP_PBUF_POOL_FREE_HOOK
manifest can be defined to reference a callback function
(See DRV_HDWR
_pbuf_pool_free_hook()).
The following sections give an overview of the small set of
functions that the driver needs to provide to be usable by this
package. When the multiple direct driver support is being used then
these named functions are provided by this
common CYGPKG_IO_ETH_DRIVERS
I/O Ethernet
package, with a per-driver descriptor structure used to reference
the specific driver implementations
(See Section 168.3, “Multiple direct drivers”).
168.2. API reference
- cyg_lwip_eth_ecos_init() — Initialize the hardware driver
- cyg_lwip_eth_low_level_output() — Transmit a packet
- cyg_lwip_eth_run_deliveries() — Packet buffer house-keeping
- cyg_lwip_eth_ioctl() — Control interface
DRV_HDWR
_pbuf_pool_free_hook() — PBUF free hook callback
The following function definitions document the namespace used by the eCos lwIP TCP/IP stack to interact with hardware drivers.
168.3. Multiple direct drivers
When support for multiple direct drivers is configured then a driver instance is contained within a cyg_lwip_eth_t structure:
typedef struct cyg_lwip_eth { const char *name; // NUL terminated ASCII human-readable name void (*init)(struct cyg_lwip_eth *drvdesc); void (*run_deliveries)(void *instance); err_t (*ll_output)(struct netif *netif,struct pbuf *p); int (*pbuf_free_hook)(void *instance,struct pbuf *p); void (*phy_event)(struct netif *netif); int (*ioctl)(struct netif *netif,unsigned long key,void *data,int data_length); void *instance; cyg_uint32 flags; } CYG_HAL_TABLE_TYPE cyg_lwip_eth_t;
This CYGPKG_IO_ETH_DRIVERS
package will implement
the wrapper namespace to support lwIP, calling the relevant individual
device driver registered functions as required.
You create an instance of cyg_lwip_eth_t using
the CYG_LWIP_DRIVER
macro, which sets up the
structure. Using this macro ensures that if the internal design
changes then existing source will fail to compile until updated to
reflect the changed functionality. This is better than having
definitions within the low-level drivers themselves, with the
possibility of them building successfully but then failing at
run-time.
The individual hardware drivers are initialised automatically via the
wrapper provided cyg_lwip_eth_ecos_init()
function, which iterates over the __LWIPDEVTAB__
vector containing the driver instance descriptors as required.
Note | |
---|---|
When lwIP direct drivers are written to
support |
The function pointers referenced from the cyg_lwip_eth_t
descriptor closely match the raw namespace, with the exception that
initialisation is passed the cyg_lwip_eth_t driver
descriptor pointer, and the run_deliveries
and pbuf_free_hook
implementations are passed the
private instance
pointer. This ensures that the
individual driver implementation can access the necessary state as
would be the case for a single driver configuration.
Note | |
---|---|
For the
This “do you want this |
168.4. lwIP MANUAL
initialisation
Normally lwIP will default to DHCP
for
network interface address acquisition, but alternative methods
can be configured (AUTOIP
,
STATIC
or MANUAL
). The
relevant configuration specific interface initialisation code
is actually performed in this common IO Ethernet package by
the cyg_lwip_eth_drv_init_netif()
function. When configured to use fixed
STATIC
addresses those are held in the eCos
configuration file for the build. The
MANUAL
option, however, allows for the
application code to manually supply address information and
perform the interface initialisation.
When MANUAL
address configuration is
selected for an lwIP interface then an explicitly named
function must be supplied by
the application run-time, with the prototype:
char cyg_lwip_eth_init_manual(struct netif *netif, char inum, unsigned char *enaddr);
The netif
parameter references the
underlying lwIP network interface descriptor, with the
parameter inum
being the logical
(indexed from 0) interface number. The
enaddr
references the IEEE MAC address
for the interface.
It is expected that the application supplied routine will set the address configuration et al., before adding the interface, based on some per-device stored/calculated values.
It is expected that if manual application interface initialisation is being used that the developer has a reasonable understanding of lwIP and its internal requirements, and is au fait with the eCos network source base.
The following is a simple example implementation of the basic
operations that need to be performed by the application to
provide MANUAL
interface support:
char cyg_lwip_eth_init_manual(struct netif *netif, char inum, unsigned char *enaddr) { ip4_addr_t ipaddr; ip4_addr_t netmask; ip4_addr_t gw; application_code_to_fill_addresses_for_interface_number(inum, &ipaddr, &netmask, &gw); char ok = (NULL != netif_add((netif), &ipaddr, &netmask, &gw, (netif)->state, cyg_lwip_eth_netif_init, ethernet_input)); if (ok) { #if LWIP_CHECKSUM_CTRL_PER_NETIF // per-interface checksum offload control // Set following as desired for the application configuration, or the // target H/W driver feature support: (netif)->chksum_flags = NETIF_CHECKSUM_DISABLE_ALL; #endif // LWIP_CHECKSUM_CTRL_PER_NETIF netif_set_up(netif); } return ok; }
2024-03-18 | Open Publication License |