跳到主要内容

K230 SDK IoT WiFi AiW4211LV10驱动开发指南

1. 功能介绍

AiW4211LV10是一款低功耗IoT WiFi芯片,我司采用该芯片平台设计了一款AiW4211LV10开发板,该开发板可插入K230 EVB板的TF卡插槽实现接入。K230 EVB加载AiW4211LV10驱动之后,可以生成wlan0无线网卡,实现网络数据通信。

2. 模块依赖

硬件上依赖AiW4211LV10开发板,依赖K230 EVB开发板,K230 EVB为WiFi提供电源及中断检测连线。

软件上依赖于K230 SDIO主控驱动,依赖GPIO驱动的完备,需要emmc引导启动实现。

2.1 操作系统

当前驱动支持linux 4.9、linux 4.17和linux 5.10.4

2.2 硬件环境

K230 EVB开发板设置emmc启动,空出TF卡插槽用于AiW4211LV10开发板接入。

K230 EVB开发板飞线到AiW4211LV10开发板排针。连接关系如下:

表 2-1 飞线关系

Link1Link2Link3Link4Link5
K230排针J5 PIN16 (5V)J8 PIN9 (GPIO34)
WiFi排针J6 PIN1 (5V)J2 PIN3 (SDIO_INT_OUT)J2 PIN4 (TX)J2 PIN5 (RX)J2 PIN6 (GND)
TTL-USBRXTXGND

备注:TTL-USB与WiFi的连线主要是为了观察WiFi的固件输出,可以不连接

3. 模块配置

3.1 设备树修改

3.1.1 配置引脚function

修改uboot设备树arch/riscv/dts/k230_evb.dts,配置K230 EVB IO52引脚功能为GPIO,方向为input:

&iomux {
pinctrl-names = "default";
pinctrl-0 = <&pins>;
pins: iomux_pins {
pinctrl-single,pins = <

......

(IO52) ( 0 <<SEL | 0<<SL | BANK_VOLTAGE_IO50_IO61<<MSC | 1<<IE | 0<<OE | 0<<PU | 1<<PD | 7<<DS | 0<<ST )
}
}

3.1.2 配置GPIO控制器

修改linux设备树arch/riscv/boot/dts/kendryte/gpio_provider.dtsi,配置K230 EVB GPIO52控制器:

/ {

......

gpio52: gpio52@9140c000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "canaan,k230-apb-gpio";
reg = <0x0 0x9140c000 0x0 0x1000>;
interrupt-controller;
interrupt-parent = <&intc>;
#interrupt-cells = <2>;
interrupts = <84 IRQ_TYPE_EDGE_RISING>;

port52: gpio-controller@0 {
gpio-controller;
#gpio-cells = <2>;
nr-gpios = <1>;
reg-bank = <0>;
id = <52>;
};
};
};

3.1.3 配置SDHCI1参数

修改linux设备树arch/riscv/boot/dts/kendryte/k230_evb.dtsi,配置对应sdio主控参数:

sdcard: sdhci1@91581000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0x0 0x91581000 0x0 0x1000>;
interrupt-parent = <&intc>;
interrupts = <144>;
interrupt-names = "sdhci1irq";
clocks = <&dummy_sd>,<&dummy_sd>;
clock-names = "core", "bus";
max-frequency = <50000000>;
bus-width = <4>;
//cd-gpios = <>;
no-1-8-v;
cap-sd-highspeed;
sdhci,auto-cmd12;
status = "okay";
};

3.2 内核配置项

通过内核配置将AiW4211LV10驱动编译为内核模块,并将必要的协议及驱动编入内核。

使能kprobes:

> General architecture-dependent options

|| [*] Kprobes

将cfg80211编入内核,注意需要选中 cfg80211 wireless extensions compatibility:

> Networking support > Wireless

│ --- Wireless │ │

│ │ <*> cfg80211 - wireless configuration API │ │

│ │ [ ] nl80211 testmode command │ │

│ │ [ ] enable developer warnings │ │

│ │ [ ] cfg80211 certification onus │ │

│ │ [*] enable powersave by default │ │

│ │ [ ] cfg80211 DebugFS entries │ │

│ │ [*] support CRDA │ │

│ │ [*] cfg80211 wireless extensions compatibility │ │

│ │ [ ] lib80211 debugging messages │ │

│ │ < > Generic IEEE 802.11 Networking Stack (mac80211)

将AiW4211LV10驱动编译成内核模块,注意需要选中 IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP):

> Device Drivers > Network device support > Wireless LAN

│ --- Wireless LAN │ │

│ │ [ ] mac80211-based legacy WDS support │ │

│ │ [ ] ADMtek devices │ │

│ │ [*] Aich devices │ │

│ │ <M> Aich AiW4211LV10 (SDIO) support │

│ │ [ ] Atheros/Qualcomm devices │ │

│ │ [ ] Atmel devices │ │

