はじめに
今回は、前回までの記事のまとめとして、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ページへ戻りたい方は、以下をクリックください。