CYGPKG_DEVS_ETH_DWC_GMAC — eCos Support for Synopsys DesignWare Ethernet GMAC Devices


The CYGPKG_DEVS_ETH_DWC_GMAC package only implements the standard eCos driver interface. When used with the lwIP TCP/IP network stack it provides implementations of the io/eth extended filtering options, and also provides support for automatically throttling RX frame processing to limit the system overhead when used on a saturated network. See Section 167.2.4, “Control function”.

Configuration Options

This Ethernet package should be loaded automatically when selecting a target containing a DWC GMAC controller, and it should never be necessary to load it explicitly. If the application does not actually require Ethernet functionality then the package is inactive and the final executable will not suffer any overheads from unused functionality. This is determined by the presence of the generic Ethernet I/O package CYGPKG_IO_ETH_DRIVERS. Typically the choice of eCos template causes the right thing to happen. For example the default template does not include any TCP/IP stack so CYGPKG_IO_ETH_DRIVERS is not included, but the net, redboot and lwip_eth templates do include a TCP/IP stack so will specify that package and hence enable the Ethernet driver.

All eCos network devices need a unique name. By default the first Ethernet device is assigned the name eth0. The platform specific package providing the DWC GMAC network device descriptor also normally provides the interface name in its struct eth_drv_sc structure instance.

The hardware requires that incoming Ethernet frames are received into one of a small number of buffers, arranged in a ring. Once a frame has been received and its size is known the driver will pass it up to higher-level code for further processing. The number of these buffers is provided in the platform specific package providing the dwc_gmac_priv structure instance.

In the standard Ethernet driver, each receive buffer requires 1528 bytes of memory. The package header file if_dwc_gmac.h defines the manifest DWC_GMAC_RX_BUFF_SIZE which is used as the size of the receive descriptor ring buffers. A smaller number of buffers increases the probability that incoming Ethernet frames have to be discarded. TCP/IP stacks are designed to cope with the occasional lost packet, but if too many frames are discarded then this will greatly affect performance. A key issue here is that passing the incoming frames up to higher-level code happens at thread level and hence the system behaviour is defined in large part by the priority of various threads running in the TCP/IP stack. If application code has high-priority threads that take up much of the available CPU time and the TCP/IP stack gets little chance to run then there will be little opportunity to pass received frames up the stack. Similarly the priority of the TCP/IP network stack threads may affect the CPU bandwidth available for other lower-priority application threads in a saturated network. Balancing out the various thread priorities and the number of receive buffers is the responsibility of the application developer.

By default the Ethernet driver will raise interrupts using a low priority level. The exact value will depend on the processor being used, and is held in the vector_pri field supplied by the platform specific package dwc_gmac_common structure definition. The driver does very little at interrupt level, instead the real work is done via threads inside the TCP/IP stack. Hence the interrupt priority has little or no effect on the system's behaviour. The RX interrupts are disabled whilst RX processing by the thread level TCP/IP stack is pending; and only re-enabled once the thread level code has processed the RX ring buffer.

RX throttling


By default the driver uses interrupt driven RX frame handling, but allows for manual control of whether interrupt or polled RX operation is used (via the ETH_DRV_OPTIONS interface). If CYGIMP_DEVS_ETH_DWC_GMAC_NET_RX_AUTO is enabled then the driver will also support automatic switching between modes. Enabling this feature does not affect the run-time operation of the driver by itself. It is the responsibility of the application to manually select ETH_DRV_OPTION_RX_AUTO mode via the ETH_DRV_OPTIONS control API if required.

// Simplistic example of setting driver AUTO-throttle option

struct netif *p_nif = netif_default;
struct eth_drv_sc *p_sc = (struct eth_drv_sc *)(netif->state);

