Site Search

Introduction

This time, we will create a Wi-Fi connection application as a summary of the previous articles. By pressing the switch, you can connect with WPS, and when the Wi-Fi connection is completed/disconnected, the LED will turn on/off. The lighting of the LED means the Wi-Fi connection status.

App creation

Basically, just add the Wi-Fi (WPS) code to the code you have created so far. The Wi-Fi related APIs to be used are as follows.

function:
- qapi_WLAN_Enable(): Enable Wi-Fi functionality.
- qapi_WLAN_Add_Device(): Register a device.
- qapi_WLAN_Set_Callback(): Register a Callback function to receive Wi-Fi events.
- qapi_WLAN_WPS_Start(): Start WPS handshake.
- qapi_WLAN_WPS_Await_Compretion(): Get the information of the device that has passed the WPS handshake after receiving QAPI_WLAN_WPS_CB_E.
- qapi_WLAN_Set_Param(): Sets the information of the connected device.
- qapi_WLAN_WPS_Connect(): Connect to the device set by qapi_WLAN_Set_Param(). Received QAPI_WLAN_CONNECT_CB_E and succeeded in connecting.

event:
It is notified by qapi_WLAN_Callback_t registered by qapi_WLAN_Set_Callback().
QAPI_WLAN_WPS_CB_E: Notification event for WPS handshake completion
QAPI_WLAN_CONNECT_CB_E: WLAN connect/disconnect event
The connection/disconnection of the QAPI_WLAN_CONNECT_CB_E event is determined by the payload argument of the Callback function. (value of qapi_WLAN_Connect_CB_Info_t)

Processing flow
1. Enable WLAN
2. Device registration
3. Callback registration
4. Start WPS
5. Receive QAPI_WLAN_WPS_CB_E (asynchronous)
6. Start connection
7. Receive QAPI_WLAN_CONNECT_CB_E (asynchronous)
8. LED lighting

Source code

This is the entire source code that includes the 2nd and 3rd times (LED/interrupt).

* Since it is for understanding the flow, some parts such as error handling and variable definition are omitted.

wifi_demo.c

This is the main process.

worker_thread: Wait in an infinite loop after initialization after startup

event_thread: Process various Signals

switch_callback: handle interrupts from the switch

wlan_callback: handle events from WLAN module

#define SWITCH_EVENT (0x01) #define CONNECT_EVENT (0x02) #define DISCONNECT_EVENT (0x04) #define WPS_EVENT (0x08) #define EVENT_MASK (SWITCH_EVENT | CONNECT_EVENT | DISCONNECT_EVENT | WPS_EVENT) static qurt_signal_t event; static void switch_callback(qapi_GPIOINT_Callback_Data_t data) { qurt_signal_set(&event, SWITCH_EVENT); } static int32_t wlan_callback( uint8_t deviceId, uint32_t cbId, void *pApplicationContext, void *payload, uint32_t payload_Length) { switch(cbId) { case QAPI_WLAN_CONNECT_CB_E: { qapi_WLAN_Connect_Cb_Info_t *info = (qapi_WLAN_Connect_Cb_Info_t *)payload; if (info->value) { qurt_signal_set(&event, CONNECT_EVENT); } else { qurt_signal_set(&event, DISCONNECT_EVENT); } break; } case QAPI_WLAN_WPS_CB_E: qurt_signal_set(&event, WPS_EVENT); break; } } void event_thread(void *para) { uint32_t signal_set = 0; qurt_signal_init(&event); for(;;) { qurt_signal_wait_timed(&event, EVENT_MASK, (QURT_SIGNAL_ATTR_WAIT_ANY | QURT_SIGNAL_ATTR_CLEAR_MASK), &signal_set, QURT_TIME_WAIT_FOREVER); if (signal_set & SWITCH_EVENT) { start_wps_pbc(); } if (signal_set & WPS_EVENT) { connect_wps(); } if (signal_set & CONNECT_EVENT) { turn_on_led(); } if (signal_set & DISCONNECT_EVENT) { turn_off_led(); } } } static void worker_thread(void *Param) { initialize_wifi(wlan_callback); initialize_gpio(switch_callback); while (true) { Sleep(1000); } } void App_Start(qbool_t ColdBoot) { qurt_thread_attr_t worker_thread_attr; qurt_thread_t worker_thread_handle; qurt_thread_attr_t event_thread_attr; qurt_thread_t event_thread_handle; qurt_thread_attr_init(&event_thread_attr); qurt_thread_attr_set_name(&event_thread_attr, "EventThread"); qurt_thread_attr_set_priority(&event_thread_attr, THREAD_PRIORITY); qurt_thread_attr_set_stack_size(&event_thread_attr, THREAD_STACK_SIZE); qurt_thread_create(&event_thread_handle, &event_thread_attr, event_thread, NULL); qurt_thread_attr_init(&worker_thread_attr); qurt_thread_attr_set_name(&worker_thread_attr, "WorkerThread"); qurt_thread_attr_set_priority(&worker_thread_attr, THREAD_PRIORITY); qurt_thread_attr_set_stack_size(&worker_thread_attr, THREAD_STACK_SIZE); qurt_thread_create(&worker_thread_handle, &worker_thread_attr, worker_thread, NULL); }

