ESP8266のSmartPlugを試す

ESP8266_IOT_PLATFORMに含まれるSmartPlugを試してみた。
装置の各種設定をWEBページで行えるようにしたいのだが、ゼロから作るのは大変なのでSmartPlugが使えないかと考えた。
結論から言うと、バグを直せば使えそうである。
解凍したままでは、WEBページが正しく表示されないバグがある。

1つ目は、ESP8255_RTOS_SDK内でIPを実装しているlwipのマルチスレッド対応部分のうち、closeを行う部分で状態をSHUTODOWN_NONE状態に戻さないバグ。
closeを実行した後にselectで同期を取ろうとすると返り値が継続的に-1になってしまい、全てのソケット通信を続けられなくなってしまう。

socket_mt.c 351行目付近
SOCK_MT_SET_SHUTDOWN(s, SOCK_MT_STATE_NONE);
が抜けている。

2つ目は、espfsが扱うファイルイメージが4バイト境界に整列する前提であるにも関わらず、特に指定がなされていないため4バイト境界に整列しない場合があるバグ。
一つの直し方を下記に示す。
espfsというセクションを新設し4バイト境界に整列させる考え方。

ESP8266_IOT_PLATFORM\libesphttpd\Makefile 150行目付近
【修正前】
 $(Q) $(OBJCOPY) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.irom0.literal \ 
【修正後】
$(Q) $(OBJCOPY) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.espfs \
ESP8266_RTOS_SDK\ld\eagle.app.v6.common.ld 113行目付近
【修正前】
 *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
.data=.irom0.literal \ 
【修正後】
 *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
 . = ALIGN (4);
 *(.espfs)

この2つを修正すれば、ちゃんと動くようになる。

実害は無いが、ESP8266_IOT_PLATFORM内のHTTPサーバを実装する部分で、ポート番号とIPアドレスを保持する部分に抜けがあり、接続先のIPアドレスとポート番号を保持できない部分がある。代入されたconnData[index].remote_portとconnData[index].remote_ipはどこでも使われていないため問題は顕在化しない。

httpd.c 706行目付近
struct sockaddr name;
int len = sizeof(name);
getpeername(connData[index].conn->sockfd, (socklen_t *)&len);
                    ~~~~~~~~
struct sockaddr_in *piname=(struct sockaddr_in *)&name;
connData[index].remote_port = piname->sin_port;
connData[index].remote_ip=piname->in_addr.s_addr;

 

ESP8266_RTOS_SDKのsocketサポート

FreeRTOSのサポートは十分でなかった状況とは異なり、socketでソケットを作成し接続、データ送受信くらいの範囲では、完全に互換性が取れている。
既存のソースを張り付けるだけでコンパイルでき、動作も問題ない。

lwIPにより実装されており、BSDソケットと互換性がある。
ホームページ上のドキュメントではソケットのサポートはオプションとなっているが、実装されているようだ。

ESP8266_RTOS_SDKのFreeRTOSサポート

FreeRTOSのホームページ上でAPI Referenceを見てコーディングしてもエラーが出てしまう。

xTimerCreate をコールするために、TimerHandle_t型を使いたいのだが、無いとのエラーが表示される。

ESP8266_RTOS_SDK\include\freertos\timers.h の中を見てみると、xTimerHandle型になっている。
他にも TickType_t 型が portTickType 型だったりする。

NONOS環境での型名とのバッティングを避けるためなのか分からないが、これではFreeRTOSサポートとは言えない。

既存の資産を移植するようなプロジェクトにはラッパーが必要である。

ESP8266_RTOS_SDKやESP8266_NONOS_SDKのサンプルをコンパイルする

ESPRESSIFのサイトからSDK(ESP8266_RTOS_SDKやESP8266_NONOS_SDK)をダウンロードして解凍しただけでは、サンプルのコンパイルでエラーが発生したり、ライブラリのコンパイルでエラーが発生したりする。

  • NONOS_SDK環境では、プロジェクトをSDK直下に置かなければならない

例えば、expamples/IoT_Demo 直下で gen_misc.sh を実行してもコンパイルは行われない。IoT_Demo直下にあるMakefileの最終行に sinclude $(PDIR)Makefile と記述されており、SDK直下に存在する最上位のMakefileがインクルードされるためには、SDK直下にあるディレクトリでコンパイルを行う必要がある。
よって、下記のコマンドを実行しディレクトリごと1階層上に移動させる必要がある。

$ mv -r /IoT_DEMO ../

この問題はRTOS_SDKでは起きない。しかし一方で、gen_misc.sh 中に記述されているSDKのパスをコンパイル環境に合わせて書き換える必要がある。

  • RTOS環境でリンク時にROMに置かれている関数コールを解決できない

ROMのシンボル情報は下記の場所にあり、NONOS環境には全ての関数が列挙されているものの、RTOS環境にはRTOS固有と思われる関数しか記述されていない。

NONOS_SDKの /ld/eagle.rom.addr.v6.ld の情報を転記するか、各コンパイル環境直下にあるMakefileのDEPENDS_eagle.app.v6 にldファイルを追加する必要がある。

  • バグ

ESP8266_RTOS_SDK v1.5.0 は一部手を加えないとライブラリのコンパイルができない。

ESP8266開発環境の比較

ESP-WROOM-02(ESP8266)のソフト開発環境を比較してみた。

2017年4月27日現在

環境 概要 開発環境 費用 その他
arduino
Ver1.6.9
・必要とされる知識が少ない
・オブジェクト指向の実装が可能
・NONOSと同じマルチタスキング
Windows
Mac OS-X
Linux
フリー ・導入も簡単
・コンパイルに時間がかかる
ESP8266_NONOS_SDK
Ver.1.5.4
・上限3タスク※1のマルチタスク
・独自ソケットライブラリ
・JSON
Linux
Solaris
Windows※2
Mac OS-X※2
・コンパイルが速い
・SDKを解析して使うスキルが必要
          結構バグがある
・解凍しただけではサンプルのコンパイルさえ通らない
・英文マニュアルを読む必要がある
ESP8266_RTOS_SDK
Ver1.5.0
・freeRTOSによるマルチタスキング
TickTImeは10ms,変えられないことは無さそうだが、変えやすく作られていない。構造体の型がアレンジされている。
lwIPによるソケットをサポート
・JSON

※1 情報源=2C-ESP8266-SDK__API Guide__EN_V1.5.4.pdf
※2 VirtualBoxを利用

下に行くほど、高機能かつ知識が要求される。
C言語,Linux,マイコンの知見は必須。
やすらかシステムでは、イベントのスキャン,TCPコネクションの維持で2つのタスクを使っており、今後の機能追加時に上限3タスクを超える見込みであり、ESP8266_RTOS_SDKを選択する。