│ │ [ ] Broadcom devices │ │

│ │ [ ] Cisco devices │ │

│ │ [ ] Intel devices │ │

│ │ [*] Intersil devices │ │

│ │ <*> IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)

│ │ [ ] Support downloading firmware images with Host AP driver │ │

│ │ [ ] Marvell devices │ │

│ │ [ ] MediaTek devices │ │

│ │ [ ] Microchip devices

3.3 SDIO主控增加扫描接口

AiW4211LV10驱动需要依据WiFi所接入的槽位发起SDIO扫描,因此特封装plat_sdio_rescan接口函数。修改drivers/mmc/host/sdhci-of-dwcmshc.c文件如下:

static unsigned int slot_index = 0;
static struct mmc_host \*__mmc__host[3] = {NULL};
int plat_sdio_rescan(int slot)
{
struct mmc_host \*mmc = \__mmc__host[slot];
if (mmc == NULL) {
pr_err("invalid mmc, please check the argument\\n");
return -EINVAL;
}

mmc_detect_change(mmc, 0);
return 0;
}

static int dwcmshc_probe(struct platform_device \*pdev)
{

......

priv->bus_clk = devm_clk_get(&pdev-\>dev, "bus");
if (!IS_ERR(priv->bus_clk))
clk_prepare_enable(priv->bus_clk);
__mmc__host[slot_index++] = host->mmc;
err = mmc_of_parse(host->mmc);
if (err)
goto err_clk;

......

}

4. 模块编译

在SDK顶层执行make linux,随内核一同编译,ko临时存储在output/k230_evb_defconfig/little/linux/drivers/net/wireless/aich/aiw4211lv10/目录。

5. 模块启动

5.1 WiFi固件

在K230 SDK当中WiFi固件AiW4211L_demo_allinone.bin以二进制文件形式提供,如需源码请联系我们。

固件存储路径:k230_sdk/src/little/utils/firmware/AiW4211L_demo_allinone.bin

5.2 驱动加载

在硬件环境配置完成后上电启动,执行以下指令即可实现驱动加载:

modprobe aiw4211lv10 或者 modprobe aiw4211lv10 mmc=1 gpio=52

当前驱动支持传入mmc主控编号及用于中断检测的gpio编号,可以实现较为灵活的硬件配置,如果不传参则分别使用代码中规定的默认值1和52。

驱动加载完成后,使用ifconfig -a指令可以看到已经生成了无线网卡wlan0。

5.3 网络配置

启动配置工具server端并置于后台运行:iotwifi_link &

该工具的功能角色类似于wpa_supplicant。iotwifi_link首先会将wlan0 up起来,然后从WiFi设备侧同步mac地址及ip地址到host端。

运行配置工具client端,控制WiFi接入AP及设置其他参数:iotwifi_cli –config /etc/wifi.conf

运行配置工具client端,控制WiFi进入深睡模式:iotwifi_cli –dirsleep

/etc/wifi.conf是WiFi工作参数配置文件,以json格式编写,基本上是对wifi_config_t结构体的映射,具体可参考6.1.2章节。

6. API参考

AiW4211LV10驱动加载后生成的无线网卡与一般WiFi网卡无异,因此网络通信功能无特殊API需要说明。

除基本的网络通信外,K230与WiFi还存在两个消息通信接口,需要重点说明。

6.1 config接口

6.1.1 API

int kd_wifi_config(wifi_config_t *config)

配置WiFi工作参数:

  • 配置目标AP的名称、密码、认证及加密方式
  • 配置WiFi休眠等级,苏醒周期以及可唤醒的gpio
  • 配置tcp keepalive时间参数等

6.1.2 数据结构

6.1.2.1 wifi_config_t
typedef struct {
unsigned int config_mask;
#define CFG_MASK_SLEEP (1 << 0)
#define CFG_MASK_CONNECT (1 << 1)
#define CFG_MASK_KEEPALIVE (1 << 2)
wifi_sleep_t sleep;
wifi_connect_t conn;
wifi_keepalive_t keepalive;
} wifi_config_t;

表 6-1 wifi_config_t结构体成员

成员说明
config_mask配置目标项掩码,使能或屏蔽目标项,例如全部配置则:config_mask = CFG_MASK_SLEEP|CFG_MASK_CONNECT|CFG_MASK_KEEPALIVE; CFG_MASK_SLEEP:配置休眠参数,CFG_MASK_CONNECT:配置AP连接参数,CFG_MASK_KEEPALIVE:配置tcp keepalive参数
sleep休眠参数
connAP连接参数
keepalivetcp keepalive参数

6.1.2.2 wifi_sleep_t

