本文介绍编译3.x和2.3.0版本的C Link SDK时,可能遇到的问题和解决方法。
背景信息
如果您尚未接入物联网平台,推荐使用最新版本的SDK。更多信息,请参见概述。
SDK如何进行Make编译?
编写编译配置文件。
说明如果您的环境为Ubuntu或其他Linux发行版,可以先跳过这一步,直接使用SDK内置的配置文件。
参考文档示例编写配置文件。具体操作,请参见基于Make的交叉编译示例。
将配置文件保存在目录src/board下。
通过命令选择配置文件并使其生效。
在SDK根目录下,执行命令
make reconfig
。根据环境配置,输入所选文件config.***.***前的序号,再按回车键运行该文件。
在Ubuntu环境下,运行文件config.ubuntu.x86,日志信息如下所示:
$ make reconfig SELECT A CONFIGURATION: 1) config.esp8266.aos 4) config.mk3080.aos 7) config.win7.mingw32 2) config.macos.x86 5) config.rhino.make 8) config.xboard.make 3) config.mk3060.aos 6) config.ubuntu.x86 #? 6 SELECTED CONFIGURATION: VENDOR : ubuntu MODEL : x86 CONFIGURE .............................. [examples] CONFIGURE .............................. [src/infra/log] CONFIGURE .............................. [src/infra/system] CONFIGURE .............................. [src/infra/utils] CONFIGURE .............................. [src/protocol/alcs] CONFIGURE .............................. [src/protocol/coap/cloud] CONFIGURE .............................. [src/protocol/coap/local] CONFIGURE .............................. [src/protocol/http] CONFIGURE .............................. [src/protocol/http2] CONFIGURE .............................. [src/protocol/mqtt] CONFIGURE .............................. [src/ref-impl/hal] CONFIGURE .............................. [src/ref-impl/tls] CONFIGURE .............................. [src/sdk-impl] CONFIGURE .............................. [src/services/awss] CONFIGURE .............................. [src/services/dev_bind] CONFIGURE .............................. [src/services/http2_stream] CONFIGURE .............................. [src/services/linkkit/cm] CONFIGURE .............................. [src/services/linkkit/dev_reset] CONFIGURE .............................. [src/services/linkkit/dm] CONFIGURE .............................. [src/services/mdal/mal] CONFIGURE .............................. [src/services/mdal/sal] CONFIGURE .............................. [src/services/ota] CONFIGURE .............................. [src/services/shadow] CONFIGURE .............................. [src/services/subdev] CONFIGURE .............................. [src/tools/linkkit_tsl_convert] BUILDING WITH EXISTING CONFIGURATION: VENDOR : ubuntu MODEL : x86 Components: . examples . src/ref-impl/tls . src/ref-impl/hal . src/tools/linkkit_tsl_convert . src/protocol/mqtt . src/protocol/http . src/protocol/coap/local . src/protocol/coap/cloud . src/protocol/http2 . src/protocol/alcs . src/infra/system . src/infra/utils . src/infra/log . src/services/shadow . src/services/http2_stream . src/services/dev_bind . src/services/linkkit/cm . src/services/linkkit/dm . src/services/linkkit/dev_reset . src/services/subdev . src/services/mdal/mal . src/services/mdal/sal . src/services/ota . src/services/awss . src/sdk-impl
使用menuconfig工具配置选项。
在SDK根目录下,执行命令
make menuconfig
。在menuconfig工具窗口,根据业务需要,选中要配置的组件。
选择Save,保存配置。
按两次退出键,退出menuconfig工具。
在SDK根目录下,执行命令
make
,完成编译SDK代码。
编译成功后,会输出什么样的内容?
编译成功后,会打印类似如下的表格。内容包括每个模块的ROM、静态RAM等占用量的统计。
以下示例中的数据仅供参考,请以实际操作为准。
| RATE | MODULE NAME | ROM | RAM | BSS | DATA |
|-------|-------------------------------------|-----------|-----------|------------|--------|
| 27.5% | src/services/linkkit/dm | 58954 | 172 | 160 | 12 |
| 19.5% | src/protocol/alcs | 41961 | 213 | 189 | 24 |
| 11.3% | src/infra/utils | 24335 | 284 | 264 | 20 |
| 10.3% | src/services/awss | 22253 | 1012 | 1000 | 12 |
| 9.75% | src/protocol/mqtt | 20888 | 32 | 20 | 12 |
| 7.95% | src/services/linkkit/cm | 17026 | 79 | 79 | 0 |
| 4.46% | src/services/ota | 9563 | 0 | 0 | 0 |
| 4.10% | src/services/dev_bind | 8792 | 214 | 214 | 0 |
| 2.24% | src/infra/system | 4801 | 1480 | 1404 | 76 |
| 1.75% | src/sdk-impl | 3750 | 8 | 8 | 0 |
| 0.62% | src/infra/log | 1334 | 268 | 0 | 268 |
| 0.39% | src/services/dev_reset | 856 | 10 | 10 | 0 |
|-------|-------------------------------------|-----------|-----------|------------|--------|
| 100% | - IN TOTAL - | 214513 | 3772 | 3348 | 424 |
输出文件在哪个目录下?
编译完成后,输出文件在目录output/release下。
哪些输出文件是值得关注的?
以下目录中的这些输出文件值得关注。
output/release/lib
文件名
说明
libiot_hal.a
HAL接口层的参考实现。提供接口HAL_***()。
libiot_sdk.a
SDK的主库。提供接口IOT_***和linkkit_xxx()。
libiot_tls.a
裁剪过的Mbed TLS。提供接口mbedtls_***(),支撑libiot_hal.a。
output/release/include
文件名
说明
iot_import.h
所有需开发者提供给SDK的底层支撑接口。
iot_export.h
所有SDK向开发者提供的底层编程接口。
output/release/bin
文件名
说明
linkkit-example-solo
高级例程。可演示
linkkit_***()
接口的使用。mqtt-example
基础例程。可演示
IOT_***()
接口的使用。
如何设置交叉编译的Toolchain?
设置交叉编译的Toolchain方法有两种:
单独设置Toolchain的前缀。
单独设置某个工具的前缀。
打开编译配置文件src/borad/config.***.***,按照下面两种方法修改或添加Toolchain。
# 以arm-none-eabi-为例
# 方法1: 设置Toolchian前缀
CROSS_PREFIX := arm-none-eabi-
# 方法2: 单独设置某个工具链
OVERRIDE_CC := arm-none-eabi-gcc
OVERRIDE_LD := arm-none-eabi-ld
OVERRIDE_AR := arm-none-eabi-ar
OVERRIDE_STRIP := arm-none-eabi-strip
# 注:当交叉工具链没有共有的前缀或者前缀不符合prefix+gcc|ar|strip类型时, 可用如下代码单独指定strip程序不执行,例如armcc没有对应的strip程序
OVERRIDE_STRIP = true
如何添加编译和连接选项?
打开编译配置文件src/borad/config.***.***,分别在CONFIG_ENV_CFLAGS和CONFIG_ENV_LDFLAGS中添加您的编译选项。添加完毕后,运行make reconfig
使配置文件生效。
如何编译动态库?
在文件src/borad/config.***.***中,添加CONFIG_LIB_EXPORT := dynamic
配置选项。添加完毕后,执行make all
命令,进行编译。在目录output/release/lib/下查看动态库。
menuconfig配置保存后,重新进入时,为何仍是默认的选项?
menuconfig每次运行均展示默认配置。若需查看末次配置的具体信息,请使用Load功能,加载已保存的配置文件。
重新配置已保存的menuconfig配置文件,无法加载,该如何自查?
默认名称的配置文件会被清除,请检查保存的配置文件的名称。确保配置文件的名称已修改,且加载的配置文件名称和所在目录是正确的。
如何在配置文件中修改SDK的配置?
在SDK文件src/board/config.***.***中,以CONFIG_ENV_CFLAGS += -D*****
的语法新增自定义CFLAGS。其中*****
代表具体的宏名称,覆盖SDK中默认的可配置参数。
以下示例代码,在config.***.***文件中,增加参数的定义,配置MQTT的接收Buffer参数等。
CONFIG_ENV_CFLAGS += \
-DCONFIG_MQTT_RX_MAXLEN=5000 \
-DCONFIG_MBEDTLS_DEBUG_LEVEL=0 \
menuconfig出现错误时,常见自查方法有哪些?
2.3.0版本的SDK仅支持Linux环境下进行menuconfig;3.x版本支持Linux、Mac和Windows环境下进行menuconfig。
Windows环境:
执行
config.bat
脚本。Ubuntu 16.04桌面环境:
请检查并确认您的环境。更多信息,请参见安装本地开发环境。
请检查终端窗口的大小。
其他Linux环境:
请检查您的权限。在Windows环境下解压的文件上传至Linux,可能导致工具出现权限问题。建议在Linux环境,直接下载并解压源码包。
请检查环境变量。您可以通过以下命令,临时添加这两个环境变量。
export TERMINFO=/usr/share/terminfo export TERM=xterm-basic
在非Linux环境下,menuconfig工具目前不支持SDK 2.3.0版本。请直接修改make.settings对应的选项,完成配置。
如何让编译系统屏蔽编译指定模块?
在交叉编译的移植过程中,通常需要手动先屏蔽一些目录不编译。
以目录examples/和HAL默认实现的目录为例,可以在文件src/borad/config.***.***中,增加格式为CONFIG_*****:=
的代码来屏蔽相应的目录。其中*****
代表相对SDK根目录的路径。
下面是屏蔽目录src/ref-impl/tls/ 、src/ref-impl/hal/、examples/、src/tools/linkkit_tsl_convert/下模块的示例代码。
CONFIG_src/ref-impl/tls :=
CONFIG_src/ref-impl/hal :=
CONFIG_examples :=
CONFIG_src/tools/linkkit_tsl_convert :=
如何通过代码提取功能,从云端下载代码?
为了提高提取代码的速度,SDK脚本默认会根据配置从云端获取代码。若希望在本地代码基础上进行抽取或裁剪,方法如下:
Linux或Mac:
在Link SDK根目录下,执行以下命令:
cd c-sdk ./extract.sh local
Windows:
打开./config.bat文件,将运行脚本代码
"%SHELL%" extract.sh
修改为"%SHELL%" extract.sh local
。双击执行./config.bat。
3.x版本的SDK如何打开日志功能?
3.x版本的SDK默认关闭了日志功能。在编译前,您可以通过不选中Log Configurations
配置项中的以下设置,打开日志功能。
为何设备断电20分钟后,云端才显示离线?
默认情况下,通过配置项CORE_MQTT_DEFAULT_KEEPALIVE_S,Link SDK的云端心跳值为1200s,即20分钟。如果您需要修改心跳间隔时间,可在应用层设置MQTT的配置项,示例代码如下:
uint16_t keepalive = 60;//数据类型: (uint16_t *) 取值范围: 30 ~ 1200s 默认值: 1200s
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_KEEPALIVE_SEC, &keepalive);
如何设置MQTT连接的配置项?
您可以调用aiot_mqtt_setopt,设置配置项参数。更多信息,请参见aiot_mqtt_option_t。
如果在上述信息中,您未找到要设置的配置项,您可以在/core/utils/core_mqtt.h中,找到SDK的默认配置项。
请勿随意更改配置项的值。
/* default configuration */
#define CORE_MQTT_MODULE_NAME "MQTT"
#define CORE_MQTT_DEINIT_INTERVAL_MS (100)
#define CORE_MQTT_DEFAULT_KEEPALIVE_S (1200)
#define CORE_MQTT_DEFAULT_CLEAN_SESSION (1)
#define CORE_MQTT_DEFAULT_CONNECT_TIMEOUT_MS (10 * 1000)
#define CORE_MQTT_DEFAULT_HEARTBEAT_INTERVAL_MS (25 * 1000)
#define CORE_MQTT_DEFAULT_HEARTBEAT_MAX_LOST_TIMES (2)
#define CORE_MQTT_DEFAULT_SEND_TIMEOUT_MS (5 * 1000)
#define CORE_MQTT_DEFAULT_RECV_TIMEOUT_MS (5 * 1000)
#define CORE_MQTT_DEFAULT_REPUB_TIMEOUT_MS (3 * 1000)
#define CORE_MQTT_DEFAULT_RECONN_ENABLED (1)
#define CORE_MQTT_DEFAULT_RECONN_INTERVAL_MS (2 * 1000)
#define CORE_MQTT_DEFAULT_RECONN_RANDLIMIT_MS (1 * 1000)
#define CORE_MQTT_DEFAULT_RECONN_MAX_COUNTERS (60) /*mqtt 断线重连退避算法的最大计数*/
#define CORE_MQTT_DEFAULT_DEINIT_TIMEOUT_MS (2 * 1000)
#define CORE_MQTT_DIAG_TLV_MQTT_CONNECTION (0x0010)
#define CORE_MQTT_DIAG_TLV_MQTT_HEARTBEAT (0x0020)
#define CORE_MQTT_NWKSTATS_RTT_THRESHOLD (10000)
/* default settings for mqtt 5.0 */
#define CORE_TX_PKT_MAX_LENGTH (1024 * 256)
#define CORE_DEFAULT_SERVER_RECEIVE_MAX (10)
#define CORE_MQTT_USER_PROPERTY_KEY_MAX_LEN (128) /* max key length for user property */
#define CORE_MQTT_USER_PROPERTY_VALUE_MAX_LEN (128) /* max value length for user property */
如何使用Username和Password实现MQTT连云
在一型一密接入方式中,其中免预注册的方式(即设备首次连接物联网平台时,平台自动创建设备身份并下发密钥给设备) 下发的密钥不是Produckey、DeviceName、DeviceSecret,而是ClientId、Username、Password。
对于这种情况,LinkSDK 4.x提供了三个设置选项供设备接入,分别是:AIOT_MQTTOPT_USERNAME
, AIOT_MQTTOPT_PASSWORD
, AIOT_MQTTOPT_CLIENTID
。
示例代码如下:
char *user_name = "demo_user_name";
char *password = "demo_passwd";
char *client_id = "demo_client_id";
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_USERNAME, user_name);
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PASSWORD, password);
aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_CLIENTID, client_id);
用户再调用aiot_mqtt_connect就可将设备连接至物联网平台。