WiFi Sample Application

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

    1. Initialize Stack tasks and objects
    2. Initialize a Wireless Interface
    3. Start that Wireless Interface
    4. Scan for Wireless network available
    5. Analyze scan results
    6. Join a Wireless network
    7. 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_wifi.c, located in the folder $/Micrium/Software/uC-TCPIP/Examples/Init, contains this sample application:

Listing - AppInit_TCPIP_WiFi()
#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_wifi.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/WiFi/Template/net_dev_wifi_template_spi.h>   /* See Note #2.           */
#include  <Dev/WiFi/Manager/Generic/net_wifi_mgr.h>
#include  <BSP/Template/net_bsp_wifi.h>                     /* See Note #3.           */
 
CPU_BOOLEAN  AppInit_TCPIP_WiFi (void)
{
#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       addr_ipv6;
#endif
#endif
    NET_IF_NBR          if_nbr;
    NET_IF_WIFI_AP      ap[10];
    NET_IF_WIFI_SSID   *p_ssid;
    NET_IF_WIFI_SSID    ssid;
    NET_IF_WIFI_PSK     psk;
    CPU_INT16U          ctn;
    CPU_INT16U          i;
    CPU_INT16S          result;
    CPU_BOOLEAN         found;
    NET_ERR             err_net;
 
                                                        /* ------- PREREQUISITES MODULE INIT -------- */
    CPU_Init();                                         /* See Note #4.                               */
    Mem_Init();
                                                        /* ------ INIT NETWORK TASKS & OBJECTS ------ */
    err_net = Net_Init(&NetRxTaskCfg,                   /* See Note #5.                               */
                       &NetTxDeallocTaskCfg,
                       &NetTmrTaskCfg);
    if (err_net != NET_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* --------- ADD WIRELESS INTERFACE --------- */
                                                        /* See Note #6.                               */
    if_nbr = NetIF_Add(&NetIF_API_WiFi,                 /* See Note #6b.                              */
                       &NetDev_API_TemplateWiFiSpi,     /* BSP API,              See Note #6d.        */
                       &NetDev_BSP_WiFi,                /* Device configuration, See Note #6e.        */
                       &NetDev_Cfg_WiFi_1,              /* PHY driver API,       See Note #6f.        */
                       &NetWiFiMgr_API_Generic,         /* PHY configuration,    See Note #6g.        */
                        DEF_NULL,
                       &err_net);
    if (err_net != NET_IF_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* -------- START WIRELESS INTERFACE -------- */
                                                        /* See Note #7.                               */
    NetIF_Start(if_nbr, &err_net);                      /* Makes the IF ready to RX and TX.           */
    if (err_net != NET_IF_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* ------- SCAN FOR WIRELESS NETWORKS ------- */
    ctn = NetIF_WiFi_Scan(if_nbr,                       /* See Note #11.                              */
                          ap,                           /* Access point table See Note #11a.          */
                          10,                           /* Access point table size.                   */
                          DEF_NULL,                     /* Hidden SSID See Note #11b.                 */
                          NET_IF_WIFI_CH_ALL,           /* Channel to scan See Note #11c.             */
                         &err_net);
    if (err_net != NET_IF_WIFI_ERR_NONE) {
        return (DEF_FAIL);
    }
                                                        /* ------ ANALYSE WIFI NETWORKS FOUND ------- */
    found = DEF_NO;
    for (i = 0; i < ctn - 1; i++) {                     /* Browse table of access point found.        */
        p_ssid = &ap[i].SSID;
        result = Str_Cmp_N(p_ssid,                      /* Search for a specific WiFi Network SSID.   */
                          "Wifi_AP_SSID",               /* WiFi Network SSID.                         */
                           NET_IF_WIFI_STR_LEN_MAX_SSID);
        if (result == 0) {
            found = DEF_YES;
            break;
        }
    }
    if (found == DEF_NO) {
        return (DEF_FAIL);
    }
                                                        /* -------- JOIN A WIRELESS NETWORK --------- */
    Mem_Clr(&ssid, sizeof(ssid));
    Mem_Clr(&psk,  sizeof(psk));
    Str_Copy_N((CPU_CHAR *)&ssid,
                           "Wifi_AP_SSID",              /* WiFi Network SSID.                         */
                            12);                        /* SSID string length.                        */
    Str_Copy_N((CPU_CHAR *)&psk,
                           "Password",                  /* Pre shared Key (PSK), Wifi password.       */
                            8);                         /* PSK string length.                         */
    NetIF_WiFi_Join(if_nbr,                             /* See Note #12.                              */
                    ap[i].NetType,                      /* See Note #12a.                             */
                    NET_IF_WIFI_DATA_RATE_AUTO,         /* See Note #12b.                             */
                    ap[i].SecurityType,                 /* See Note #12c.                             */
                    NET_IF_WIFI_PWR_LEVEL_HI,           /* See Note #12d.                             */
                    ssid,                               /* See Note #12e.                             */
                    psk,                                /* See Note #12f.                             */
                   &err_net);
    if (err_net != NET_IF_WIFI_ERR_NONE) {
        return (DEF_FAIL);
    }
 
#ifdef NET_IPv4_MODULE_EN
                                                        /* ------ CONFIGURE IPV4 STATIC ADDR -------- */
                                                        /* For Dynamic IPv4 cfg, µC/DHCPc is required */
                                                        /* TODO Update IPv4 Addr following your ...   */
                                                        /* ... network requirements.                  */
                                                        /* See Note #10.                              */
    NetASCII_Str_to_IP("10.10.10.64",                   /* Convert Host IPv4 string to 32 bit addr.   */
                       &addr_ipv4,
                        NET_IPv4_ADDR_SIZE,
                       &err_net);
    NetASCII_Str_to_IP("255.255.255.0",                 /* Convert IPv4 mask string to 32 bit addr.   */
                       &msk_ipv4,
                        NET_IPv4_ADDR_SIZE,
                       &err_net);
    NetASCII_Str_to_IP("10.10.10.1",                    /* Convert Gateway string to 32 bit 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 #11.*/
                       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-CONFIG ---- */
                                                        /* See Note #13.                              */
    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 #14.                              */
    cfg_result = NetIPv6_AddrAutoCfgEn(if_nbr,          /* Enable and Start Auto-Config process.      */
                                   DEF_YES,
                                  &err_net);
    if (cfg_result == DEF_FAIL) {
        return (DEF_FAIL);
    }
    
#else
                                                        /* ----- CFG IPV6 STATIC LINK LOCAL ADDR ---- */
                                                        /* DHCPv6c is not yet available.              */
 
    ipv6_flags = 0;                                     
    DEF_BIT_SET(ipv6_flags, NET_IPv6_FLAG_BLOCK_EN);    /* Set Address Configuration as blocking.     */
    DEF_BIT_SET(ipv6_flags, NET_IPv6_FLAG_DAD_EN);      /* Enable DAD with Address Configuration.     */
                                                        /* TODO Update IPv6 Addr following your  ...  */
                                                        /* ... network requirements.                  */
                                                        /* See Note #10.                              */
    NetASCII_Str_to_IP("fe80::1111:1111",               /* Convert IPv6 string addr to 128 bit addr.  */
                       &addr_ipv6,
                        NET_IPv6_ADDR_SIZE,
                       &err_net);
    cfg_result = NetIPv6_CfgAddrAdd(if_nbr,             /* Add a statically-configured IPv6 host  ... */
                                   &addr_ipv6,          /* ... addr to the interface. See Note #12.   */
                                    64,
                                    ipv6_flags,
                                   &err_net);
    if (cfg_result == DEF_FAIL) {
        return (DEF_FAIL);
    }
#endif
#endif
    return (DEF_OK);
}
  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 wireless module. 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 a Wireless device driver which can be found under the following folder:

      $/Micrium/Software/uC-TCPIP/Dev/WiFi/<module>/net_dev_<module>.h

    If Micrium does not support your network wireless device driver, you will have to write your own device driver starting from the Wireless Device driver template. Before starting to write your own driver, make sure that the driver is not already available.
     

  3. 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.

    However we recommend, starting with a working configuration from an example project for your Wireless module. 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 and your Wireless Module.
     

  4. 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
       

  5. 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.
       
  6. 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 #3 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 WiFi Manager API function. This API is provided by Micriµm and it's located in:

       $/uC-TCPIP/Dev/WiFi/Manager/Generic/net_wifi_mgr.h
       
    7. The sixth and last parameter is the address of the WiFi manager configuration data structure. Actually there are no configuration require with the generic WiFi manager. So this parameters can be kept as null.
       

  7. NetIF_Start() makes the network interface scan, join or create adhoc wireless network. This function must interact with the wireless module thus some interrupt should be generated from the wireless's interrupt pin when calling this function.
     

  8. NetIF_WiFi_Scan() is used to scan for available Wireless Network available in the range.

    1. The second parameter is a table of access point that will be receive access points found in the range. Obviously, the maximum number of access point that the table can store must be past to the function.
       

    2. It's possible to scan for a specific hidden network by passing a string that contains the SSID of the hidden network. If the scan request is for all access point, you only have to pass a null pointer.
       

    3. The fourth parameter is the wireless channel to scan on, it can be:

        NET_IF_WIFI_CH_ALL
      NET_IF_WIFI_CH_1
      NET_IF_WIFI_CH_2
      NET_IF_WIFI_CH_3
      NET_IF_WIFI_CH_4
      NET_IF_WIFI_CH_5
      NET_IF_WIFI_CH_6
      NET_IF_WIFI_CH_7
      NET_IF_WIFI_CH_8
      NET_IF_WIFI_CH_9
      NET_IF_WIFI_CH_10
      NET_IF_WIFI_CH_11
      NET_IF_WIFI_CH_12
      NET_IF_WIFI_CH_13
      NET_IF_WIFI_CH_14
       
  9. NetIF_WiFi_Join() is used to join a wireless network. Note that the network must has been found during a scan previously. Once the wireless access point is join, it is possible to receive and transmit packet on the network.

    1. The second parameter is the Network type it can be either:


      NET_IF_WIFI_NET_TYPE_INFRASTRUCTURE
      NET_IF_WIFI_NET_TYPE_ADHOC


      The scan function should return the network type as well.

    2. The third parameter is the wireless date rate to configure:

        NET_IF_WIFI_DATA_RATE_AUTO 
      NET_IF_WIFI_DATA_RATE_1_MBPS
      NET_IF_WIFI_DATA_RATE_2_MBPS
      NET_IF_WIFI_DATA_RATE_5_5_MBPS
      NET_IF_WIFI_DATA_RATE_6_MBPS
      NET_IF_WIFI_DATA_RATE_9_MBPS
      NET_IF_WIFI_DATA_RATE_11_MBPS
      NET_IF_WIFI_DATA_RATE_12_MBPS
      NET_IF_WIFI_DATA_RATE_18_MBPS
      NET_IF_WIFI_DATA_RATE_24_MBPS
      NET_IF_WIFI_DATA_RATE_36_MBPS
      NET_IF_WIFI_DATA_RATE_48_MBPS
      NET_IF_WIFI_DATA_RATE_54_MBPS
      NET_IF_WIFI_DATA_RATE_MCS0
      NET_IF_WIFI_DATA_RATE_MCS1
      NET_IF_WIFI_DATA_RATE_MCS2
      NET_IF_WIFI_DATA_RATE_MCS3
      NET_IF_WIFI_DATA_RATE_MCS4
      NET_IF_WIFI_DATA_RATE_MCS5
      NET_IF_WIFI_DATA_RATE_MCS6
      NET_IF_WIFI_DATA_RATE_MCS7
      NET_IF_WIFI_DATA_RATE_MCS8
      NET_IF_WIFI_DATA_RATE_MCS9
      NET_IF_WIFI_DATA_RATE_MCS10
      NET_IF_WIFI_DATA_RATE_MCS11
      NET_IF_WIFI_DATA_RATE_MCS12
      NET_IF_WIFI_DATA_RATE_MCS13
      NET_IF_WIFI_DATA_RATE_MCS14
      NET_IF_WIFI_DATA_RATE_MCS15
    3. The fourth parameter is the wireless network's security type. It can be:
        NET_IF_WIFI_SECURITY_OPEN
       NET_IF_WIFI_SECURITY_WEP
       NET_IF_WIFI_SECURITY_WPA
       NET_IF_WIFI_SECURITY_WPA2
      The scan function should return the network security type as well.
    4. The fifth parameter is the wireless radio's power level. It can be:
        NET_IF_WIFI_PWR_LEVEL_LO
       NET_IF_WIFI_PWR_LEVEL_MED
       NET_IF_WIFI_PWR_LEVEL_HI
    5. The sixth parameter is the access point's SSID to join.
    6. The seventh parameter is the Pre shared key (PSK) of the access point's. If the security type of the access point is open, the PSK can set to null.

  10. 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.


  11. 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
     

  12. 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.

  13. 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.

  14. 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.