1、概述
AliOS Things支持MCU与通信芯片间的多种连接方式,如UART、SPI、SDIO、USB。这些连接方式不仅拓展了基于AliOS Things开发的可选联网方案,还满足了不同应用场景对传输速率需求,如表1所示。其中,HAAS100通过USB外接LTE,可以实现相同厂商不同模组间无缝替换,例如EC20、EC200S。
表1 AliOS Things所支持外接方式以及应用场景
2、USB外接通信芯片的优点
USB本身具有使用方便、数据传输可靠、成本低、省电等优点。而使用USB做为外接通信芯片的通道,将保留这些优点,具体表现为:
2.1、使用方便
- 一个接口可以用于多种设备的连接,用户可以方便地替换所要连接的通信芯片,无需针对不同通信芯片采用不同的连接器和线缆。
- 自动配置,通信芯片接入后,MCU侧可以自动对通信芯片进行识别,并加载对应的驱动程序。
- 支持热插拔,用户可以随时接入或拔出通信芯片,而不会损害硬件设备,也无需重启设备。
- 无需额外供电,USB接口提供了+5V电压,500mA以下电流,一般情况下通信芯片无需额外电源。
2.2、数据传输可靠
- 接收端和线缆硬件规范,保证数据传输在一个平静的接口电器环境中,避免了导致数据错误的大部分噪声干扰。
- 差分传输模式,USB 1.1/2.0采用四线模式,其中D+/D-为数据传输通道,采用差分信号的传输方式,D+/D-需要同时满足电平条件才能判定为0或1,降低了因干扰产生比特跳变的可能性。
- CRC校验,USB硬件自带CRC校验,可检测传输过程中发生的错误。
- 协议确认重传,USB在协议层面提供了确认(ACK/NACK)与重传机制,可从传输错误中恢复。
2.3、成本低、省电
- USB部件成本较低,无论是使用独立的controller,还是使用集成IP的方案,成本都可以控制在合理范围内。并且从可扩展性来看,USB可以支持更多种类的设备连接,而无需硬件上的改动。
- USB使用了省电电路与协议,配合通信芯片的休眠与唤醒功能,可实现整体上的低功耗。
3、实现基于USB通道外接通信芯片
为了实现基于USB通道外接通信芯片,除了要保证MCU具备USB连接硬件能力以外,MCU侧还需要实现USB host协议栈,以完成
- 设备识别
- 驱动加载
- 数据传输
图 1 MCU侧USB Host协议栈结构,包括了Host controller层、Host Core层、Host Class层、USB Device Driver层
MCU侧的USB host协议栈大致分为四层:Host Controller层、Host Core层、Host Class层、USB Device Driver层。其中,Host Controlle是USB host协议栈最底层,负责直接与硬件交互,读写寄存器、中断处理;Host Core是协议栈的核心层,对下负责管理Host controller、设备、接口、端点,并负责设备枚举,对上负责host class的注册、设备的配置以及传输请求处理;Host Class层为各USB host类的实现层,例如HID、CDC、UVC等类。 最后,设备驱动层用于实现与USB设备应用交互逻辑,例如通过AT指令与EC20进行交互。各层的设计细节将在另一篇文章中详细介绍,此处将不再展开。本节将围绕设备识别、驱动加载、数据传输介绍USB外接通信芯片的实现方式。
3.1、设备识别
当通信芯片通过USB连接上MCU后,两者会发生以下对话。
Host:你是什么设备?
Device: 12 01 0100... / Device Descriptor /
Host:你有几种功能?
Device:09 02 09... / Configuration Descriptor /
Host:每个功能有几个接口?
Device: 09 04 00... / Interface Descriptor /
Host:每个接口使用哪几个端点?
Device: 06 05 82... / Endpoint Descriptor /
Host: 我知道你是谁了,开始传输
Device: OK
....
这些问答的目的是为了帮助USB Host准确地对接入的设备进行识别。交互的信息主要包括设备描述符、配置描述符、接口描述符、端点描述符。
3.2、类加载
在枚举过程的最后会根据设备所属类加载驱动。这里有两种加载方式,一种是按设备加载,另一种是按接口加载。以EC20为例,其接口都为vendor类,无法根据接口类进行加载。因此,需要根据设备的Vendor ID(VID)、Product ID(PID)加载对应类。
事实上,针对这一类由vendor定制广域网USB设备,Linux USB驱动的解决方案,是使用专门有文件(usb/serial/option.c)用于存储厂商的VID和PID列表;在枚举时,如果USB设备的VID与PID相匹配,则加载相应驱动(usb/serial/wwan.c)进行处理。如上文所述,EC20有5个接口,其中接口0为DM口、接口1为GPS接口、接口2为AT口、接口3为PPP口、接口4为NDIS口,如图5所示。由于PC端资源是充足的,Linux USB Host在枚举EC20时可以为每个接口创建相应的端点,并允许用户同时操作这些接口(open/read/write)。
图 4 EC20各USB接口功能
然而,在运行RTOS的MCU芯片上USB控制器的资源是有限的,无法同时创建这么多个接口所需要的端点。以HAAS1000为例,除了控制端点0,其USB控制器只有4个端点可供使用。因此,在MCU上枚举过程中需要考虑底层硬件资源限制,否则会导致驱动加载失败。这里采用的策略是复用端点的方式。在加载驱动时,有针对性地选择接口:首先为接口2分配端点资源,用于AT指令交互,保证4G模块联网并获取IP;然后,在其它接口需要使用时,释放端点2的端点资源。
3.3、数据交互
完成类加载后,上层可通过USB通道收发送数据。以EC20的AT接口为例,AliOS Things的AT驱动框架(SAL + AT Utility)可以无缝运行在USB协议栈上。
图 5 基于USB协议栈的AT通道
需要做的工作是使用USB Class API实现AT Utility所需HAL(at_dev_ops_t)即可,如下所示。
/*
- AT dev operation type
*/
typedef struct {
at_dev_type_t type;
/**
* AT device init
*
* @return 0 - success, -1 - failure
*/
int (init)(void dev);
/**
-
Receive data from AT device
-
@return 0 - success, -1 - failure
*/
int (recv)(void dev,
void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout);
/**
-
Send data to AT device.
-
@return 0 - success, -1 - failure
*/
int (send)(void dev,
void *data, uint32_t size, uint32_t timeout);
/**
-
AT deviec deinit
-
@return 0 - success, -1 - failure
*/
int (deinit)(void dev);
-
} at_dev_ops_t;
在此基础上,使用AT Utility API实现SAL所需HAL(sal_op_t)即可,如下所示。
typedef struct sal_op_s {
struct sal_op_s * next; //<! Next sal_op_t structure
char *version; //<! Reserved for furture use.
char *name; //<! Drvier name
/* Add sal device */
int (*add_dev)(void*);
/**
* Module low level init so that it's ready to setup socket connection.
*
* @return 0 - success, -1 - failure
*/
int (*init)(void);
/**
* Start a socket connection via module.
*
* @param[in] c - connect parameters which are used to setup
* the socket connection.
*
* @return 0 - success, -1 - failure
*/
int (*start)(sal_conn_t *c);
/**
* Send data via module.
* This function does not return until all data sent.
*
*/
int (*send_data)(int fd, uint8_t *data, uint32_t len,
char remote_ip[16], int32_t remote_port, int32_t timeout);
/**
* Get IP information of the corresponding domain.
* Currently only one IP string is returned (even when the domain
* coresponses to mutliple IPs). Note: only IPv4 is supported.
*
*
* @return 0 - success, -1 - failure
*/
int (*domain_to_ip)(char *domain, char ip[16]);
/**
* Close the socket connection.
*
* @return 0 - success, -1 - failure
*/
int (*finish)(int fd, int32_t remote_port);
/**
* Destroy SAL or exit low level state if necessary.
*
* @return 0 - success, -1 - failure
*/
int (*deinit)(void);
/**
* Register network connection data input function
* Input data from module.
* This callback should be called when the data is received from the module
* It should tell the sal where the data comes from.
*
* @return 0 - success, -1 - failure
*/
int (*register_netconn_data_input_cb)(netconn_data_input_cb_t cb);
} sal_op_t;
完成以上对接后,上层应用即可以基于标准的套接字API编程,降低了应用层移植成本。相关AT驱动组件介绍请参考AliOS Things帮助文档 SAL组件、AT组件。
4、HaaS100外接4G模组示例
图6 HaaS100通过USB外接EC20
图 7 USB所用排针接线
HaaS100板上排针提供了USB引脚,可以用接USB母口扩展线,与通信模组连接,如图6、7所示。
步骤一:配置
aos make linkkit_demo@haas100 -c config
步骤二:配置选择
aos make menuconfig
配置
步骤三:编译
aos make
步骤四:烧录
请参考HaaS快速开始
步骤五:启动
该应用运行Linkkit demo,USB枚举成功后,通过AT通道,可以连接入阿里云IoT平台。
5、总结
广域网通信模组通常都提供USB通道,支持AT、PPP、RNDIS、ECM等通信方式。因此,在MCU侧支持USB协议栈,可自动识别枚举各类通信设备,并加载所需的驱动,方便用户上层的开发。本文简要介绍了AliOS Things的USB Host协议栈,并以EC20为例描述了枚举识别过程,同时给出了在USB通道上对接AliOS Things传统AT通道的方式。在后续相关系列文章中,我们将介绍基于USB通道的PPP、RNDIS、ECM方式,并给出相应对比数据。敬请期待。
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页