Ai-Thinker-Open_RTL8710BX_A.../Living_SDK/device/sal
2020-06-18 22:04:32 +08:00
..
gprs/sim800 rel_1.6.0 init 2020-06-18 22:04:32 +08:00
include rel_1.6.0 init 2020-06-18 22:04:32 +08:00
wifi rel_1.6.0 init 2020-06-18 22:04:32 +08:00
ip4_addr.c rel_1.6.0 init 2020-06-18 22:04:32 +08:00
README.md rel_1.6.0 init 2020-06-18 22:04:32 +08:00
sal.c rel_1.6.0 init 2020-06-18 22:04:32 +08:00
sal.mk rel_1.6.0 init 2020-06-18 22:04:32 +08:00
sal_arch.c rel_1.6.0 init 2020-06-18 22:04:32 +08:00
sal_device.c rel_1.6.0 init 2020-06-18 22:04:32 +08:00
sal_err.c rel_1.6.0 init 2020-06-18 22:04:32 +08:00
sal_sockets.c rel_1.6.0 init 2020-06-18 22:04:32 +08:00
ucube.py rel_1.6.0 init 2020-06-18 22:04:32 +08:00

AliOS Things SAL Porting Guide

在AliOS Things移植过程中如果需要支持外接Wifi/BLE等模且TCP/IP协议栈运行模组侧则需要SAL和底层模组控制模块进行对接。SAL功能对上层提供标准socket接口使上层应用不感知TCP/IP协议栈运行在MCU侧还是通讯模组侧。AliOS Things SAL的接口定义请查看头文件sal.h

本文将讲述AliOS Things 中SAL移植要点。

1、SAL模块重要数据结构

首先先了解一下AliOS Things中跟SAL相关的两个个重要的数据结构: sal_op_tsal_conn_t两个结构体。SAL依赖底层的相关操作和接口封装都在sal_op_t这个结构体中;sal_conn_t结构体为建立连接时SAL传给底层模组控制模块的相关参数。两个结构体相关定义在文件sal.h中。

typedef struct sal_op_s {
    char *version; 

    int (*init)(void);

    int (*start)(sal_conn_t *c);
    
    int (*send)(int fd, uint8_t *data, uint32_t len,
                char remote_ip[16], int32_t remote_port);
                
    int (*domain_to_ip)(char *domain, char ip[16]);
    
    int (*close)(int fd, int32_t remote_port);
    
    int (*deinit)(void);
    
    int (*register_netconn_data_input_cb)(netconn_data_input_cb_t cb);
} sal_op_t;
typedef struct {
    int fd; 
    CONN_TYPE type;
    char *addr; 
    int32_t r_port; 
    int32_t l_port; 
    uint32_t tcp_keep_alive;
} sal_conn_t;

2、SAL接口的实现

在具体的平台移植过程中用户需要分别实现SAL模块结构体中对应的接口函数。AliOS Things对SAL层接口有一层封装参见device/sal/sal.c文件。具体的接口实现一般在device/sal/xxx/中,其中xxx代表模组类型。参考实现:mk3060.c。下面对每个接口做一些说明:

init

该接口需要对通信模组进行相关初始化,使通信模组达到可以工作的状态。

deinit

如果有需要,该接口需要提供对通信模组的去初始化操作。

start

该接口需要模组启动一次连接。SAL传给底层的参数为一个结构体指针sal_conn_t,该结构体参数说明如下:

fd: 每个连接对应SAL socket层的句柄

type: 建立连接的类型,数据定义参见枚举CONN_TYPE

addr: 对端ip或者域名例如“192.168.1.1”或者“www.taobao.com”

r_port: 对端端口号

l_port: 本地端口号

tcp_keep_alive: tcp keep alive的时间

因此底层模组控制模块需要维护一套SAL socket 句柄和底层链路的对应关系。可以在发送/关闭连接时可以通过SAL socket句柄查找到对应的底层连接在接收底层数据时可以根据底层连接找到对应的SAL socket句柄。

close

该接口关闭模组的一个连接。入参说明如下:

fd: 需要关闭的socket句柄

remote_port: 对端端口号该参数为可选参数小于0时为无效参数

send

该接口通过模块发送数据的接口,该接口为阻塞接口,直到模组通知底层控制模块数据发送成功才会返回。入参说明如下:

fd: 发送数据所操作的句柄

data: 待发送数据的指针

len: 待发送数据的长度

remote_ip[16], 对端ip地址该参数为可选参数入参为NULL时无效

remote_port: 对端端口号该参数为可选参数小于0时为无效参数

domain_to_ip

该接口提供获取对应域名ip地址的功能注意1、即使该域名对应多个ip也只会返回一个Ip地址2、目前该接口只需要支持ipv4。入参说明如下

domain: 域名信息

ip[16]: 点格式的ip字符串目前只支持ipv4例如:192.168.111.111

register_netconn_data_input_cb

该接口提供一个SAL数据接收函数的回调功能底层模组控制模块在收到数据后调用该接口上送到SAL中SAL会在其中对每个句柄的数据进行管理。SAL提供的数据上送接口实现请见sal_packet_input

SAL提供的数据上送接口回调typedef int (*netconn_data_input_cb_t)(int fd, void *data, size_t len, ip_addr_t *addr, u16_t port);

参数说明如下:

fd: 数据上送需要操作的句柄

data: 接收到的数据(该部分内存由底层自行释放)

len: 接收到的数据长度

addr: 该数据的源地址为可选参数可以传入NULL该部分内存由底层自行释放

port: 该数据的源端口为可选参数可以传入0

3、模组注册和初始化SAL

在完成SAL接口对接实现后定义一个 sal_op_t结构体,将各个接口和回调的实现地址赋值给结构体中对应的域。例如:

sal_op_t sal_op = {
    .version = "1.0.0",
    .init = sal_wifi_init,
    .start = sal_wifi_start,
    .send = sal_wifi_send,
    .domain_to_ip = sal_wifi_domain_to_ip,
    .close = sal_wifi_close,
    .deinit = sal_wifi_deinit,
    .register_netconn_data_input_cb = sal_wifi_packet_input_cb_register,
};

底层模组控制模块需要实现一个函数调用sal_module_register对SAL进行模块注册。例如

int mk3060_sal_init(void)
{
    return sal_module_register(&sal_op);
}

该模块注册函数需要在device.csal_device_init中进行调用。例如:

int sal_device_init()
{
    int ret = 0;

#ifdef DEV_SAL_MK3060
    ret = mk3060_sal_init();
#endif
    if (ret){
        LOGE(TAG, "device init fail ret is %d\n", ret);
    }
    
    return ret;
}

4、编译底层模组控制模块

在完成底层模组与SAL接口对接后该部分代码建议的放置路径为device/sal/xxx/yyy。其中xxx为模组类型例如wifi、ble、lora等yyy为模组型号例如mk3060。例如mk3060的wifi模组代码放置路径为device/sal/wifi/mk3060/。对应模组控制模块代码makefile名称需与模组型号一致为yyy.mk例如mk3060的makefile文件名为:mk3060.mk

编译时请注意在正常的编译命令后需要指定编译sal和所使用的通信模组信息例如aos make alinkapp@b_l475e sal=1 module=wifi.mk3060 ,其中sal=1表示需要编译salmodule=wifi.mk3060

表示所需要连接的模组类型为wifi.mk3060此时AliOS Things的Makefile 体系会自动调用devcie/sal/wifi/mk3060/mk3060.mk 将模组控制模块代码编译进来。