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

为了完成移植实践, 您需要:

  • 一块搭载esp8266的开发板
  • USB连接线
  • 运行Windows, Linux或者MacOS的计算机

本实践使用的开发板为ESP-LAUNCHER, 即官方提供的ESP8266EX_Demo_Board.

使用的主机开发平台为MacOS, 使用其他系统的用户也可以参考官方入门教程完成开发环境搭建

搭建开发环境

建议用户先阅读乐鑫SDK Readme以加快开发环境搭建, 下面对MacOS环境搭建的相关步骤做简要说明

1. 安装必要的软件

安装pip

sudo easy_install pip

安装pyserial

sudo pip install pyserial

2. 克隆esp-idf官方仓库

cd ~
mkdir esp && cd esp
git clone git@github.com:espressif/ESP8266_RTOS_SDK.git -b release/v3.3

本次移植演示使用release/v3.3分支, 对应commit id为fd785ab0c50009ab93503ae785814136f6d1009b

esp8266 RTOS sdk在v3.0之后的版本做了esp-idf框架的改造, 对于v3.0之前的非esp-idf框架版本, 用户可对照此教程自行对接

下载完成后需要配置idf sdk路径

export IDF_PATH=~/esp/ESP8266_RTOS_SDK

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. 连接开发板

  • 安装USB驱动, ESP-LAUNCHER所需的串口驱动可以从FTDI获取
  • 获取串口端口名, MacOS可使用ls /dev/cu.*命令查询, 本演示中的串口端口名为/dev/cu.usbserial-AH06UHLH

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

  • 所有配置必须在项目路径下完成, 所以先cd到examples/wifi/simple_wifi/项目路径
  • esp-idf使用make menuconfig进行项目配置, 在SDK移植章节我们将介绍一些必要的配置
  • 配置完成后运行make all编译固件
  • 编译完成后运行make flash命令烧写固件(请确保开发板已进入下载模式)
  • 烧写成功后运行make monitor打开串口打印信息监视器(请确保开发板已进入工作模式)

至此, 用户已经完成了esp8266开发环境的搭建, 并完成了wifi station例程的编译烧写, 下面我们将介绍如何移植C-SDK4.0, 并成功连接阿里云物联网平台

移植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自定义组件

下载C-SDK4.0, 将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/freertos_port/ external

说明:

组件目录portfiles/freertos_port中的freertos_port.c为sdk针对esp-idf的移植层文件, 它实现C-SDK与esp-idf框架和mbedtls的对接

2. 移植demo程序

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

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

附件: simple_wifi.c

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

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

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

MBEDTLS配置:

  • 若用户要使用PSK作为TLS秘钥交换方法, 则需要
  • 进入Component config菜单的mbedTLS子菜单, 进入TLS Key Exchange Methods配置项
  • 打开Enable pre-shared-key ciphersuites开关
  • 同时在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 all, make 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&a13FN5TplKq
[2.000][LK-0318] 4780A5F17990D8DC4CCAD392683ED80160C4C2A1FFA649425CD0E2666A8593EB
[2.010][LK-0319] a13FN5TplKq.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|a13FN5TplKq&mqtt_basic_demo|2524608000000
[2.020][LK-031A] 3A27B38E1BAB95462F8EA659C15EE26319286EB1CB7B372451EE82A30A9E7FDF
establish mbedtls connection with server(host='a13FN5TplKq.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/a13FN5TplKq/mqtt_basic_demo/thing/event/+/post_reply
[2.460][LK-0309] pub: /sys/a13FN5TplKq/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/a13FN5TplKq/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/a13FN5TplKq/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建连成功, 同时输出了建连用时