本文介绍如何在ESP8266开发板上移植C-SDK4.0,并用demo连接至阿里云物联网平台。

准备工作

为完成实践,您需要准备:

  • 开发板。本文使用的开发板为ESP-LAUNCHER, 即官方提供的ESP8266EX_Demo_Board。
  • USB连接线。
  • 运行Windows,Linux或者macOS的计算机。使用的主机开发平台为macOS。
说明 其他系统的用户也可以参考乐鑫提供的入门教程完成开发环境搭建。

搭建开发环境

说明 下面的开发环境的搭建、ESP8266是否工作正常的描述仅供参考,如果用户在使用过程中遇到问题,请联系开发板的供货商进行咨询与问题解决。

建议用户先阅读乐鑫SDK Readme以加快开发环境搭建,下面关于macOS环境搭建请参见以下步骤:

  1. 安装必要的软件

    执行sudo easy_install pip安装pip。

    执行sudo pip install pyserial安装pyserial。

  2. 克隆esp-idf官方仓库执行脚本如下所见:
    cd ~
    mkdir esp && cd esp
    git clone https://github.com/espressif/ESP8266_RTOS_SDK.git -b release/v3.3

    下载完成后需要执行脚本export IDF_PATH=~/esp/ESP8266_RTOS_SDK配置idf sdk路径。

    说明
    • 本次移植演示使用release/v3.3分支,对应commit id为fd785ab0c50009ab93503ae785814136f6d1009b
    • ESP8266_RTOS_SDK在v3.0之后的版本已做了esp-idf框架的改造,对于v3.0之前的非esp-idf框架版本,用户可自行调整并参见此教程完成对接。
  3. 安装工具链和编译工具

    手动下载macOS工具链, 将工具链解压存放在~/esp目录下:

    mkdir -p ~/esp
    cd ~/esp
    tar -xzf ~/Downloads/xtensa-lx106-elf-macos-1.22.0-100-ge567ec7-5.2.0.tar.gz

    其他平台的工具链可在ESP8266 SDK GitHub页面获取。

    配置工具链系统路径:

    export PATH=$PATH:$HOME/esp/xtensa-lx106-elf/bin

    用户可参见以下脚本在$HOME/.bash_profile中添加所有环境变量的配置:

    set_esp8266 ()
    {
        exprot IDF_PATH=$HOME/esp/ESP8266_RTOS_SDK
        export PATH=$PATH:$HOME/esp/xtensa-lx106-elf/bin
    }
  4. 连接开发板

    获取串口端口名,macOS可使用ls /dev/cu.*命令查询,本演示中的串口端口名为/dev/cu.usbserial-AH06UHLH

  5. 配置项目、编译、烧写和串口监视

    1. 所有配置必须在项目路径下完成,所以先执行脚本cd examples/wifi/simple_wifi/进入到examples/wifi/simple_wifi/目录中。
    2. esp-idf使用make menuconfig进行项目配置, 详情请参见下方移植思路。
    3. 配置完成后运行make all编译固件。
    4. 编译完成后运行make flash命令烧写固件(请确保开发板已进入下载模式)。
    5. 烧写成功后运行make monitor打开串口打印信息监视器(请确保开发板已进入工作模式)。

    至此,用户已经完成了ESP8266开发环境的搭建,并完成了wifi station例程的编译烧写。

    说明 请确保开发板已工作正常再进行下面的步骤。
  6. 移植C-SDK4.0

    移植C-SDK的过程主要包括了SDK代码的导入,SDK port层文件配置和编译系统的配置。

    SDK的portfiles目录已经包含了ESP8266的portfile,因此用户只需要导入SDK源码,配置编译系统即可完成移植工作。

    建议提前阅读idf的编译系统介绍以理解移植过程。用户需要先了解idf的一些基本概念:

    • project:项目目录,仅包含了所有用于构建app的源文件和配置文件。
    • components:功能独立的模块化代码, 将会编译成.a静态库并链接到APP,这些模块化的组件存放在idf的components目录下,用户可以添加自定义component。

    ESP8266-sdk的编译系统默认使用GUN make,我们只需移入C-SDK代码, 编写C-SDK对应的.mk编译配置文件即可将C-SDK加入编译。

