本帖最后由 lin704932121 于 2018-5-4 23:34 编辑
大概去年这时候,21ic发了一波STM32F469I-Discovery板子。我很高兴能拿到这拿到这块板子,并写了两篇试用帖子【STM32F469I试用】Linux下USB无线网卡驱动的移植和【STM32F469I试用】USB摄像头的采集与显示。最近,有坛友问我是否有相应的3G网卡驱动,我趁这个假期把之前移植好的代码整理了一下,分享给大家。这个3G网卡驱动大概消耗十几KB的内存。
一、USB 3G网卡拨号流程
USB 3G网卡和PC一般是通过modem(也可以说是虚拟串口)来进行通信的。3G网卡插入后,首先要用AT指令拨打指定运营商号码,再通过PPP认证协议获取到自身的IP地址。然而现在厂商为了方便用户安装驱动程序,3G网卡一上电是一个存储类,用户通过它可以安装.exe文件的驱动程序。驱动程序安装完成后,3G网卡再次上电,驱动程序会向3G网卡发送一串特定指令。3G 网卡收到特定指令后,会使USB的D+和D-引脚浮空,造成USB断开。接着PC会再一次枚举3G网卡,此时3G网卡就会成为modem(虚拟串口)类。由于每个厂商甚至每种型号的3G网卡的特定指令都不一样,因此如果厂商没有提供Linux下的驱动话,在Linux下进行拨号上网就便的很困难。还好,有人抓取了windows下的驱动程序和3G网卡之间的USB通信协议包,获取到了这些特定指令,详情可见usb_modeswitch这个开源项目。
下图是将usb_modeswitch移植到STM32F4后的拨号流程图,3G网卡插入后,首先判断modem驱动是否支持该型号网卡,如果支持就直接使用AT指令进行拨号,然后再进行ppp认证。如果不支持再判断usb_modeswitch是否可以转换网卡的模式。
二、联通USB 3G网卡的使用
我手上有个联通华为E261型号的3G网卡,就用它来做测试吧。
1.运行 EvalBoards\ST\STM32469I-Discovery\uCOS-III\KeilMDK\uCOS-III.uvproj ,编译并直接烧写程序。工程环境用的是MDK 4.7。
2.程序烧写完成后会同时在USART3和LCD上输出信息。USART3 连接到了板子上的STLINK,PC机上直接打开这个虚拟串口就可以使用它了。
2.用一根OTG线连接板子上USB FS端口,并插入3G网卡。
3.如下图,串口终端中输入ping命令测试网络连通性。
UDP上行带宽测试
工程里包含有iperf带宽测试程序。如下图,在串口终端中输入:
iperf -c 120.25.217.198 -u -b 4Mbits -t 18 -i 1
其中,120.25.217.198是我的一个云服务器ip地址,-u代表udp测试,-b 4Mbits代表测试带宽4Mbits/s,-t 18代表测试时间18秒,-i 1代表每秒钟报告一次测试结果。
可以看到,服务器报告的测试带宽为1.58Mbits,丢包率0.044%。
TCP上行测试
如下图,在串口终端中输入:
iperf -c 120.25.217.198 -t 18 -i 1
可以看到,TCP测试带宽仅为250Kbits/s,远远不如UDP测试的速率。这其中一方面是因为3g网卡和服务器的传输延迟大,另一方面是lwip配置的发送缓冲区不够大。将lwipopts.h中TCP_SND_BUF修改为(8*TCP_MSS),重新编译。
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (4*TCP_MSS)
-->
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (8*TCP_MSS)
如下图,重新进行TCP上行测试,可以看到TCP测试带宽提高到了550Kbits/s。然而提高发送缓冲区也意味着消耗更多内存,终端中输入stats命令,可以看到内存堆的最高消耗由15KB提高到了21KB。
MEM HEAP
avail: 24576
used: 1532
max: 15920
err: 0
-->
MEM HEAP
avail: 24576
used: 1532
max: 21836
err: 0
三、其它运营商3G网卡使用
usb_modeswitch只是转换3G网卡模式,并不识别3g网卡的运营商。代码中默认是中国联通的拨号脚本,如果想使用中国移动或中国电信3g上网卡,需要在modem.c文件modem_probe()函数中,取消注释相应运营商的拨号函数。
for(i=0;i<4;i++)
{
msleep(3000+2000*i);
if((ret = modem_dial_china_unicom(modem)) == 0) break; //中国联通拨号脚本函数
// if((ret = modem_dial_china_telecom(modem)) == 0) break; //中国电信拨号脚本函数
// if((ret = modem_dial_china_mobile(modem)) == 0) break; //中国移动拨号脚本函数
}
当然,也可以尝试使用AT+COPS?指令来识别出3g网卡当前所使用的运营商,再使用不同的拨号脚本。
手里还有另一块华为MU509联通制式模块,顺便也附上它的UDP带宽测试结果图吧。测试结果的带宽并不高,只有380Kbits/s左右。
USB-3G-Modem-for-STM32F4xx.rar
(4.08 MB)
2017/2/19追记:
我重新运行了板子上的代码。插上华为E261型号3G网卡后,AT指令拨号总是失败。然而我假期在家里测试是可以的,来到北京就不行了?
我试着在PC上使用USBPcap抓取3G网卡通讯协议包,发现PC对3G网卡发送有一条特殊AT指令AT&FE0V1X1&D2&C1S0=0。将该指令添加到拨号脚本的函数里,3G网卡可以正常拨号。暂时还不明白这条指令是什么意思。
在modem.c文件modem_dial_china_unicom()函数里,添加AT&FE0V1X1&D2&C1S0=0指令。
struct modem_chat chat[] =
{
{"AT\r","OK"},
{"AT+CGDCONT=1,\"IP\",\"3gnet\",,0,0\r","OK"},
{"AT+CFUN=1\r","OK"},
{"ATDT*99#\r", "CONNECT"},
{ } /* Terminating entry */
};
修改为:
struct modem_chat chat[] =
{
{"AT\r","OK"},
{"AT+CGDCONT=1,\"IP\",\"3gnet\",,0,0\r","OK"},
{"AT+CFUN=1\r","OK"},
{"AT&FE0V1X1&D2&C1S0=0\r","OK"},
{"ATDT*99#\r", "CONNECT"},
{ } /* Terminating entry */
};
|
强