WiFi Sample Application
- This example show how to initialize µC/TCP-IP:
- Initialize Stack tasks and objects
- Initialize a Wireless Interface
- Start that Wireless Interface
- Scan for Wireless network available
- Analyze scan results
- Join a Wireless network
- 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:
#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); }
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.
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.
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.
Some prerequisite module initializations are required. The following modules must be initialized prior to starting the Network Protocol stacks initialization:
uC/CPU
uC/LIB Memory module
Net_Init() is the Network Protocol stack's initialization function. It must only be called once and before any other Network functions.
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
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.
NetIF_Add()
is a network interface function responsible for initializing a Network Device driver.
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.
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
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
The third parameter is the address of the device BSP data structure. See Note #3 for more details.
The fourth parameter is the address of the device configuration data structure. See Note #1 for more details.
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
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.
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.
NetIF_WiFi_Scan()
is used to scan for available Wireless Network available in the range.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.
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.
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
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.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.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- The fourth parameter is the wireless network's security type. It can be:
NET_IF_WIFI_SECURITY_OPEN
The scan function should return the network security type as well.
NET_IF_WIFI_SECURITY_WEP
NET_IF_WIFI_SECURITY_WPA
NET_IF_WIFI_SECURITY_WPA2 - 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 - The sixth parameter is the access point's SSID to join.
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.
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.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
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.NetIPv6_AddrAutoCfgHookSet()
is used to set the IPv6 Auto-Configuration hook function that will received the result of the Auto-Configuration process.- The first argument is the Network interface number on which the Auto-Configuration will take place.
- 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.
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.- The first argument is the Network interface number on which the Auto-Configuration will take place.
The second argument enables or disables the Duplication Address Detection (DAD) during the Auto-Configuration process.