ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

EC20拨号疑难排查:quectel-CM启动流程与114.114.114.114 DNS之谜

EC20拨号疑难排查:quectel-CM启动流程与114.114.114.114 DNS之谜 1. 项目背景与使用场景1.1 EC20模块在嵌入式项目里的角色EC20是移远通信推出的LTE Cat 4全网通模块在嵌入式开发圈子里出镜率极高。无论是工控网关、边缘计算盒子、充电桩计费终端、安防视频传输设备还是车载终端只要涉及“设备需要上网”这个需求EC20基本是首选项之一。它的优势很直接支持国内三大运营商的全网通频段下行速率最高150Mbps、上行50Mbps对绝大多数物联网业务来说完全够用而且封装兼容性做得好LCC封装能直接贴片也有Mini PCIe封装适合做插卡式模组。在嵌入式Linux平台上使用EC20移远官方提供了一套拨号工具就是标题里的quectel-CM。这个工具的作用相当于给模块做一次完整的“上网初始化”检测模块状态、校验SIM卡、配置APN、发起拨号、分配IP、设置路由和DNS最终在系统里生成一个可用的网络接口通常叫wwan0或ethX。没有这个工具模块单纯上电只会枚举出几个串口设备并不会主动建立数据连接。我在实际项目里见过不少新入行的同事第一次拿到EC20开发板时以为插上模块、接通USB就能直接ping通外网结果折腾一整天发现ifconfig里根本没有新网卡。原因很简单EC20不是一个即插即用的USB网卡它需要经过一套QMI协议与模组交互把数据通道打通之后上层网络才会真正可用。quectel-CM就是把这套流程自动化的工具。1.2 quectel-CM和STM32等MCU开发的区别这里必须单独把“STM32 EC20”这个组合拎出来说因为它是非常多硬件工程师会踩的岔路口。很多人在网上搜到“stm32 ec20”的关键词以为MCU开发也和嵌入式Linux一样需要跑quectel-CM其实不是。MCU场景下STM32通过串口直连EC20的AT命令通道完全走的是AT指令流程。核心动作包括ATCPIN?查SIM卡状态、ATCREG?查网络注册、ATCGDCONT1,IP,cmnet设置APN上下文、ATQIACT1激活PDP上下文、ATQIOPEN建立Socket连接之后就走ATQISEND和ATQIRD收发数据。整个过程相当于人为复刻了quectel-CM在Linux里做的事情但是基于指令流逐条执行没有内核网络协议栈参与。你需要自己处理TCP/UDP连接、心跳、粘包业务代码全在MCU里。而Linux环境下EC20的Modem口会在USB枚举时挂载出几个ttyUSB设备其中有一个是QMI口。quectel-CM正是通过这个口使用QMI协议和模块协商出一条网络通路然后把数据映射到内核的wwan0网卡上。之后上层用的就是标准socket编程和以太网设备没有本质区别。这是两种完全不同的开发范式先分清楚自己手里的平台是Linux还是MCU再决定学哪套方案能少走很多弯路。2. quectel-CM启动流程逐段拆解2.1 工具启动前的准备工作很多人拿到quectel-CM直接双击运行或者嵌入式板子上直接执行发现报错或日志异常第一反应是工具坏了。其实工具本身很稳定问题大多出在启动前的外部条件上。第一步是确认模块有没有被系统正确枚举。在Linux下接上EC20之后用ls /dev/ttyUSB*查看正常会看到ttyUSB0到ttyUSB3四个设备分别对应AT口、Modem口、QMI口、ADB/日志口。不同固件版本枚举顺序可能有差异但基本固定。如果只有一个口冒出来说明驱动没加载完整常见原因包括内核缺少option或qmi_wwan驱动、USB接线不良、模块供电不足。第二步是确认拨号模式。EC20支持多种工作模式包括QMI、ECM、RNDIS、PPP等。quectel-CM默认走QMI通道这也是移远官方推荐的方式。如果你之前用ECM模式调试过模块设备节点会有所不同需要先通过AT指令切回QMI模式ATQCFGusbnet,2然后重新插拔模块。这个参数很关键usbnet设为0是PPP、1是ECM、2是QMI。经常有人发现quectel-CM提示“Cannot open /dev/ttyUSB2”多半是模式不对。第三点是SIM卡状态。建议在任何软件操作之前先用串口工具直接连AT口发送ATCPIN?如果返回CPIN: READY再继续如果返回ERROR或者CME ERROR说明SIM卡没插好、卡槽方向不对、或者SIM卡被写入了PIN码锁。这一步能帮你把问题范围缩小一大半。2.2 从设备检测到拨号成功的完整链路quectel-CM的运行逻辑并不复杂把它拆成几个阶段看理解起来非常清晰。第一阶段是设备检测。工具启动后会遍历/ dev目录下的ttyUSB设备寻找符合QMI能力的节点。它通过向候选设备发送QMI请求读取模块的IMEI、固件版本、SIM卡状态等基本信息。日志里如果能看到类似“Find /dev/ttyUSB2”或“Get card status”的输出说明设备检测已通过。第二阶段是SIM卡和网络注册检查。工具会确认SIM卡的IMSI、CCID信息并检查是否已经注册上运营商网络。这个阶段对应的日志字段通常是“Waiting for network register”或者“Check registration state”。我遇到过模块一直卡在这里不往下走的情况原因是SIM卡欠费和天线没接好虽然这两个问题表面上毫无关联但最终都表现为网络无法注册。第三阶段是APN配置。工具使用你传入的APN参数或者模块出厂配置通过QMI WDS接口设置接入点。不同运营商、不同业务类型的APN不一样公网卡通常是cmnet、ctnet、3gnet内网卡和物联专网卡则由运营商单独分配。APN设置错误最典型的后果是拨号能成功但网络完全不通或者只能访问部分内网地址。第四阶段是发起数据连接。工具调用WDS Start Network接口请求模块激活PDP上下文。这一步成功之后模块会获得一个IP地址和对应的DNS地址。日志里出现“Get IP address”和对应的IP数值就说明数据面已经通了。第五阶段是本地网络配置。这是quectel-CM的收尾工作把获取到的IP绑定到wwan0网卡上、设置默认路由、写入DNS配置。到这里Linux系统层面才真正具备访问外网的能力。很多人看到前面全部成功最后连不上网问题往往就出在路由或DNS配置上这正好引出了后面要重点剖析的114.114.114.114问题。2.3 拨号日志怎么读才不蒙圈我刚用quectel-CM的时候也被日志搞晕过因为它的输出格式并不统一有些版本打的是调试信息有些是状态变更不好好读很容易误判。有几种典型日志需要区分对待。以“[OK]”结尾的通常是命令执行成功的确认比如“ATQCFG? [OK]”说明AT指令回执正常。带“ERROR”字样的是有环节出了问题但问题可大可小比如AT指令偶发超时返回ERROR并不代表模块挂了可能是USB休眠导致的短暂无响应。还有一类是进度提示比如“Waiting for network register”只是告诉你它在等待不代表异常。实战中建议这样看日志先用时间戳对一遍流程确认执行到哪个阶段失败再抓关键错误码比如QMI请求返回的错误码0x03是设备无响应、0x0B是APN拒绝、0x12是sim卡未就绪最后结合串口AT口的实时日志做交叉验证。如果你要排查一个拨号问题务必备好三样东西quectel-CM的完整输出、/dev/ttyUSB0的AT口日志、dmesg内核日志。三者对照绝大多数问题都能定位到具体环节。3. 核心实操从零完成一次EC20拨号3.1 交叉编译quectel-CMquectel-CM的源码在GitHub上有多个历史版本移远官方也维护着固定的发布仓库。编译本身不难但嵌入式交叉编译有几个小地方要留意。工具源码依赖libqmi库所以编译前需要准备好libqmi的交叉编译库。如果你用的是Buildroot或Yocto建议直接把quectel-CM加进包管理系统里它们已经有现成的recipe省去手动处理依赖的麻烦。如果是手动编译步骤大致是先交叉编译libqmi再把libqmi的头文件和库路径传给quectel-CM的Makefile。命令大致是./configure --hostarm-linux-gnueabihf --prefix$PWD/out CCarm-linux-gnueabihf-gcc make make install编译完成后会生成quectel-CM可执行文件丢到板子的/usr/bin目录即可。需要注意一点有些移植版本对glibc版本敏感如果你镜像里的glibc版本比较老建议找对应版本的quectel-CM源码编译不要盲目用网上现成的二进制包不然会出现“No such file or directory”或者段错误这类诡异问题。3.2 常用参数与拨号命令quectel-CM的参数不多但每个都值得认真对待。最基本的用法是直接运行quectel-CM工具会自动检测模块并使用模块内部配置的APN。实际项目中更多是显式指定参数最常用的是-s指定APN。例如联通的物联网卡执行quectel-CM -s cpiot如果你的卡是专网卡还需要配置用户名和密码用-u和-p参数。有的企业内网APN还要求设置鉴权方式需要用到-1参数指定PAP或CHAP。工具还支持-4强制走IPv4、-6走IPv6以及-r参数重启模块后再拨号。还有一种比较实用的场景是DHCP模式。quectel-CM默认把拨号获得的IP配置到网卡上但它也支持协商一个IP地址后自动启动udhcpc获取通过-d参数开启。我自己更推荐手动指定IP因为DHCP模式依赖板子上的udhcpc环境出问题时会多一个排查变量。3.3 开机自启与断线重连产品化项目里quectel-CM大多需要开机自启不能依赖人工登录执行。在systemd系统里写一个service文件就能搞定[Unit] DescriptionEC20 Quectel CM Dial Afternetwork.target [Service] Typesimple ExecStart/usr/bin/quectel-CM -s cmnet Restartalways RestartSec5 [Install] WantedBymulti-user.target重点说一下Restartalways这个参数。4G网络在电梯、隧道、地下停车场这些场景下信号波动非常剧烈模块随时可能掉线如果没有自动重启机制设备就会一直维持“断网但不自知”的状态。quectel-CM本身具备一定重连能力但加上systemd的进程级守护会更可靠。实测下来在弱信号环境下5秒重启间隔是个不错的折中太短会导致模块来不及恢复太长会浪费恢复时间。4. 深入解读quectel-CM会把DNS写成114.114.114.114吗4.1 源码里的DNS处理逻辑这个热搜词特别有意思“quectel-cm是否会将114.114.114.114写dns”。我猜提问的人一定是在拨号后发现/etc/resolv.conf里的DNS地址从运营商的自动分配变成了114.114.114.114而且业务联调时碰到了一堆域名解析问题。先说结论是的在某些版本、某些条件下quectel-CM确实会把系统默认DNS设置或覆盖为114.114.114.114。这不是操作失误而是源码里的一段兜底逻辑在起作用。查看quectel-CM的源码可以发现在拨号成功后工具会通过QMI WDS接口获取运营商下发的DNS地址。正常流程里它会把获取到的DNS写到resolv.conf里。但代码里有一段处理是如果模块下发的DNS地址异常全为0.0.0.0或者获取失败工具会fallback到一组公共DNS。不同版本选的公共DNS不完全一样有的版本是114.114.114.114有的版本是114.114.114.114加8.8.8.8的组合。这就是问题来源。这种兜底逻辑从程序健壮性角度是合理的运营商信号不佳、DNS服务器临时不可用确实可能拿不到有效DNS。但对开发者来说这个行为非常隐晦因为你看到的现象只是“为什么我的resolv.conf被改了”可能完全想不到是quectel-CM干的。4.2 哪些情况下会触发公共DNS兜底根据我实际排查过的案例触发条件主要有以下几种。最常见的是模块在弱信号下或者刚开机还没完全注册到网络时quectel-CM就已经开始拨号流程此时模块返回的DNS上下文可能是空的工具走兜底逻辑写入公共DNS。这种情况下你会发现一个矛盾现象IP和路由配置都正常ping运营商内网地址能通但解析外部域名时走的却是公共DNS。如果你的设备还需要访问内网特定域名那问题会更明显内网域名解析全部失败。其次是部分物联专网卡的场景。这类SIM卡的APN上下文里运营商在下发DNS时可能只下发内网DNS或者出于某些配置原因没有携带公共DNS字段。quectel-CM获取不到有效DNS就会触发兜底。更特殊的是有些企业专网根本不允许公网DNS解析兜底一写进去整个域名解析链路就乱了。还有一种是代码版本差异。某些旧版本quectel-CM并没有严格判断“是否获取到有效DNS”只要拨号成功就会直接写入预置的114.114.114.114。这种问题在新版本中有所收敛但如果你手里的源码是几年前的项目里扒出来的中招概率很高。4.3 正确的DNS接管方案知道了原因解决起来就有针对性了。我推荐按优先级做三件事。第一件事升级quectel-CM到较新版本。新版本源码里对DNS下发的判断更严谨至少会等模块返回真正的DNS上下文。不过这不能完全解决问题因为弱信号下的空DNS现象再新版工具里依然可能触发兜底。第二件事从源码层面修改默认DNS。在quectel-CM源码里找到DNS fallback相关的定义把114.114.114.114改成你自己希望的内网DNS或者干脆把兜底路径去掉。源码修改的挑战是每升级一次工具版本就要重新改一次运维上不算省事。第三件事也是最推荐的拨号成功后在业务启动脚本里主动改写resolv.conf。因为quectel-CM只是它在启动时设置一次DNS之后不会再持续监控或刷新。比如你可以写一个脚本在quectel-CM拨号成功后等待几秒然后执行echo nameserver 10.0.0.1 /etc/resolv.conf同时把这个脚本放到systemd服务的ExecStartPost里。这样无论quectel-CM写了什么最终生效的都是你指定的DNS。不过要注意别在quectel-CM启动进程还没结束时抢写resolv.conf否则可能被它的收尾操作覆盖最好用sleep加条件等待来处理。5. 常见问题与排查技巧实录5.1 设备枚举异常我在多个项目里都遇过EC20插上之后枚举不出完整ttyUSB设备的情况处理思路一般按顺序排查。首先是硬件层面。EC20在数据收发瞬间的峰值电流能到2A甚至更高如果供电能力不足模块会反复重启表现就是USB设备不断枚举、断开、再枚举。这时候用万用表量模块供电引脚的电压如果在数据传输时电压跌落明显基本就能确定是供电问题。解决方案是换更大电流的DCDC电源芯片并在模块输入端并联470uF以上电解电容加上百uF钽电容组合。这个经验对MCU和Linux平台同样适用。其次是驱动层面。Linux下EC20依赖option和qmi_wwan驱动如果内核没有把这两个编译进去或者模块的VID/PID没能被驱动识别枚举就会失败。可以先modprobe option、modprobe qmi_wwan再看看dmesg里usb核心识别到了什么信息。还有一种隐蔽情况是USB线缆质量差信号完整性不过关表现为时好时坏换根短线往往立竿见影。5.2 SIM卡和网络注册类问题SIM卡问题经常被当成软件问题排查实际上大多数是接触和配置问题。先在AT口发ATCPIN?如果返回CME ERROR: SIM not inserted先别急着怀疑系统把卡拔出来重新插。模块的卡槽和手机不太一样很多开发板用的翻盖卡槽卡没推到位或者方向反了的情况太常见了。如果确认插好了还是这个错误用橡皮擦一下SIM卡金属触点氧化层会导致接触不良。如果CPIN正常但ATCREG?一直返回CREG: 0,2说明模块已注册但被拒绝大概率是运营商侧问题。遇到欠费停机、SIM卡绑定的APN不存在、该卡被限制使用数据服务都是这个表现。在quectel-CM的日志里这类问题通常表现为一直停留在“Waiting for network register”阶段。用串口直接连AT口看CREG变化会更直观。有些模块在有信号但注册被拒时CREG会反复在0、2、3之间跳这时候要重点查卡本身的状态而不是天线信号。5.3 拨号成功但上不了网这是最让人头疼的一类问题因为从quectel-CM的角度看所有步骤都执行完了IP也有了路由也配了但实际业务就是不通。我总结下来有三个高频根因。第一个是路由配置被覆盖。有些镜像的网络管理服务比如NetworkManager会在quectel-CM配好默认路由之后抢占把默认路由指到空的eth0上导致wwan0的数据包发不出去。查一下ip route如果默认路由的主出口不是wwan0那就手动调整metric让wwan0的路由优先级更高或者干脆停掉NetworkManager。第二个是防火墙拦截。嵌入式板子如果跑了iptables规则默认FORWARD或OUTPUT链策略是DROP即便路由正确也一样上不了网。这种问题非常隐蔽因为quectel-CM日志完全正常TCP握手卡在SYN_SENT状态。排查时直接iptables -L看一下策略或者临时把策略改成ACCEPT做对照测试。第三个是MTU不匹配。LTE网络的MTU通常建议设置在1400到1430之间如果系统网卡MTU保持默认1500碰到某些运营商网络会导致大包被丢弃小包正常表现是ping网关通、ping域名超时或者访问网页卡死。用ip link set wwan0 mtu 1400做一次对照测试就能确认。5.4 常见问题速查表我把日常支持里最常遇见的若干问题整理成了一张速查表方便现场排查时快速对照。现象可能原因排查命令/手段解决办法枚举不出ttyUSB设备供电不足/驱动缺失/USB线材劣质dmesg查看USB枚举日志更换电源、加载驱动、换短线模块反复重启电源跌落万用表监测供电引脚电压增强供电、加大电容AT口无响应波特率不对/模块死机AT指令测试确认115200波特率、拉PWRKEY复位SIM卡报错卡没插好/欠费ATCPIN?重插卡、联系运营商一直等待网络注册天线问题/注册被拒ATCREG?检查天线、确认卡状态拨号成功但ping不通路由/防火墙/MTUip route、iptables -L调整路由优先级、放行防火墙、降低MTUresolv.conf被改quectel-CM DNS兜底cat /etc/resolv.conf业务脚本里强制覆盖DNS掉线后恢复慢缺少自动重连journalctl查看systemd日志配置Restartalways5.5 STM32场景的独立坑点如果是STM32加EC20的玩法有几个坑是Linux平台完全碰不到但在MCU开发里反复出现的。第一个是串口缓冲和流控。EC20的AT口和Socket数据口如果共用同一个UART高速收发时很容易丢数据尤其当STM32的串口FIFO太浅或者开启了流控但线没接RTS/CTS的时候。建议HAL库工程里给串口开DMA加空闲中断不然数据稍微一多粘包和断包的坑会耗掉你一整天。第二个是模块波特率协商问题。很多EC20模块默认波特率是115200但有些固件出厂是9600。STM32代码里如果没有做波特率自适应基本AT指令都能成功但一遇到大数据量传输就开始乱码。还有一点要注意模块进入低功耗模式后再唤醒串口可能短暂不可用代码里要加多发几次AT指令做唤醒确认。第三个是Socket连接管理。EC20模块侧最多同时支持数十个Socket连接但MCU侧通常一个数据通道就够用了。重点是你需要自己处理重连逻辑不像Linux上有quectel-CM帮你盯着。我一般的做法是开一个定时任务每30秒发一次心跳ATQIURC到串口查询模块是否有URC上报如果连续三次没响应就重启模块并重新建链。6. 项目中的实际经验与建议6.1 电源设计不能省这是所有问题之源很多EC20的问题表面上是软件故障根子上全是供电压垮的。我在调试阶段就犯过这样的错误用开发板自带的USB口给模块供电刚开始一切正常一旦建立数据连接电流一上来模块就自动重启。而且这个现象在日志里表现得很“随机”时而拨号到一半断掉时而上电就枚举失败排查了很半天才想到去量电源波形。如果你的产品是电池供电还要额外注意DW等电压跌落检测。EC20的工作电压范围3.3V到4.3V推荐是3.8V左右电压低于3.3V就会触发欠压保护。电池电量低的时候4G模块发射瞬间的大电流会把电压瞬间拉低直接导致模块重启。做产品设计时建议预留一个低电量提示功能在电压过低时提前警告用户。6.2 天线和信号质量对调试效率的影响很多新手容易低估天线的影响。我曾遇到过一个客户quectel-CM所有的流程都正常但数据传输速率一直是几十kbps换了另一张SIM卡也一样。最后发现是外置天线增益不够再加上设备外壳金属遮蔽信号强度一直在-110dBm以下。你可以在AT口用ATCSQ查询信号强度返回值一般在0到31之间建议不要低于12。低于10的话就算拨号成功掉线率和延迟都会显著上升。注意CSQ反映的是信号质量总分不代表它一定是信号弱也可能是干扰导致的误码率偏高。排查这类问题时先换一个外置高增益天线放置在无遮挡的位置做对照是最快的排除法。6.3 日志和监控机制要提前设计好无论是Linux还是MCU平台日志系统一定要在项目早期就搭建好。MCU端至少要能把AT指令和模块返回完整记录到Flash里Linux端则建议使用syslog或journalctl把quectel-CM的输出统一收集起来。这样到了现场出问题时你能直接拿到第一手数据不用让用户帮忙复现半天还说不清楚现象。我见过一些产品现场出了问题远程登录一看quectel-CM进程已经死掉了/var/log里空空如也。这种时候排查完全靠猜。后来我在所有项目的quectel-CM service里都配了标准输出重定向再结合systemd的journald总算能做到故障可追溯。无线网络调试本来就充满不确定性日志就是你的照妖镜。6.4 最后再分享一个调试技巧我在排查EC20网络问题时经常会在串口AT口和网络侧同时做交叉验证。具体来说quectel-CM跑拨号的同时我会另开一路串口终端连到ttyUSB0实时丢AT指令去看模块的真实状态。比如quectel-CM日志里显示拨号失败但AT口返回CGACT: 1说明PDP上下文其实已经激活了问题可能出在qmi和内核网卡之间的数据通道协商上。反过来也一样AT口都没激活quectel-CM却在试图配置IP这多半是模块固件和工具版本不匹配。另外可以多利用模块自带的ATQCFGnwscanmode和ATQCFGband这类指令强制模块锁定在指定网络频段。在弱信号或者运营商网络异常的场景下频段扫描耗时长锁定频段能明显缩短拨号时间。这个技巧在拔测现场信号极差的情况下时尤其有效有时候能帮你在别人都掉线的时候保住业务通路。
返回列表