esp-open-rtosを使ってみる

APへの接続と接続結果の表示

ESP8266にはSoftAPモードとStationモードの2つのモードが有ります。
一度でもStationモードで起動すると、それ以降は特にモードを指定しなくてもStationモードのままとなります。
Stationモードでは、プログラム起動と同時に、バックグラウンドでAPへの接続タスク(dhcp client)が動きます。
Stationモードを使うシステムでは、APへの接続完了を待ってから処理を始める必要が有ります。

以下のコードでその動きを確認してみました。

task1
APの接続完了を待って、APから払い出されたMACアドレス、IPアドレス、ネットマスク、Gatewayアドレスを表示します。
MAC2STRやMACSTRなどの定義は、include/espressif/esp_misc.hの中で以下の様にdefineされていま す。
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"

#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
    ip4_addr2_16(ipaddr), \
    ip4_addr3_16(ipaddr), \
    ip4_addr4_16(ipaddr)

#define IPSTR "%d.%d.%d.%d"

task2
task1の処理中、task1以外のタスクがどのようにブロックされるのかを確認するために動かしています。
task1の終了で、このタスクも終了します。

/* The example of esp-free-rtos
 *
 * This sample code is in the public domain.
 */
#include <stdlib.h>
#include <string.h>
#include "espressif/esp_common.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp8266.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"

int TaskIsAlive = 1;

// WiFi Task
void task1(void *pvParameters)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Start\n",pcTaskGetName(0),nowTick);

  /* Wait until we have joined AP and are assigned an IP */
  int wifiStatus;
  while (1) {
    wifiStatus = sdk_wifi_station_get_connect_status();
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] wifiStatus=%d\n",pcTaskGetName(0),nowTick,wifiStatus);
    //if (sdk_wifi_station_get_connect_status() == STATION_GOT_IP) break;
    if (wifiStatus == STATION_GOT_IP) break;
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Connected to AP\n",pcTaskGetName(0),nowTick);

  uint8_t hwaddr[6];
  if (sdk_wifi_get_macaddr(STATION_IF, hwaddr)) {
    /*
    #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
    #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
    */
    printf("[%s] MAC address="MACSTR"\n",pcTaskGetName(0),MAC2STR(hwaddr));
  }
  struct ip_info info;
  if (sdk_wifi_get_ip_info(STATION_IF, &info)) {
    /*
    #define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
    ip4_addr2_16(ipaddr), \
    ip4_addr3_16(ipaddr), \
    ip4_addr4_16(ipaddr)
    #define IPSTR "%d.%d.%d.%d"
    */
    printf("[%s] IP address="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.ip));
    printf("[%s] Netmask="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.netmask));
    printf("[%s] Gateway="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.gw));
  }
  TaskIsAlive = 0;
  vTaskDelete( NULL );

}

// Dummy Task
void task2(void *pvParameters)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Start\n",pcTaskGetName(0),nowTick);
  while(TaskIsAlive) {
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] Running...\n",pcTaskGetName(0),nowTick);
    vTaskDelay(100/portTICK_PERIOD_MS);
  }
  vTaskDelete( NULL );
}


void user_init(void)
{
  uart_set_baud(0, 115200);
  printf("SDK version:%s\n", sdk_system_get_sdk_version());
  printf("pcTaskGetName=%s\n",pcTaskGetName(0));

  xTaskCreate(task1, "task1", 384, NULL, 2, NULL);
  xTaskCreate(task2, "task2", 256, NULL, 2, NULL);
}

結果は以下のようになりました。
148tick目でAPへの接続が完了し、その後DHCPクライアントが動き始めて、
408tick目でIPアドレスが割り当てられて、
438tick目でWiFiステータスがSTATION_GOT_IPに変わっていることが分かります。

バックグラウンドのタスクがAPへ接続しているとき(scandoneが実行中??)は、約130tickの間(約1.3秒間)、task1も task2も動けないようです。
Stationモードでネットワーク(WiFi)を使うシステムでは、APへの接続が完了するまで、他のタスクを待たせた方がいいかもしれませ ん。
SDK version:0.9.9
pcTaskGetName=uiT
mode : sta(18:fe:34:d4:2f:77)
add if0
[task1:1] Start
[task1:1] wifiStatus=1
[task2:1] Start
[task2:1] Running...
[task2:11] Running...
scandone
[task2:138] Running...
[task1:138] wifiStatus=1
add 0
aid 7
cnt

connected with aterm-e625c0-g, channel 11
dhcp client start...
[task2:148] Running...
[task2:158] Running...
[task2:168] Running...
[task2:178] Running...
[task2:188] Running...
[task2:198] Running...
[task2:208] Running...
[task2:218] Running...
[task2:228] Running...
[task1:238] wifiStatus=1
[task2:238] Running...
[task2:248] Running...
[task2:258] Running...
[task2:268] Running...
[task2:278] Running...
[task2:288] Running...
[task2:298] Running...
[task2:308] Running...
[task2:318] Running...
[task2:328] Running...
[task1:338] wifiStatus=1
[task2:338] Running...
[task2:348] Running...
[task2:358] Running...
[task2:368] Running...
[task2:378] Running...
[task2:388] Running...
[task2:398] Running...
ip:192.168.10.154,mask:255.255.255.0,gw:192.168.10.1
[task2:408] Running...
[task2:418] Running...
[task2:428] Running...
[task1:438] wifiStatus=5
[task1:438] Connected to AP
[task1] MAC address=18:fe:34:d4:2f:77
[task1] IP address=192.168.10.154
[task1] Netmask=255.255.255.0
[task1] Gateway=192.168.10.1



