全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 钉钉智能硬件
阿里云物联网套件

华东2

更新时间:2017-11-30 14:00:30

以下描述如何将华东2节点设备端V2.0+版本C-SDK移植到目标硬件平台.

详细技术文档请访问官方WiKi

IoT套件后续会逐渐增加已适配的平台, 如果您使用的平台未被适配, 请访问官方Github, 给我们提出Issue

V2.0+设备端C-SDK概述

  1. +---------------------------+ +---------------------------+
  2. | | | | => 构建完成后产生:
  3. | IoT SDK Example Program | | sample/mqtt|coap|ota/*.c |
  4. | | | | output/release/bin/*-example
  5. +---------------------------+ +---------------------------+
  6. | | | | => SDK提供功能的API, 都在这里声明
  7. | IoT SDK Interface Layer | | src/sdk-impl/iot_export.h | => 构建完成后产生:
  8. | | | |
  9. | IOT_XXX_YYY() APIs | | Has all APIs' prototype | output/release/include/
  10. | | | | iot-sdk/iot_export.h
  11. | | | | iot-sdk/exports/*.h
  12. +---------------------------+ +---------------------------+
  13. | | | | => SDK提供功能的API, 都在这里实现
  14. | | | src/utils: utilities | => 构建完成后产生:
  15. | | +---> | src/log: logging |
  16. | | | src/tls: security |
  17. | IoT SDK Core Implements | | src/guider: authenticate | output/release/lib/
  18. | : => | <---+ | src/system: device mgmt | libiot_sdk.a
  19. | : You SHOULD NOT Focus | | src/mqtt: MQTT client |
  20. | : on this unless | | src/coap: CoAP client |
  21. | : you're debugging bugs | | src/http: HTTP client |
  22. | | | src/shadow: device shadow |
  23. | | | src/ota: OTA channel |
  24. | | | |
  25. +---------------------------+ +---------------------------+
  26. | | | | => SDK仅含有示例代码, 移植时需二次开发
  27. | Hardware Abstract Layer | | src/sdk-impl/iot_import.h | => 构建完成后产生:
  28. | | | : => |
  29. | HAL_XXX_YYY() APIs | | : HAL_*() declarations | output/release/lib/
  30. | | | | libiot_platform.a
  31. | : You MUST Implement | | src/platform/*/*/*.c | output/release/include/
  32. | : this part for your | | : => | iot-sdk/iot_import.h
  33. | : target device first | | : HAL_*() example impls | iot-sdk/imports/*.h
  34. +---------------------------+ +---------------------------+

2.0版本相对1.0.1版本在结构性方面, 升级了编译系统, 支持后续功能模块的灵活迭代和裁剪, 但是在代码架构方面, 和1.0.1版本保持恒定, 也是分为三层的, 如上图

  • 最底层称为”硬件平台抽象层”, 也简称HAL层, 对应上图的 Hardware Abstract Layer

    • 这里是抽象不同的嵌入式目标板上操作系统对我们SDK的支撑函数
    • 举例来说, 包括网络收发, TLS/DTLS通道建立和读写, 内存申请是否, 互斥量加锁解锁等
    • 注意: 在任何跨平台移植时, 实现这部分是需要完成的第一步工作
    • 注意: 阿里的SDK里, 并不含有多平台的HAL层实现, 但我们提供了Linux桌面OS(Ubuntu16.04)上的参考实现, 移植时可以作为参考
  • 中间层称为”SDK内核实现层”, 对应上图的 IoT SDK Core Implements

    • 这里是IoT套件C-SDK的核心实现部分, 它基于HAL层接口完成了MQTT/CoAP通道等的功能封装
    • 举例来说, 包括MQTT的连接建立, 报文收发, CoAP的连接建立, 报文收发, OTA的固件状态查询, OTA的固件下载等
    • 注意: 如果HAL层实现的好, 这一层在跨平台移植时, 理想情况不需要做任何修改
  • 最上层称为”SDK接口声明层”, 对应上图的 IoT SDK Interface Layer

    • 这里没有实现, 只有一系列C函数的原型声明, 也就是SDK跨平台移植完成之后, 可以用于编写业务逻辑, 和阿里云服务器通信的API
    • 举例来说, 怎么去使用这些API做业务逻辑, 我们在sample目录提供了丰富的示例程序, 并且只要填入了设备信息, 就可以在Linux主机上运行体验

以下按照从下到上的顺序, 逐个对每个层次做更加详细的说明

硬件平台抽象层(HAL层)

  • 所有HAL层函数的声明都在 src/sdk-impl/iot_import.h 这个头文件中列出
  • 各功能点引入的HAL层接口依赖在src/sdk-impl/imports/iot_import_*.h中列出
  • 这些imports目录下的子文件, 都被src/sdk-impl/iot_import.h包含
  • 在V2.0+版本的编译系统中, 这个部分会被编译成output/release/lib/libiot_platform.a

以下可以列出所有跨平台移植时需要实现的HAL层接口

  1. src/sdk-impl$ grep -ro "HAL_[_A-Za-z0-9]*" *|cut -d':' -f2|sort -u|cat -n
  2. 1 HAL_DTLSSession_create
  3. 2 HAL_DTLSSession_free
  4. 3 HAL_DTLSSession_read
  5. 4 HAL_DTLSSession_write
  6. 5 HAL_Free
  7. 6 HAL_GetModuleID
  8. 7 HAL_GetPartnerID
  9. 8 HAL_Malloc
  10. 9 HAL_MutexCreate
  11. 10 HAL_MutexDestroy
  12. 11 HAL_MutexLock
  13. 12 HAL_MutexUnlock
  14. 13 HAL_Printf
  15. 14 HAL_Random
  16. 15 HAL_SleepMs
  17. 16 HAL_Snprintf
  18. 17 HAL_Srandom
  19. 18 HAL_SSL_Destroy
  20. 19 HAL_SSL_Establish
  21. 20 HAL_SSL_Read
  22. 21 HAL_SSL_Write
  23. 22 HAL_TCP_Destroy
  24. 23 HAL_TCP_Establish
  25. 24 HAL_TCP_Read
  26. 25 HAL_TCP_Write
  27. 26 HAL_UDP_close
  28. 27 HAL_UDP_create
  29. 28 HAL_UDP_read
  30. 29 HAL_UDP_readTimeout
  31. 30 HAL_UDP_write
  32. 31 HAL_UptimeMs
  33. 32 HAL_Vsnprintf

对这些函数做实现的时候, 可以参考src/platform下已经写好的示例, 这些示例在Ubuntu16.04主机和Win7主机上被完善的编写和测试过

  1. src/platform$ tree
  2. .
  3. +-- iot.mk
  4. +-- os
  5. | +-- linux
  6. | | +-- HAL_OS_linux.c
  7. | | +-- HAL_TCP_linux.c
  8. | | +-- HAL_UDP_linux.c
  9. | +-- ubuntu -> linux
  10. | +-- win7
  11. | +-- HAL_OS_win7.c
  12. | +-- HAL_TCP_win7.c
  13. +-- ssl
  14. +-- mbedtls
  15. | +-- HAL_DTLS_mbedtls.c
  16. | +-- HAL_TLS_mbedtls.c
  17. +-- openssl
  18. +-- HAL_TLS_openssl.c

以下是这些函数的一个说明表格, 更多详细信息, 请查阅代码中的注释, 或关注官方WiKi

函数名 说明
HAL_DTLSSession_create 初始化DTLS资源并建立一个DTLS会话, 用于CoAP功能
HAL_DTLSSession_free 销毁一个DTLS会话并释放DTLS资源, 用于CoAP功能
HAL_DTLSSession_read 从DTLS会话中读数据, 用于CoAP功能
HAL_DTLSSession_write 向DTLS会话中写数据, 用于CoAP功能
HAL_Free 释放一片堆上内存
HAL_GetModuleID 用于紧密合作伙伴, 一般客户只需要在此可实现为空函数
HAL_GetPartnerID 用于紧密合作伙伴, 一般客户只需要在此可实现为空函数
HAL_Malloc 申请一片堆上内存
HAL_MutexCreate 创建一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_MutexDestroy 销毁一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_MutexLock 加锁一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_MutexUnlock 解锁一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_Printf 打印函数, 用于向串口或其它标准输出打印日志或调试信息
HAL_Random 随机数函数, 接受一个无符号数作为范围, 返回0到该数值范围内的随机无符号数
HAL_SleepMs 睡眠函数, 使当前执行线程睡眠指定的毫秒数
HAL_Snprintf 打印函数, 向内存缓冲区格式化构建一个字符串, 参考C99标准库函数snprintf
HAL_Srandom 随机数播种函数, 使HAL_Random的返回值每个执行序列各不相同, 类似srand
HAL_SSL_Destroy 销毁一个TLS连接, 用于MQTT功能, HTTPS功能
HAL_SSL_Establish 建立一个TLS连接, 用于MQTT功能, HTTPS功能
HAL_SSL_Read 从一个TLS连接中读数据, 用于MQTT功能, HTTPS功能
HAL_SSL_Write 向一个TLS连接中写数据, 用于MQTT功能, HTTPS功能
HAL_TCP_Destroy 销毁一个TLS连接, 用于MQTT功能, HTTPS功能
HAL_TCP_Establish 建立一个TCP连接, 包含了域名解析的动作和TCP连接的建立
HAL_TCP_Read 在指定时间内, 从TCP连接读取流数据, 并返回读到的字节数
HAL_TCP_Write 在指定时间内, 向TCP连接发送流数据, 并返回发送的字节数
HAL_UDP_close 关闭一个UDP socket
HAL_UDP_create 创建一个UDP socket
HAL_UDP_read 阻塞的从一个UDP socket中读取数据包, 并返回读到的字节数
HAL_UDP_readTimeout 在指定时间内, 从一个UDP socket中读取数据包, 返回读到的字节数
HAL_UDP_write 阻塞的向一个UDP socket中发送数据包, 并返回发送的字节数
HAL_UptimeMs 时钟函数, 获取本设备从加电以来到目前时间点已经过去的毫秒数
HAL_Vsnprintf 字符串打印函数, 将va_list类型的变量, 打印到指定目标字符串

在这些HAL接口中

必选实现

函数名 说明
HAL_Malloc 申请一片堆上内存
HAL_Free 释放一片堆上内存
HAL_SleepMs 睡眠函数, 使当前执行线程睡眠指定的毫秒数
HAL_Snprintf 打印函数, 向内存缓冲区格式化构建一个字符串, 参考C99标准库函数snprintf
HAL_Printf 打印函数, 用于向串口或其它标准输出打印日志或调试信息
HAL_Vsnprintf 字符串打印函数, 将va_list类型的变量, 打印到指定目标字符串
HAL_UptimeMs 时钟函数, 获取本设备从加电以来到目前时间点已经过去的毫秒数

可实现为空

函数名 说明
HAL_GetPartnerID 用于紧密合作伙伴, 一般客户只需要在此可实现为空函数
HAL_GetModuleID 用于紧密合作伙伴, 一般客户只需要在此可实现为空函数
HAL_MutexCreate 创建一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_MutexDestroy 销毁一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_MutexLock 加锁一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数
HAL_MutexUnlock 解锁一个互斥量, 用于同步控制, 目前SDK仅支持单线程应用, 可实现为空函数

没有MQTT时可实现为空

函数名 说明
HAL_SSL_Destroy 销毁一个TLS连接, 用于MQTT功能, HTTPS功能
HAL_SSL_Establish 建立一个TLS连接, 用于MQTT功能, HTTPS功能
HAL_SSL_Read 从一个TLS连接中读数据, 用于MQTT功能, HTTPS功能
HAL_SSL_Write 向一个TLS连接中写数据, 用于MQTT功能, HTTPS功能
HAL_TCP_Destroy 销毁一个TLS连接, 用于MQTT功能, HTTPS功能
HAL_TCP_Establish 建立一个TCP连接, 包含了域名解析的动作和TCP连接的建立
HAL_TCP_Read 在指定时间内, 从TCP连接读取流数据, 并返回读到的字节数
HAL_TCP_Write 在指定时间内, 向TCP连接发送流数据, 并返回发送的字节数
HAL_Random 随机数函数, 接受一个无符号数作为范围, 返回0到该数值范围内的随机无符号数
HAL_Srandom 随机数播种函数, 使HAL_Random的返回值每个执行序列各不相同, 类似srand

没有CoAP时可实现为空

函数名 说明
HAL_DTLSSession_create 初始化DTLS资源并建立一个DTLS会话, 用于CoAP功能
HAL_DTLSSession_free 销毁一个DTLS会话并释放DTLS资源, 用于CoAP功能
HAL_DTLSSession_read 从DTLS连接中读数据, 用于CoAP功能
HAL_DTLSSession_write 向DTLS连接中写数据, 用于CoAP功能

没有ID2时可实现为空

函数名 说明
HAL_UDP_close 关闭一个UDP socket
HAL_UDP_create 创建一个UDP socket
HAL_UDP_read 阻塞的从一个UDP socket中读取数据包, 并返回读到的字节数
HAL_UDP_readTimeout 在指定时间内, 从一个UDP socket中读取数据包, 返回读到的字节数
HAL_UDP_write 阻塞的向一个UDP socket中发送数据包, 并返回发送的字节数

SDK内核实现层

  • 所有被提供的函数的声明都在 src/sdk-impl/iot_export.h 这个头文件中列出
  • 各功能点提供的接口在src/sdk-impl/exports/iot_export_*.h中列出
  • 这些exports目录下的子文件, 都被src/sdk-impl/iot_export.h包含
  • 在V2.0+版本的编译系统中, 这个部分会被编译成output/release/lib/libiot_sdk.a

SDK接口声明层 + 例程

请参考快速接入页面官方SDK首页

以下详细描述如何将华东2节点设备端V1.0.1版本C-SDK移植到目标硬件平台.

V1.0.1设备端C-SDK简介

SDK基本框架如下图所示:

SDK框架

  • SDK大致可分为硬件抽象层、SDK内核代码、面向应用的API。
  • 在移植到目标硬件平台时,需要根据硬件平台的情况实现硬件平台抽象接口。
  • 在硬件平台抽象层中,包含OS层、network层、ssl层等3类。其中,OS层主要包括时间、互斥锁以及其它等接口,在目录$(SDK_PATH)/src/platform/os/下;network层主要包括网络相关的接口(目前为TCP接口),在目录$(SDK_PATH)/src/platform/network/下;ssl层包含ssl或tls相关接口,在目录$(SDK_PATH)/src/platform/ssl/下。

硬件平台抽象层

硬件平台抽象层包含数据类型、OS(或硬件)接口、TCPIP网络接口、SSL(TLS)接口等4个部分。下面分别对这4部分进行叙述。

数据类型

  • 表1-自定义数据类型
序号 数据类型名称 说明
1 bool bool类型
2 int8_t 8比特有符号整型
3 uint8_t 8比特无符号整型
4 int16_t 16比特有符号整型
5 uint16_t 16比特无符号整型
6 int32_t 32比特有符号整型
7 uint32_t 32比特无符号整型
8 int64_t 64比特有符号整型
9 uint64_t 64比特无符号整型
10 uintptr_t 能够容纳指针类型长度的无符号整型
11 intptr_t 能够容纳指针类型长度的有符号整型
  • 表2-自定义关键字
序号 关键字名称 说明
1 true bool值:真。如果目标平台无此定义,可宏定义: #define true (1)
2 false bool值:假。如果目标平台无此定义,可宏定义: #define false (0)
  • 此部分定义在源文件:$(SDK_PATH)/src/platform/os/aliot_platform_datatype.h。
  • 请根据目标平台情况实现,实现请放置于源文件:$(SDK_PATH)/src/platform/aliot_platform_datatype.h中。

注: SDK所定义的数据类型是C99标准所定义的数据类型的一部分,如果目标硬件平台完全支持C99标准,则无需修改此部分代码即可满足于目标平台。

OS(硬件)接口

  • 表3-OS相关接口说明
序号 接口名称 说明
1 aliot_platform_malloc 分配内存块
2 aliot_platform_free 释放内存块
3 aliot_platform_time_get_ms 获取系统时间(单位:ms),允许溢出
4 aliot_platform_printf 格式化输出
5 aliot_platform_ota_start 启动OTA,由于暂不支持OTA功能,该接口暂无需实现
6 aliot_platform_ota_write 写OTA固件,由于暂不支持OTA功能,该接口暂无需实现
7 aliot_platform_ota_finalize 完成OTA,由于暂不支持OTA功能,该接口暂无需实现
8 aliot_platform_msleep 睡眠指定时间,如果是无OS的平台,将函数实现为延时指定时间即可
9 aliot_platform_mutex_create 创建互斥锁,如果是无OS的平台,无需实现该接口
10 aliot_platform_mutex_destroy 销毁互斥锁,如果是无OS的平台,无需实现该接口
11 aliot_platform_mutex_lock 锁住指定互斥锁,如果是无OS的平台,无需实现该接口
12 aliot_platform_mutex_unlock 释放指定互斥锁,如果是无OS的平台,无需实现该接口
13 aliot_platform_module_get_pid 该接口仅用于特定场景,若无涉及,返回NULL即可
  • 详细的接口输入输出说明请参考源文件:($(SDK_PATH)/src/platform/os/aliot_platform_os.h)。
  • 实现时,请在路径$(SDK_PATH)/src/platform/os/下创建一个文件夹(请注意这个文件夹名,后续编译将用到这个名字),相应移植实现放置在该文件夹下。

注:如果是无OS平台,所有面向应用的接口都不能被并发调用(包括在中断服务程序中调用)

TCPIP网络接口

  • 表4-TCPIP网络相关接口说明
序号 接口名称 说明
1 aliot_platform_tcp_establish 建立tcp连接,返回连接句柄
2 aliot_platform_tcp_destroy 释放一个tcp连接
3 aliot_platform_tcp_write 往TCP通道写入数据。注意实现超时参数
4 aliot_platform_tcp_read 从TCP通道读取数据。注意实现超时参数
  • 详细的接口输入输出说明请参考源文件:($(SDK_PATH)/src/platform/network/aliot_platform_network.h)。
  • 实现时,请在路径$(SDK_PATH)/src/platform/network/下创建一个文件夹(请注意这个文件夹名,后续编译将用到这个名字),相应移植实现放置在该文件夹下。

SSL接口

  • 表5-SSL相关接口说明
序号 接口名称 说明
1 aliot_platform_ssl_establish 建立经SSL加密的传输通道
2 aliot_platform_ssl_destroy 释放一个SSL通道
3 aliot_platform_ssl_write 往SSL通道写入数据。注意实现超时参数
4 aliot_platform_ssl_read 从SSL通道读取数据。注意实现超时参数
  • 详细的接口输入输出说明请参考源文件:($(SDK_PATH)/src/platform/ssl/aliot_platform_ssl.h)。
  • 实现时,请在路径$(SDK_PATH)/src/platform/ssl/下创建一个文件夹(请注意这个文件夹名,后续编译将用到这个名字),相应移植实现放置在该文件夹下。

集成编译

平台移植工作完成之后,修改make.settings文件的相关配置项即可进行编译,具体如下:

  1. PLATFORM_OS = linux //OS文件夹名
  2. PLATFORM_NETWORK = linuxsock //network文件夹名
  3. PLATFORM_SSL = mbedtls //SSL文件夹名

完成配置后,执行make,即可编译目标平台的代码。

移植样例

请参考SDK代码中提供的平台适配代码。

本文导读目录