wifi.c

It summarizes wifi-related processing.

initialize_wifi: enabling WLAN, registering device callbacks

start_wps_pbc: Start WPS with PBC (Push button)

connect_wps: Connection processing after WPS handshake completion

qapi_Status_t initialize_wifi(qapi_WLAN_Callback_t cb)
{
	qapi_WLAN_Enable(QAPI_WLAN_ENABLE_E);
	qapi_WLAN_Add_Device(0);
        qapi_WLAN_Set_Callback(0, cb, NULL);
}
qapi_Status_t start_wps_pbc()
{
	qapi_WLAN_WPS_Start(0,
							QAPI_WLAN_WPS_NO_ACTION_POST_CONNECT_E,
							QAPI_WLAN_WPS_PBC_MODE_E,
							&wps_pin);
}
qapi_Status_t connect_wps()
{
	qapi_WLAN_Netparams_t net_param;
        qapi_WLAN_WPS_Credentials_t wpsCred;
        uint32_t passphraseLen = 0;  
        memset(&wpsCred, 0, sizeof(qapi_WLAN_WPS_Credentials_t));
	memset(&net_param, 0x00, sizeof(qapi_WLAN_Netparams_t));
	net_param.dont_Block = 0;
	qapi_WLAN_WPS_Await_Completion(0, &net_param);
	memset(buf, 0x00, sizeof(buf));
	wpsCred.ssid_Length = strlen((char*)net_param.ssid);
	strncpy((char *) wpsCred.ssid, (char*)net_param.ssid, wpsCred.ssid_Length);
	wpsCred.auth_Mode = QAPI_WLAN_AUTH_WPA2_PSK_E;
	wpsCred.encryption_Type = net_param.cipher.ucipher;
	passphraseLen = strlen((char*)net_param.u.passphrase);  
	qapi_WLAN_Set_Param(0,  
						__QAPI_WLAN_PARAM_GROUP_WIRELESS, 
						__QAPI_WLAN_PARAM_GROUP_WIRELESS_SSID,
						(char *) net_param.ssid,
						sizeof(net_param.ssid),
						0);  
	qapi_WLAN_Set_Param(0,
						__QAPI_WLAN_PARAM_GROUP_WIRELESS_SECURITY,
						__QAPI_WLAN_PARAM_GROUP_SECURITY_PASSPHRASE,
						(void *) net_param.u.passphrase,
						passphraseLen,
						0);
	qapi_WLAN_Set_Param (0,
						__QAPI_WLAN_PARAM_GROUP_WIRELESS_SECURITY,
						__QAPI_WLAN_PARAM_GROUP_SECURITY_WPS_CREDENTIALS,
						&wpsCred,
						sizeof(qapi_WLAN_WPS_Credentials_t),
						0);
	qapi_WLAN_WPS_Connect(0);
}

