esp-open-rtosを使ってみる

Socket-APIとRAW-API

lwIPには3つのAPIが用意されています。
・raw API(callback API)
・Sequential-style API(Netconn APIとNETIF API)
・Socket API(BSD-Socket API)

そこで、少しだけですが、raw APIとはどのようなAPIなのか紹介します。
以下のコードでは、3つのタスクを起動しています。

task1(WiFiタスク)
APの接続状況を監視し、接続が完了したらSemaphoreを使ってtask2に許可を与えます。

task2(Socket-APIタスク)
Socket API(lwip_gethostbyname関数)を使って、ホスト名(ntp.nict.jp)のIPアドレスを求めます。
処理が終わったら、Semaphoreを使ってtask3に許可を与えます。

task3(RAW-APIタスク)
raw API(dns_gethostbyname関数)を使って、ホスト名(pool.ntp.org)のIPアドレスを求めます。
ホスト名にntp.nict.jpを指定すると、なぜか止まってしまいます。

/* 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/udp.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"

#define SNTP_SERVER "ntp.nict.jp"
#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
    ip4_addr2_16(ipaddr), \
    ip4_addr3_16(ipaddr), \
    ip4_addr4_16(ipaddr)

SemaphoreHandle_t xSemaphore1;
SemaphoreHandle_t xSemaphore2;


void sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
{
  TickType_t nowTick;
  nowTick = xTaskGetTickCount();
  LWIP_UNUSED_ARG(hostname);
  LWIP_UNUSED_ARG(arg);

  if (ipaddr != NULL) {
    /* Address resolved, send request */
    printf("[%s:%d] Server address resolved, ipaddr=%d.%d.%d.%d\n",pcTaskGetName(0),nowTick,IP2STR(ipaddr));
    //printf("sntp_dns_found ipaddr=%d.%d.%d.%d\n",IP2STR(ipaddr));
  } else {
    /* DNS resolving failed -> try another server */
    printf("[%s:%d] Failed to resolve server address resolved\n",pcTaskGetName(0),nowTick);
  }
}

// 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);
  //showNetworkInfo();

  /* Now start task2 */
  xSemaphoreGive(xSemaphore1);
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Give to task2\n",pcTaskGetName(0),nowTick);

#if 0
  /* Now start task3 */
  xSemaphoreGive(xSemaphore2);
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Give to task3\n",pcTaskGetName(0),nowTick);
#endif

  while(1) {
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

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

  /* wait for Semaphore */
  xSemaphoreTake(xSemaphore1, portMAX_DELAY);
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Take\n",pcTaskGetName(0),nowTick);

  /* Convert URL to IP using Socket */
  struct hostent *hostent; // Server data structure.
  hostent = lwip_gethostbyname(SNTP_SERVER);
  LWIP_ASSERT("hostent != NULL", hostent != NULL);

  printf("[%s:%d] %s = ",pcTaskGetName(0),nowTick,hostent->h_name);
  unsigned int i=0;
  while ( hostent->h_addr_list[i] != NULL) {
    printf("%s ", inet_ntoa( *( struct in_addr*)( hostent->h_addr_list[i])));
    i++;
  }
  printf("\n");

  /* Now start task3 */
  xSemaphoreGive(xSemaphore2);
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Give to task3\n",pcTaskGetName(0),nowTick);

  while(1) {
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}


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

  /* wait for Semaphore */
  xSemaphoreTake(xSemaphore2, portMAX_DELAY);
  nowTick = xTaskGetTickCount();
  printf("[%s:%d] Take\n",pcTaskGetName(0),nowTick);

  /** The UDP pcb used by the SNTP client */
  struct udp_pcb* sntp_pcb;
  /** Addresses of servers */
  const char* sntp_server = "pool.ntp.org";
  ip_addr_t sntp_server_address;

  err_t err;
  sntp_pcb = udp_new();
  LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
  if (sntp_pcb != NULL) {
      err = dns_gethostbyname(sntp_server, &sntp_server_address, sntp_dns_found, NULL);
      if (err == ERR_INPROGRESS) {
        /* DNS request sent, wait for sntp_dns_found being called */
        printf("[%s:%d] Waiting for server address to be resolved.\n",pcTaskGetName(0),nowTick);
      }
  }

  while(1) {
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}


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));

  /* Create Semaphore */
  xSemaphore1 = xSemaphoreCreateBinary();
  xSemaphore2 = xSemaphoreCreateBinary();
  /* Check everything was created. */
  configASSERT( xSemaphore1 );
  configASSERT( xSemaphore2 );

  xTaskCreate(task1, "WiFi", 256, NULL, 2, NULL);
  xTaskCreate(task2, "Socket-API", 256, NULL, 2, NULL);
  xTaskCreate(task3, "RAW-API", 256, NULL, 2, NULL);
}


起動すると以下の表示となります。
Socket-APIタスクはコードの順番に処理が進みますが、
RAW-APIタスクでは、dns_gethostbyname()の結果がCallBack関数(sntp_dns_found)に戻ります。
CallBack関数のタスク名は「tcpip_thread」となっています。
CallBack関数内でsendやreceiveなどのraw-APIを呼び出した場合、その結果もCallBack関数に戻ります。
つまり、raw-APIではCallBackの連続となります。
SDK version:0.9.9
pcTaskGetName=uiT
[WiFi:1] Start
[WiFi:1] wifiStatus=1
[Socket-API:1] Start
[RAW-API:1] Start
[WiFi:138] wifiStatus=1
connected with aterm-e625c0-g, channel 11
dhcp client start...
[WiFi:238] wifiStatus=1
[WiFi:338] wifiStatus=1
ip:192.168.10.154,mask:255.255.255.0,gw:192.168.10.1
[WiFi:438] wifiStatus=5
[WiFi:438] Connected to AP
[WiFi:438] Give to task2
[Socket-API:438] Take
[Socket-API:438] ntp.nict.jp = 133.243.238.243
[Socket-API:440] Give to task3
[RAW-API:440] Take
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
Function called without core lock
[RAW-API:440] Waiting for server address to be resolved.
[tcpip_thread:450] Server address resolved, ipaddr=133.243.238.163

raw-APIは難しいので、これ以上の追及はやめます。

続く....