移植思路

移植思路有以下两种:

  • 方法一: 在project目录中引入C-SDK,将SDK源码与用户app源码共同编译。
  • 方法二: 将C-SDK作为idf自定义组件引入到idf的components目录中。

我们推荐用第二种方法, 将C-SDK作为独立组件有助于在不同项目中复用,并解除与用户app代码的耦合。主要的步骤如下:

  1. 添加C-SDK自定义组件

    • 获取SDK
    • 用户需要下载附件posix_port.c(适配了esp8266), 用它将LinkSDK中portfiles/aiot_port/posix_port.c替换掉。
    • LinkSDK与idf中都有mbedtls库,避免引用库冲突,修改文件$IDF_PATH/components/C-SDK/core/sysdep/core_adapter.c, 关闭CORE_ADAPTER_MBEDTLS_ENABLED宏定义。
    • 将SDK复制到$IDF_PATH/components目录下, 在SDK目录下添加构建文件component.mk,文件内容如下所见:
      COMPONENT_ADD_INCLUDEDIRS := core core/sysdep core/utils components/ota
      
      COMPONENT_SRCDIRS := core core/utils core/sysdep components/ota portfiles/aiot_port/ external
  2. 移植demo程序

    我们通过修改examples/wifi/simple_wifi/下的example来完成mqtt上云的演示。

    原生的例程主要演示使用wifi station模式接入特定的wifi热点, 用户可下载附件源文件覆盖原有的simple_wifi.c

  3. 项目配置、编译和烧写

    进入examples/wifi/simple_wifi/项目路径, 运行make menuconfig配置项目, 主要配置如下

    1. 进入SDK tool configuration菜单,确保Compiler toolchain path/prefix正确配合为xtensa-lx106-elf-
    2. 进入Serial flasher config菜单, 修改ESP8266开发板的默认串口端口名。
    3. 进入Example Configuration菜单, 配置使用Station模式,配置WiFi SSID/Password和最大重连次数。
    4. 调整主程序栈空间大小,进入Component config菜单的ESP8266-specific子菜单,将Main task stack size配置为4096,保存并退出配置。

    MBEDTLS配置

    若用户要使用PSK作为TLS密钥交换方法, 则需要

    1. 进入Component config菜单的mbedTLS子菜单, 进入TLS Key Exchange Methods配置项。
    2. 打开Enable pre-shared-key ciphersuites开关。
    3. 同时在mbedtls组件的component.mk中添加CFLAGS += -DMBEDTLS_PSK_MAX_LEN=64

    如下所示:

    COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include port/esp8266/include
    
    COMPONENT_SRCDIRS := mbedtls/library port port/esp8266
    
    COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o
    
    COMPONENT_SUBMODULES += mbedtls
    
    CFLAGS += -DMBEDTLS_PSK_MAX_LEN=64

    配置完成后,运行make allmake flash完成编译和烧写。

  4. 运行和日志信息

    运行make monitor打开串口监视器,重启设备可以查看到以下日志:

    ......
    I (274) esp_image: segment 1: paddr=0x00073818 vaddr=0x40273810 size=0x0e5fc ( 58876) map
    I (300) esp_image: segment 2: paddr=0x00081e1c vaddr=0x3ffe8000 size=0x00a3c (  2620) load
    I (301) esp_image: segment 3: paddr=0x00082860 vaddr=0x40100000 size=0x00a50 (  2640) load
    I (308) esp_image: segment 4: paddr=0x000832b8 vaddr=0x40100a50 size=0x05854 ( 22612) load
    I (325) boot: Loaded app from partition at offset 0x10000
    I (349) system_api: Base MAC address is not set, read default base MAC address from EFUSE
    I (359) system_api: Base MAC address is not set, read default base MAC address from EFUSE
    phy_version: 1155.0, 6cb3053, Nov 11 2019, 17:31:08, RTOS new
    I (413) phy_init: phy ver: 1155_0
    I (418) reset_reason: RTC reset 1 wakeup 0 store 0, reason is 1
    I (425) simple wifi: ESP_WIFI_MODE_STA
    I (473) simple wifi: wifi_init_sta finished.
    I (479) simple wifi: connect to ap SSID:C_SDK_Test password:1234abcd
    I (614) wifi: state: 0 -> 2 (b0)
    I (659) wifi: state: 2 -> 3 (0)
    I (671) wifi: state: 3 -> 5 (10)
    I (676) wifi: pm start, type: 2
    I (2320) event: sta ip: 192.168.0.101, mask: 255.255.255.0, gw: 192.168.0.1
    I (2329) simple wifi: got ip:192.168.0.101
    I (2334) simple wifi: connected to ap SSID:C_SDK_Test password:1234abcd
    I (2342) simple wifi: Start linkkit main
    [1.990][LK-0313] MQTT user calls aiot_mqtt_connect api, connect
    [2.000][LK-0317] mqtt_basic_demo&a13FNXXXXXX
    [2.000][LK-0318] 4780A5F17990D8DC4CCAD392683ED80160C4C2A1FFA649425CD0E2666A8593EB
    [2.010][LK-0319] a13FNXXXXXX.mqtt_basic_demo|timestamp=2524608000000,_ss=1,_v=sdk-c-4.0.0,securemode=2,signmethod=hmacsha256,ext=1,|
    [2.020][LK-031A] devicename|hmacsha256|a13FNXXXXXX&mqtt_basic_demo|2524608000000
    [2.020][LK-031A] 3A27B38E1BAB95462F8EA659C15EE26319286EB1CB7B372451EE82A30A9E7FDF
    establish mbedtls connection with server(host='a13FNXXXXXX.itls.cn-shanghai.aliyuncs.com', port=[1883])
    [2.450][LK-0313] MQTT connect success in 460 ms
    AIOT_MQTTEVT_CONNECT
    [2.450][LK-0309] sub: /sys/a13FNXXXXXX/mqtt_basic_demo/thing/event/+/post_reply
    [2.460][LK-0309] pub: /sys/a13FNXXXXXX/mqtt_basic_demo/thing/event/property/post
    
    [LK-030A] > 7B 22 69 64 22 3A 22 31  22 2C 22 76 65 72 73 69 | {"id":"1","versi
    [LK-030A] > 6F 6E 22 3A 22 31 2E 30  22 2C 22 70 61 72 61 6D | on":"1.0","param
    [LK-030A] > 73 22 3A 7B 22 4C 69 67  68 74 53 77 69 74 63 68 | s":{"LightSwitch
    [LK-030A] > 22 3A 30 7D 7D                                   | ":0}}
    
    suback, res: -0x0000, packet id: 1, max qos: 1
    [2.530][LK-0309] pub: /sys/a13FNXXXXXX/mqtt_basic_demo/thing/event/property/post_reply
    
    [LK-030A] < 7B 22 63 6F 64 65 22 3A  32 30 30 2C 22 64 61 74 | {"code":200,"dat
    [LK-030A] < 61 22 3A 7B 7D 2C 22 69  64 22 3A 22 31 22 2C 22 | a":{},"id":"1","
    [LK-030A] < 6D 65 73 73 61 67 65 22  3A 22 73 75 63 63 65 73 | message":"succes
    [LK-030A] < 73 22 2C 22 6D 65 74 68  6F 64 22 3A 22 74 68 69 | s","method":"thi
    [LK-030A] < 6E 67 2E 65 76 65 6E 74  2E 70 72 6F 70 65 72 74 | ng.event.propert
    [LK-030A] < 79 2E 70 6F 73 74 22 2C  22 76 65 72 73 69 6F 6E | y.post","version
    [LK-030A] < 22 3A 22 31 2E 30 22 7D                          | ":"1.0"}
    
    pub, qos: 0, topic: /sys/a13FNXXXXXX/mqtt_basic_demo/thing/event/property/post_reply
    pub, payload: {"code":200,"data":{},"id":"1","message":"success","method":"thing.event.property.post","version":"1.0"}
    heartbeat response
    heartbeat response
    heartbeat response
    ......

    日志说明

    • I (2342) simple wifi: Start linkkit main为demo中添加的,用于标识C-SDK开始工作的日志信息。
    • 包含[LK-XXXX]的日志由C-SDK提供, 其中[2.450][LK-0313] MQTT connect success in 460 ms表示MQTT建连成功,同时输出了建连用时。