gpio.c

GPIO related processing is summarized.

initialize_gpio: Initialize GPIO used by LED/Switch, register interrupt handler

turn_on_led: turn on LED

turn_off_led: turn off the LED

static qapi_GPIO_ID_t gpio_id_12;
static qapi_GPIO_ID_t gpio_id_27;
static qapi_TLMM_Config_t gpio_cfg_12;
static qapi_TLMM_Config_t gpio_cfg_27;
static qapi_PWM_Handle_t handle;
static qapi_PWM_Config_t config_set;
static qapi_Instance_Handle_t int_handle;
qapi_Status_t initialize_gpio(qapi_GPIOINT_CB_t cb)
{
	gpio_cfg_27.func = 0;
	gpio_cfg_27.dir = QAPI_GPIO_INPUT_E;
	gpio_cfg_27.pull = QAPI_GPIO_PULL_UP_E;
	gpio_cfg_27.drive = QAPI_GPIO_2MA_E;
	gpio_cfg_27.pin = 27;
	qapi_TLMM_Get_Gpio_ID(&gpio_cfg_27, &gpio_id_27);
	qapi_TLMM_Config_Gpio(gpio_id_27, &gpio_cfg_27);
	// Configure GPIO12
	gpio_cfg_12.func = 0;
	gpio_cfg_12.dir = QAPI_GPIO_OUTPUT_E;
	gpio_cfg_12.pull = QAPI_GPIO_NO_PULL_E;
	gpio_cfg_12.drive = QAPI_GPIO_4P0MA_E;
	gpio_cfg_12.pin = 12;
	config_set.freq = 30000;
	config_set.duty = 500;
	config_set.phase = 2000;
	config_set.moduleType = 0;
	config_set.source_CLK = QAPI_PWM_SOURCE_CLK_SLEEP_MODE_E;
	// Drive GPIO with high value
	qapi_TLMM_Get_Gpio_ID(&gpio_cfg_12, &gpio_id_12);
	qapi_TLMM_Config_Gpio(gpio_id_12, &gpio_cfg_12);
	qapi_GPIOINT_Register_Interrupt(&int_handle,
										27,
										cb,
										0,
										QAPI_GPIOINT_TRIGGER_EDGE_FALLING_E,
										QAPI_GPIOINT_PRIO_MEDIUM_E,
										false);
}
qapi_Status_t turn_on_led()
{
	qapi_TLMM_Drive_Gpio(gpio_id_12, gpio_cfg_12.pin, QAPI_GPIO_HIGH_VALUE_E);
}
qapi_Status_t turn_off_led()
{
	qapi_TLMM_Drive_Gpio(gpio_id_12, gpio_cfg_12.pin, QAPI_GPIO_LOW_VALUE_E);
}

execution

Connect GPIO12, 27, and GND on the reference board in the same way as before. When the power is turned on, the switch waits for an interrupt. Press the switch to start WPS. If WPS on the AP side is enabled, the handshake will be completed after a few seconds, and QAPI_WLAN_WPS_CB_E will trigger the connection. The LED lights up when QAPI_WLAN_CONNECT_CB_E is received to indicate connection completion. When the AP power is turned off, the LED turns off (disconnection detection) after a while.

Summary

This time, I tried to create an application that connects to Wi-Fi (WPS) using a switch. The QCA4020 supports UART/SPI/I2C in addition to the GPIO used in this application, so it can be operated from the host SoC. Also, even in an environment without a host SoC, it can be operated by using BLE. Since there is 300KB for user applications (external flash can be added), applications can be developed according to the purpose.

If you are interested in QCA4020, please contact us from the button below.

Inquiry

If you have any questions regarding this article, please contact us below.

To Qualcomm manufacturer information Top

If you want to return to the Qualcomm manufacturer information top page, please click below.