はじめに

今回は、前回までの記事のまとめとして、Wi-Fi接続アプリを作成します。スイッチの押下によりWPSで接続し、Wi-Fi接続が完了・切断するとLEDが点灯・消灯します。LEDの点灯はWi-Fiの接続状態を意味します。

アプリの作成

基本的には今まで作成したコードにWi-Fi(WPS)のコードを追加するだけです。使用するWi-Fi関連のAPIとしては以下になります。

関数:
- qapi_WLAN_Enable():Wi-Fiの機能を有効化します。
- qapi_WLAN_Add_Device():デバイスを登録します。
- qapi_WLAN_Set_Callback():Wi-Fiのイベントを受け取るためのCallback関数を登録します。
- qapi_WLAN_WPS_Start():WPSのハンドシェイクを開始します。
- qapi_WLAN_WPS_Await_Compretion():QAPI_WLAN_WPS_CB_E受信後にWPSのハンドシェイクで成功したデバイスの情報を取得します。
- qapi_WLAN_Set_Param():接続するデバイスの情報を設定します。
- qapi_WLAN_WPS_Connect():qapi_WLAN_Set_Param()で設定したデバイスに接続します。QAPI_WLAN_CONNECT_CB_E受信で接続成功です。

イベント:
qapi_WLAN_Set_Callback()で登録するqapi_WLAN_Callback_tで通知されます。
QAPI_WLAN_WPS_CB_E:WPSのハンドシェイク完了の通知イベント
QAPI_WLAN_CONNECT_CB_E:WLANの接続・切断イベント
QAPI_WLAN_CONNECT_CB_Eイベントの接続・切断は、Callback関数のpayload引数で判断します。(qapi_WLAN_Connect_CB_Info_tのvalue)

処理の流れ
1. WLANの有効化
2. デバイスの登録
3. コールバックの登録
4. WPSの開始
5. QAPI_WLAN_WPS_CB_Eの受信(非同期)
6. 接続の開始
7. QAPI_WLAN_CONNECT_CB_Eの受信(非同期)
8. LEDの点灯

ソースコード

2・3回目(LED・割り込み)を取り込んだ全体のソースコードになります。

※流れを理解するためのものですので、エラー処理や変数定義などは省いている部分があります。

wifi_demo.c

メインの処理です。

worker_thread:起動後の初期化処理後、無限ループで待機

event_thread:各種Signalを処理

switch_callback:スイッチからの割り込みを処理

wlan_callback:WLANモジュールからのイベントを処理

#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

wifi関連の処理をまとめています。

initialize_wifi:WLANの有効化、デバイス・コールバックの登録

start_wps_pbc:WPSをPBC(Push button)で開始

connect_wps:WPSハンドシェイク完了後の接続処理

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関連の処理をまとめています。

initialize_gpio:LED・Switchで使用するGPIOの初期化、割り込みハンドラーの登録

turn_on_led:LEDを点灯

turn_off_led: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);
}

実行

リファレンスボードのGPIO12・27・GNDを前回までと同様に接続します。電源オンで、スイッチの割り込み待ち状態になります。スイッチ押下でWPSを開始します。AP側のWPSが有効になっていると数秒後にハンドシェイクが完了し、QAPI_WLAN_WPS_CB_Eをトリガに接続を開始します。接続完了のQAPI_WLAN_CONNECT_CB_E受信でLEDが点灯します。APの電源をOFFにするとしばらくしLEDが消灯(切断検知)します。

まとめ

今回は、スイッチを利用してWi-Fi(WPS)接続するアプリを作成してみました。QCA4020では、今回のアプリで使用したGPIO以外にもUART/SPI/I2Cに対応しているので、ホストのSoCから操作可能です。また、ホストになるSoCがない環境でも、BLEを利用することで操作可能です。ユーザーアプリケーション用に300KB(外部フラッシュも追加可能)ありますので、用途に沿ったアプリケーションを開発可能です。

QCA4020にご興味がありましたら、以下のボタンからお問い合わせください。

お問い合わせ

本記事に関してご質問などありましたら、以下より問い合わせください。

Qualcomm メーカー情報Topへ

Qualcomm メーカー情報Topページへ戻りたい方は、以下をクリックください。