Ethernet Sample Application

  1. This example show how to initialize µC/TCP-IP:

    1. Initialize Stack tasks and objects
    2. Initialize an Ethernet Interface
    3. Start that Ethernet Interface
    4. Configure IP addresses of that Interface

This example is based on template files so some modifications will be required, insert the appropriate project/board specific code to perform the stated actions. Note that the file init_ether.c, located in the folder $/Micrium/Software/uC-TCPIP/Examples/Init, contains this sample application:

Listing - AppInit_TCPIP()
#include  <cpu_core.h>
#include  <lib_mem.h>
#include  <Source/net.h>
#include  <Source/net_ascii.h>
#include  <IF/net_if.h>
#include  <IF/net_if_ether.h>
#ifdef NET_IPv4_MODULE_EN
#include  <IP/IPv4/net_ipv4.h>
#endif
#ifdef NET_IPv6_MODULE_EN
#include  <IP/IPv6/net_ipv6.h>
#endif
#include  <Cfg/Template/net_dev_cfg.h>                      /* See Note #1. */
#include  <Dev/Ether/Template/net_dev_ether_template_dma.h> /* See Note #2. */
#include  <Dev/Ether/PHY/Generic/net_phy.h>                 /* See Note #3. */
#include  <BSP/Template/net_bsp_ether.h>                    /* See Note #4. */
 
 
CPU_BOOLEAN  AppInit_TCPIP (void)
{
    NET_IF_NBR      if_nbr;
    NET_ERR         err_net;
#ifdef NET_IPv4_MODULE_EN
    NET_IPv4_ADDR   addr_ipv4;
    NET_IPv4_ADDR   msk_ipv4;
    NET_IPv4_ADDR   gateway_ipv4;
#endif
#ifdef NET_IPv6_MODULE_EN
    CPU_BOOLEAN     cfg_result;
#if (NET_IPv6_CFG_ADDR_AUTO_CFG_EN == DEF_DISABLED)
    NET_FLAGS       ipv6_flags;
    NET_IPv6_ADDR   ipv6_addr;
#endif
#endif
                                                        /* ------- PREREQUISITES MODULE INIT -------- */
    CPU_Init();                                         /* See Note #5.                               */
    Mem_Init();
                                                        /* ------ INIT NETWORK TASKS & OBJECTS ------ */
    err_net = Net_Init(&NetRxTaskCfg,                   /* See Note #6.                               */
                       &NetTxDeallocTaskCfg,
                       &NetTmrTaskCfg);
    if (err_net != NET_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* --------- ADD ETHERNET INTERFACE --------- */
                                                        /* See Note #7.                               */
    if_nbr = NetIF_Add(&NetIF_API_Ether,                /* See Note #7b.                              */
                       &NetDev_API_TemplateEtherDMA,    /* Device driver API,    See Note #7c.        */
                       &NetDev_BSP_BoardDev_Nbr,        /* BSP API,              See Note #7d.        */
                       &NetDev_Cfg_Ether_1,             /* Device configuration, See Note #7e.        */
                       &NetPhy_API_Generic,             /* PHY driver API,       See Note #7f.        */
                       &NetPhy_Cfg_Ether_1,             /* PHY configuration,    See Note #7g.        */
                       &err_net);
    if (err_net != NET_IF_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* -------- START ETHERNET INTERFACE -------- */
    NetIF_Start(if_nbr, &err_net);                      /* See Note #8.                               */
    if (err_net != NET_IF_ERR_NONE) {
        return (DEF_FAIL);
    }
#ifdef NET_IPv4_MODULE_EN
                                                        /* ------- CONFIGURE IPV4 STATIC ADDR ------- */
                                                        /* See Note #9                                */
    NetASCII_Str_to_IP("10.10.10.64",                   /* Convert IPv4 string addr to 32 bits addr.  */
                       &addr_ipv4,
                       NET_IPv4_ADDR_SIZE,
                      &err_net);
    NetASCII_Str_to_IP("255.255.255.0",                 /* Convert IPv4 mask string to 32 bits addr.  */
                       &msk_ipv4,
                       NET_IPv4_ADDR_SIZE,
                      &err_net);
    NetASCII_Str_to_IP("10.10.10.1",                    /* Convert Gateway string to 32 bits addr.    */
                       &gateway_ipv4,
                       NET_IPv4_ADDR_SIZE,
                      &err_net);
    NetIPv4_CfgAddrAdd(if_nbr,                          /* Add a statically-configured IPv4 host ...  */
                       addr_ipv4,                       /* ... addr, subnet mask, & default      ...  */
                       msk_ipv4,                        /* ... gateway to the interface. See Note #10.*/
                       gateway_ipv4,
                      &err_net);
    if (err_net != NET_IPv4_ERR_NONE) {
        return (DEF_FAIL);
    }
#endif
#ifdef NET_IPv6_MODULE_EN
#if (NET_IPv6_CFG_ADDR_AUTO_CFG_EN == DEF_ENABLED)
                                                        /* ---- START IPV6 STATELESS AUTO-CONFI ----- */
                                                        /* See Note #12.                              */
    NetIPv6_AddrAutoCfgHookSet(if_nbr,                  /* Set hook to received Auto-Cfg result.      */
                              &App_AutoCfgResult,       /* TODO update pointer to hook defined in App.*/
                              &err_net);
    
                                                        /* See Note #13.                              */
    cfg_result = NetIPv6_AddrAutoCfgEn(if_nbr,          /* Enable and Start Auto-Config process.      */
                                       DEF_YES,
                                      &err_net);
    if (cfg_result == DEF_FAIL) {
        return (DEF_FAIL);
    }


  1. The device configuration template file should be copied to your application folder and modified to follow your requirements. Refer to the User's Manual for more information about how to configure your device.

    We recommend starting with a working configuration from an example project for your MCU. Micriµm might have some projects available only for internal usage, so if no working project are found online, please ask at support@micrium.com for a configuration file example.
  2. Most of the time Micriµm provides an Ethernet Network device driver which can be found under the following folder:

    $/Micrium/Software/uC-TCPIP/Dev/Ether/<Controller>/net_dev_<controller>.h


    If Micrium does not support your network device driver, you will have to write your own device driver starting from the Ethernet Device driver template. Before starting to write your own driver, make sure that the driver is not already available. Net_Init() is the Network Protocol stack initialization function. This function takes the three TCP-IP internal tasks configurations (defined in net_cfg.c) as argument.
  3. The PHY driver should be provided by Micriµm and located under the following folder:


    $/Micrium/Software/uC-TCPIP/Dev/Ether/PHY/<phy part number>/net_phy_<phy part number>.h



    Most of the time for MII, RMII or GMII PHY, the generic PHY works correctly. If your PHY is not available and the generic is not working you will have to write you own PHY driver. Normally for a single connector PHY, some minor changes to the generic driver are required.

  4. The board support package (BSP) template file should be copied to your application folder and modified for your specific board. Refer to the User's Manual for more information about how to write a BSP (Ethernet BSP Layer).

    However we recommend, starting with a working configuration from an example project for your MCU. Micriµm might have some projects available only for internal usage, so if no working project are found online, please ask at support@micrium.com for a BSP file example specific for your MCU.

  5.  Some prerequisite module initializations are required. The following modules must be initialized prior to starting the Network Protocol stacks initialization:

    1. uC/CPU

    2. uC/LIB Memory module
       
  6. Net_Init() is the Network Protocol stack's initialization function. It must only be called once and before any other Network functions.

    1. This function takes the three TCP-IP internal task configuration structures as arguments (such as priority, stack size, etc.). By default these configuration structures are defined in net_cfg.c :

       NetRxTaskCfg RX task configuration
      NetTxDeallocTaskCfg TX task configuration
      NetTmrTaskCfg Timer task configuration
    2. We recommend you configure the Network Protocol Stack task priorities & Network application (such as a Web server) task priorities as follows:

        NetTxDeallocTaskCfg                            (highest priority)
                    
      Network applications (HTTPs, FTP, DNS, etc.)
      NetTmrTaskCfg
      NetRxTaskCfg (lowest priority)


      We recommend that the uC/TCP-IP Timer task and network interface Receive task be lower priority than almost all other application tasks; but we recommend that the network interface Transmit De-allocation task be higher priority than all application tasks that use uC/TCP-IP network services.

      However, better performance can be observed when the Network applications are set with the lowest priority. Some experimentation could be required to identify the best task priority configuration.

  7. NetIF_Add() is a network interface function responsible for initializing a Network Device driver.

    1. NetIF_Add() returns the interface index number. The interface index number should start at '1', since the interface '0' is reserved for the loopback interface. The interface index number must be used when you want to access the interface using any Network interface API.

    2. The first parameter is the address of the Network interface API. These API are provided by Micriµm and are defined in file 'net_if_<type>.h'. It should be either:

       NetIF_API_Ether     Ethernet interface
      NetIF_API_WiFi      Wireless interface
    3. The second parameter is the address of the device API function. The API should be defined in the Device driver header:

        $/uC-TCPIP/Dev/<if_type>/<controller>/net_dev_<controller>.h
    4.  The third parameter is the address of the device BSP data structure. See 'Note #4' for more details.

    5.  The fourth parameter is the address of the device configuration data structure. See 'Note #1' for more details.

    6. The fifth parameter is the address of the PHY API function. See Note #3' for more details.

    7. The sixth and last parameter is the address of the PHY configuration data structure. The PHY configuration should be located in net_dev_cfg.c/h.

  8. NetIF_Start() makes the network interface ready to receive and transmit. Once this function returns without an error the device should be able to receive packet, an interrupt should then be generated from the Ethernet controller (at least for each packets present on the cable).

  9. NetASCII_Str_to_IP() converts the human readable address into a format required by the protocol stack.

    In this example the IP address used, 10.10.10.64, addresses out of the 10.10.10.1 network with a subnet mask of 255.255.255.0. To match different networks, the IP address, the subnet mask and the default gateway's IP address have to be customized.

  10. NetIPv4_CfgAddrAdd() configures the network IPv4 static parameters (IPv4 address, subnet mask and default gateway) required for the interface. More than one set of network parameters can be configured per interface. NetIPv4_CfgAddrAdd() can be repeated for as many network parameter sets as need configuring for an interface.

    IPv4 parameters can be added whenever as long as the interface was added (initialized) even if the interface is started or not.

    For Dynamic IPv4 configuration, µC/DHCPc is required


  11. NetIPv6_CfgAddrAdd() configures the network IPv6 static parameters (IPv6 address and prefix length) required for the interface. More than one set of network parameters can be configured per interface. NetIPv6_CfgAddrAdd() can be repeated for as many network parameter sets as need configuring for an interface.

    IPv6 parameters can be added whenever as long as the interface is added (initialized) even if the interface is started or not.

    For the moment dynamic IPv6 is not yet supported either by IPv6 Autoconfig or DHCPv6c.

  12. NetIPv6_AddrAutoCfgHookSet() is used to set the IPv6 Auto-Configuration hook function that will received the result of the Auto-Configuration process.
    1. The first argument is the Network interface number on which the Auto-Configuration will take place.
    2. The second argument is the pointer to the hook function the application needs to implement. Refer to section IPv6 Stateless Address Auto-Configuration Hook Function for an example.

  13. NetIPv6_AddrAutoCfgEn() enables the interface to the IPv6 Address Auto-Configuration process. If the interface link state is already UP, the Auto-Configuration process will started immediately, else it will start after the interface link state becomes UP.

    1. The first argument is the Network interface number on which the Auto-Configuration will take place.
    2. The second argument enables or disables the Duplication Address Detection (DAD) during the Auto-Configuration process.