こちらに 固定IPアドレスにする方法が紹介されていました。
必要な部分だけをコピーして以下のコードで試してみました。
sdk_wifi_station_dhcpc_stop()でDHCPクライアントの処理を止めているのがミソの様です。
APのSSID、パスワード、IPアドレス、GWアドレスは各自の環境に合わせて変更が必要です。
/* The example of esp-free-rtos
 *
 * This sample code is in the public domain.
 */
#include <stdlib.h>
#include <string.h>
#include "espressif/esp_common.h"
#include "espressif/user_interface.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp8266.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"

int TaskIsAlive = 1;

// WiFi Task
void task1(void *pvParameters)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Start\n",pcTaskGetName(0),nowTick);

  /* Wait until we have joined AP and are assigned an IP */
  int wifiStatus;
  while (1) {
    wifiStatus = sdk_wifi_station_get_connect_status();
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] wifiStatus=%d\n",pcTaskGetName(0),nowTick,wifiStatus);
    //if (sdk_wifi_station_get_connect_status() == STATION_GOT_IP) break;
    if (wifiStatus == STATION_GOT_IP) break;
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
  printf("[%s:%d] Connected to AP\n",pcTaskGetName(0),nowTick);

  uint8_t hwaddr[6];
  if (sdk_wifi_get_macaddr(STATION_IF, hwaddr)) {
    /*
    #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
    #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
    */
    printf("[%s] MAC address="MACSTR"\n",pcTaskGetName(0),MAC2STR(hwaddr));
  }
  struct ip_info info;
  if (sdk_wifi_get_ip_info(STATION_IF, &info)) {
    /*
    #define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
    ip4_addr2_16(ipaddr), \
    ip4_addr3_16(ipaddr), \
    ip4_addr4_16(ipaddr)
    #define IPSTR "%d.%d.%d.%d"
    */
    printf("[%s] IP address="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.ip));
    printf("[%s] Netmask="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.netmask));
    printf("[%s] Gateway="IPSTR"\n",pcTaskGetName(0),IP2STR(&info.gw));
  }
  TaskIsAlive = 0;
  vTaskDelete( NULL );

}

// Dummy Task
void task2(void *pvParameters)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Start\n",pcTaskGetName(0),nowTick);
  while(TaskIsAlive) {
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] Running...\n",pcTaskGetName(0),nowTick);
    vTaskDelay(100/portTICK_PERIOD_MS);
  }
  vTaskDelete( NULL );
}


void user_init(void)
{
  uart_set_baud(0, 115200);
  printf("SDK version:%s\n", sdk_system_get_sdk_version());
  printf("pcTaskGetName=%s\n",pcTaskGetName(0));

  char ssid[] = "Your_SSID";
  char password[] = "Your_PASSWORD";
  struct sdk_station_config _station_info;
  struct ip_info static_ip_info;

  memset(&static_ip_info, 0, sizeof(static_ip_info));
  strcpy((char *)_station_info.ssid, ssid);
  strcpy((char *)_station_info.password, password);
  _station_info.bssid_set = 0;

  IP4_ADDR(&static_ip_info.ip, 192, 168, 10, 70);
  IP4_ADDR(&static_ip_info.gw, 192, 168, 10, 1);
  IP4_ADDR(&static_ip_info.netmask, 255, 255, 255, 0);
  sdk_wifi_station_dhcpc_stop();
  //vTaskDelay(50);

  //Must call sdk_wifi_set_opmode before sdk_wifi_station_set_config
  sdk_wifi_set_opmode(STATION_MODE);
  sdk_wifi_set_ip_info(STATION_IF, &static_ip_info);
  sdk_wifi_station_set_config(&_station_info);
  //sdk_wifi_station_connect();

  xTaskCreate(task1, "task1", 384, NULL, 2, NULL);
  xTaskCreate(task2, "task2", 256, NULL, 2, NULL);
}

結果は以下のようになりました。
指定したIPアドレスでAPに接続できています。
DHCPクライアントが動かない分、200Tickほど早くAPへの接続が完了します。
SDK version:0.9.9
pcTaskGetName=uiT
mode : sta(18:fe:34:d4:2f:77)
add if0
[task1:1] Start
[task1:1] wifiStatus=1
[task2:1] Start
[task2:1] Running...
[task2:11] Running...
scandone
[task2:138] Running...
[task1:138] wifiStatus=1
add 0
aid 11
cnt

connected with aterm-e625c0-g, channel 11
ip:192.168.10.70,mask:255.255.255.0,gw:192.168.10.1
[task2:148] Running...
[task2:158] Running...
[task2:168] Running...
[task2:178] Running...
[task2:188] Running...
[task2:198] Running...
[task2:208] Running...
[task2:218] Running...
[task2:228] Running...
[task1:238] wifiStatus=5
[task1:238] Connected to AP
[task1] MAC address=18:fe:34:d4:2f:77
[task1] IP address=192.168.10.70
[task1] Netmask=255.255.255.0
[task1] Gateway=192.168.10.1

続く....