if (p_sc->funs->control) {
    cyg_uint32 mode = ETH_DRV_OPTION_RX_AUTO;
    struct eth_drv_options drvopt;

    drvopt.u.mand = ~ETH_DRV_OPTION_RX_MODE_MASK;
    drvopt.eor = mode;

    int res = (p_sc->funs->control)(p_sc,ETH_DRV_OPTIONS,&drvopt,sizeof(drvopt));
    // Check mode is configured as requested:
    if (0 == res) {
        if (mode == (drvopt.u.val & ETH_DRV_OPTION_RX_MODE_MASK)) {
            success = true;
        } else {
            res = -1;

When AUTO-throttling is enabled other configuration options are made available to control the behaviour of the AUTO-throttle support.

This option configures the number of samples used for the running averages. A smaller value will be coarser, but result in quicker transitions on large deltas. A greater number of samples value will result in a smoother transition over a longer period of time.
This option enables the AUTO support tracking of the RX load when in INT (interrupt) state. Since this has an impact on the performance of the RX path the feature can be disabled by deselecting this option. When this option is disabled the INT-to-POLL transition will only occur on network buffer exhaustion. When enabled the code will also track the active RX load when in AUTO-INT mode and switch to polled mode when the CYGNUM_DEVS_ETH_DWC_GMAC_WM_INT2POLL_PPMS configured watermark is exceeded.
When the AUTO-throttle feature is enabled this option specifies the load threshold (packets-per-millisecond) over which we will switch from INT mode into POLL mode. This watermark is only used when AUTO mode is enabled, and AUTO-INT state is active, and triggers a switch to POLL mode When the load average rises above this threshold. It should be tuned appropriately.
When the AUTO-throttle feature is enabled this option specifies the load threshold (packets-per-millisecond) under which we switch from POLL mode back to INT mode when the load average drops below this threshold. It should be tuned appropriately.

When the driver is configured for RX polled operation, this value is the number of milliseconds used between polled receiver calls.


Care should be taken when setting a short poll period; since on networks where the driver will accepts large numbers of RX packets, and a large amount of packet buffer space is allocated allowing the system to hold a large number of pending RX packets, then depending on the relative priority of the network stack control thread other application threads can be denied bandwidth.

MAC Address

All Ethernet devices should have a unique address which has to be provided from somewhere. There are a number of possibilities:

  1. The platform supplied driver instance dwc_gmac_priv structure provides the enaddr field which can be pre-initialised by the platform specific world. The MAC address supplied in the referenced structure is used if neither of the run-time options detailed below are provided. For example, the cyclone5_sx platform provides the CDL variable CYGDAT_DEVS_ETH_CYCLONE5_SX_MACADDR_ETH0 which is used to initialise the descriptor enaddr field for the eth0 instance.
  2. The platform HAL can provide the address. For example the target board may have a small serial EPROM or similar which is initialized during board manufacture. The platform HAL can read the serial EPROM during system startup and provide the information to the Ethernet driver. If this is the case then the platform HAL should provide a macro CYGHWR_DEVS_ETH_DWC_GMAC_GET_ESA in the exported header cyg/hal/plf_arch.h.
  3. If the target hardware boots via RedBoot and uses a block of flash to hold configuration variables then one of these variables will be the MAC address. This is normally indicated by CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT being defined, in which case the driver will attempt to access the MAC address via the CYGNUM_CALL_IF_FLASH_CFG_GET interface to read the CYGNUM_FLASH_CFG_TYPE_CONFIG_ESA option. The MAC address to use can be manipulated at the RedBoot prompt using the fconfig command, thus giving each board a unique address. An eCos application containing the Ethernet driver will automatically pick up this address.

When designing a new target board it is recommended that the board comes with a unique network address supported by the platform HAL, rather than relying on users to change the address. The latter approach can be error-prone and will lead to failures that are difficult to track down.

Platform-specific PHY

The Ethernet GMAC hardware relies on an external media independent interface (MII), also known as a PHY chip. This separate chip handles the low-level details of Ethernet communication, for example negotiating a link speed with the hub. In most scenarios the PHY chip simply does the right thing and needs no support from the Ethernet driver. If there are special requirements, for example if the board has to be hardwired to communicate at 10Mbps rather than autonegotiate the link speed, then usually this is handled by fixed logic levels on some of the PHY pins or by using jumpers.

The driver supports asynchronous reporting of PHY events when the CDL option CYGSEM_DEVS_ETH_DWC_GMAC_PHY_EVENT is configured. Currently this event support is only available when using the lwIP TCP/IP networking stack.