typedef struct
{
unsigned int level;
#define WIFI_SLEEP_LIGHT 1
#define WIFI_SLEEP_DEEP 2
#define WIFI_SLEEP_ULTRA 3
unsigned int period;
union
{
/*
* gpioX_wake: 0---disable, 1---enable
*/
struct {
unsigned int gpio0_wake:1;
unsigned int gpio1_wake:1;
unsigned int gpio2_wake:1;
unsigned int gpio3_wake:1;
unsigned int gpio4_wake:1;
unsigned int gpio5_wake:1;
unsigned int gpio6_wake:1;
unsigned int gpio7_wake:1;
unsigned int gpio8_wake:1;
unsigned int gpio9_wake:1;
unsigned int gpio10_wake:1;
unsigned int gpio11_wake:1;
unsigned int gpio12_wake:1;
unsigned int gpio13_wake:1;
unsigned int gpio14_wake:1;
};
unsigned int wake_gpios;
};
} wifi_sleep_t;

表 6-2 wifi_sleep_t结构体成员

成员说明
level休眠等级 WIFI_SLEEP_LIGHT:浅睡 WIFI_SLEEP_DEEP:深睡,主要休眠模式 WIFI_SLEEP_ULTRA:超深睡,只有3/5/7/14号gpio可唤醒,目前不使用
period苏醒周期,有效数值33~~4000ms。WiFi周期性从休眠态醒来,检测AP是否有发给自己的数据缓存
wake_gpiosenable或disable可唤醒WiFi的gpio(WiFi侧gpio)

6.1.2.3 wifi_connect_t

typedef struct
{
char ssid[EXT_WIFI_MAX_SSID_LEN + 1];
ext_wifi_auth_mode auth;
char key[EXT_WIFI_MAX_KEY_LEN + 1];
unsigned char bssid[EXT_WIFI_MAC_LEN];
ext_wifi_pairwise pairwise;
} wifi_connect_t;

表 6-3 wifi_connect_t结构体成元

ssidAP名称
auth认证类型 EXT_WIFI_SECURITY_OPEN EXT_WIFI_SECURITY_WEP EXT_WIFI_SECURITY_WPA2PSK EXT_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX EXT_WIFI_SECURITY_WPAPSK EXT_WIFI_SECURITY_WPA EXT_WIFI_SECURITY_WPA2 EXT_WIFI_SECURITY_SAE EXT_WIFI_SECURITY_WPA3_WPA2_PSK_MIX EXT_WIFI_SECURITY_UNKNOWN
KeyAP密码
bssidAP bssid,一般为AP mac地址
pairwise加密类型 EXT_WIFI_PARIWISE_UNKNOWN EXT_WIFI_PAIRWISE_AES EXT_WIFI_PAIRWISE_TKIP EXT_WIFI_PAIRWISE_TKIP_AES_MIX

6.1.2.4 wifi_keepalive_t

typedef struct
{
unsigned char svrip[16];
unsigned short svrport;
unsigned short tcp_keepalive_time;
unsigned short tcp_keepalive_intvl;
unsigned short tcp_keepalive_probes;
unsigned short heartbeat_intvl;
unsigned short heartbeat_probes;
} wifi_keepalive_t;

表 6-4 wifi_keepalive_t结构体成员

svripserver端ip地址
svrportserver端端口号
tcp_keepalive_timeTCP层keepalive心跳包常规发送周期,秒
tcp_keepalive_intvlTCP层keepalive心跳包无回应之后新的发送周期,秒
tcp_keepalive_probesTCP层keepalive心跳包无回应计数超过该阈值之后,判断TCP连接异常,断开重连
heartbeat_intvl应用层心跳包发送周期,秒
heartbeat_probes应用层心跳包无回应计数超过该阈值之后,判断socket连接异常,断开重连

6.2 sleep接口

int kd_wifi_sleep(void)

控制WiFi进入休眠,休眠相关参数在config API当中设置。

7. 基本性能测试

7.1 吞吐量测试

在办公室环境使用iperf进行网络吞吐量测试,PC通过网线接入AP,K230 EVB通过AiW4211LV10接入同一AP,分别在两端启动iperf工具,交叉测试上行及下行吞吐量。

client:iperf -c xxx.xxx.xxx.xxx -i 2 -t 300

server:iperf -s -i 2

dual:iperf -c xxx.xxx.xxx.xxx -i 2 -t 300 -d

表 7-1 TCP吞吐量粗测数据

WiFi ROLEBandwidth(Mbits/sec)
client12.2
server20.3

client:iperf -c xxx.xxx.xxx.xxx -i 2 -t 300 -u -b 25M

server:iperf -s -i 2 -u

表 7-2 UDP吞吐量粗测数据

WiFi ROLEBandwidth(Mbits/sec)Jitter(ms)Lost/Total Datagrams
client17.81.3411571/455457 (0.34%)
server21.01.0641/534990 (0.00019%)

7.2 文件传输测试

分别在PC与K230 EVB端架设nginx服务器,并分别使用wget拉取544MB大文件,并校验拉取文件的MD5值,测试150次无异常。