
1. 为什么突然想测这个一个让我抓狂的烧录现场先交代一下背景。前阵子帮朋友产线调一套设备MCU 板子用的是某个 Cortex-M 内核的芯片出厂要烧录一段 32KB 左右的固件。产线工艺工程师第一版方案用的是 UART 串口烧录因为每台工位只需要一个 USB-TTL 模块成本低、接线简单。结果第一批 50 台板子烧下来平均每台要等 4 秒多才能亮绿灯整条线一天只能出不到 300 台被老板追着问能不能提效。我当时第一反应是换 JTAG/SWD 调试器烧录不就完了但工程师面露难色说一直听说 JTAG 比 UART 快可到底快多少、快在哪、值不值得为此给每台工位配一个调试器谁也说不准。于是我就搭了个对比测试环境认认真真测了一下午最后拿到一组挺有意思的数据——在当时的条件下JTAG实际走 SWD 模式比 UART 快了 6.8 倍。这篇文章就是那次实测的完整记录。我会把两种烧录方式的原理差异、测试平台的搭法、实测数据、理论带宽换算、常见报错排查以及不同场景下到底该选哪种方案全部摊开讲清楚。对于正在做量产烧录工装、或者被固件下载速度折磨的开发者和工艺工程师来说这篇内容应该能帮你省掉不少试错时间。即使你只是刚接触嵌入式的小白看完也能明白 UART 和 JTAG/SWD 在固件烧录里的角色区别。2. 测试平台与方案设计尽量公平的对比对比测试最怕变量没控制好最后得出一个没法复现的结论。所以这次我特意把软硬件环境固定下来所有数据都是在同一块板子、同一个 PC 上、连续测试取中位数得到的。2.1 硬件环境与烧录工具先列一下测试用到的东西都是嵌入式开发里很常规的配置目标板某主流 Cortex-M 内核 MCU 开发板板载 256KB Flash支持 SWD 和 UART 启动UART 通道板载 FT232R 方案的 USB-UART 模块接到 MCU 的 USART1 引脚波特率默认 115200JTAG/SWD 通道ST-Link/V2 调试器SWD 模式SWCLK 时钟设到 4MHzPC 端 UART 烧录工具自己写的 Python 小工具基于 pyserial方便精确计时PC 端 SWD 烧录工具OpenOCD 命令行 STM32CubeProgrammer CLI 各测了一遍固件样本用随机数生成并填充了三份 bin 文件大小分别是 32KB、64KB、128KB这里有一点要特别说明我标题里写的是“JTAG”但实际跑测试用的是 SWD。SWD 全称是 Serial Wire Debug是 ARM 在 JTAG 基础上发展出来的调试接口协议物理上只需要 SWDIO 和 SWCLK 两根线在 Cortex-M 系列 MCU 上非常常见。可以说 SWD 是“JTAG 调试体系”在 ARM MCU 领域的一种精简实现所以大家平时嘴上说“用 J-Link 下载”实际走的绝大多数是 SWD。真正的四线 JTAG 在 FPGA、复杂 ASIC 调试场景里更常见在 ARM MCU 上反而用得少原因后面会细说。2.2 计时口径与数据可靠性本次测试只统计一个指标从烧录工具软件里点击“开始”到工具提示“烧录成功”的墙钟时间。这个时间包含了握手、擦除、数据传输、Flash 编程、校验在内的所有环节和产线上实际感受到的等待时间完全一致。每个固件大小各测 5 次去掉最高和最低后再取平均避免串口被系统调度抖动、调试器偶尔抽风之类的问题影响结果。测试期间 PC 上不跑大型软件串口工具也不做多余打印尽量让数据贴近理论条件。实测跑下来同一组数据波动基本在正负 0.2 秒以内可重复性是可以接受的。2.3 为什么用 SWD 而不是完整四线 JTAG这里多说两句。如果你想在 STM32、GD32、NXP 这类 ARM Cortex-M 芯片上做下载调试完整四线 JTAGTDI/TDO/TCK/TMS其实是“杀鸡用牛刀”。SWD 只需要复用 TMS 和 TCK 两根引脚占用的 IO 资源少接线简单而且在大多数 MCU 上时钟上限比完整 JTAG 还要高。FPGA 的 JTAG 配置链、复杂 SoC 的边界扫描测试才需要完整的四线接口。工程上讲ARM 平台用 SWD 就是最合理的选择。所以这篇测评里我拿 SWD 的数据代表“JTAG 体系”的真实表现标题里用 JTAG 这个词也只为了和 UART 做对比时更直观现在的嵌入式工程师看到 JTAG 基本都能理解包含 SWD 在内。3. 实测结果6.8 倍这个数字是怎么来的3.1 三组固件的实测数据直接上一手数据。以下时间单位均为秒数值是该组 5 次测试的中位数固件大小UART 115200bps 耗时SWD 4MHz 耗时提速倍数32KB4.5 秒0.66 秒约 6.8 倍64KB8.1 秒1.21 秒约 6.7 倍128KB15.4 秒2.30 秒约 6.7 倍很明显三档固件下提速倍数都非常接近 6.7 到 6.8稳定性很好。标题里我取了第一组 32KB 固件的数据也就是 4.5 秒对上 0.66 秒快 6.8 倍。这个结果在产线上的意义是原来烧一台 4.5 秒换 SWD 后不到 1 秒就能完成。算上自动化工装的上下料、扫码时间单台节拍能从 7 秒压到 3 秒左右一天产能几乎翻倍。这也是为什么苹果、华为这类品牌的消费电子产品产线烧录工位清一色用的是高速调试器很少靠串口慢慢挪。3.2 理论带宽换算UART 的浪费和 SWD 的碾压实测背后是两种接口的物理层效率差异。先把理论带宽算明白你就能理解 6.8 倍并不是玄学。UART 在 115200 波特率下每秒传输 115200 个二进制位。但串口传输一个字节最常用的格式是 8N11 位起始位 8 位数据位 1 位停止位也就是传 10 个 bit 才带 8 个有效数据 bit效率只有 80%。所以 UART 的有效字节速率上限是115200 bit/s ÷ 10 bit/byte 11520 byte/s ≈ 11.25 KB/s这还只是物理层。实际 bootloader 协议还要在数据前面加帧头、长度字段后面加 CRC 校验每一帧真正的数据占比可能只有 95% 左右。算下来 32KB 固件光传输就要32 × 1024 ÷ (11520 × 0.95) ≈ 3.0 秒再算上 MCU 每收一块数据就要擦除、写入 Flash以及 PC 端等待 ACK 确认的往返延迟4.5 秒的实测非常合理。再看 SWD4MHz 的 SWCLK 意味着物理线速是 4,000,000 bit/s也就是 500KB/s 的理论带宽。SWD 协议本身有一些命令头、ACK、状态位的开销实际有效数据率大约在 200KB/s 到 280KB/s 之间取决于目标芯片的 Flash 控制器配合程度。但哪怕只按 250KB/s 算它也是 UART 115200 的 20 倍以上。那为什么最终整体只快了 6.8 倍而不是 20 倍答案在下一节。3.3 为什么是 6.8 倍而不是十几倍很多第一次做对比的人会想SWD 物理带宽是 UART 的 20 倍那烧录时间应该也缩到 1/20 才对。但实测只有 6.8 倍原因有三。第一Flash 擦除和编程是两种方式都必须付出的公共成本。MCU 内部 Flash 的写入速度是有限的无论数据从 UART 进来还是从 SWD 进来最终都要落到 Flash 里这部分时间谁也无法省略。固件越大Flash 编程时间的占比越高两种方式的总耗时差距反而会被拉近。第二UART 的 11.25KB/s 是物理上限实际上我在 bootloader 里为每包数据都加了 ACK 确认PC 端必须等到 MCU 擦写完成并返回“OK”才能发送下一包。这种设计保证了可靠性但在高波特率下会浪费大量时间在网络往返上。这是很多自制 bootloader 的通病后面我专门写了优化建议。第三SWD 烧录虽然快但也不能完全跑满线速。调试器要频繁访问目标芯片的调试端口寄存器、等待 Flash 编程完成实际有效吞吐能到 250KB/s 已经不错。综合下来整体时间差落在 6 到 7 倍这个区间符合理论推算。4. 时间都花在哪了烧录瓶颈拆解4.1 UART 慢的三个硬伤UART 烧录慢不是单一原因造成的而是三个瓶颈叠加。第一个硬伤是波特率天花板。很多产品的 bootloader 为了兼容各种 USB-TTL 模块出厂默认只支持 115200bps甚至还有用 9600bps 的老古董。115200 换算下来每秒只有 11.25KB 有效数据这是物理层的“单车道”。第二个硬伤是逐包确认的串行化等待。以我测试用的 bootloader 为例它按 256 字节一包接收数据每收一包就做 CRC 校验、擦除对应 Flash 页、写入数据、再回复 ACK。PC 端只有在收到 ACK 后才发下一包。也就是说PC 发 256 字节只花 22 毫秒左右但 MCU 擦写一个扇区要几十毫秒整条链路的时间被最慢的环节拖死UART 的间歇时间全被浪费了。第三个硬伤是上位机串口调度的不确定性。Windows 下串口驱动有缓冲区和调度延迟Python 程序里即便不加 sleep实际发包间隔也可能有几毫秒到几十毫秒的抖动。这些零碎时间加在一起在 32KB 固件下就能多出几百毫秒固件越大越明显。4.2 JTAG/SWD 赢在什么地方SWD 快首先赢在协议层面。它不像 UART 那样有起始位、停止位这些额外的线速开销每个时钟周期都能传一个 bit。其次是 SWD 的读改写过程更“聪明”调试器通过调试端口直接控制目标 CPU 的 Flash 控制器可以把数据从电脑端以 DMA 式的高速率灌入目标 RAM再由目标芯片内部完成擦写减少了每一步等待。另外SWD 在时序上采用同步时钟。MCU 的 SWCLK 和调试器是同一时钟源不存在 UART 那种波特率偏差导致的重传问题。所以 SWD 在长时间大批量传输时性能非常稳定这也是它能稳定压住 UART 的根本原因。顺便说一句很多人以为 SWD 需要目标板跑程序才能烧录这是误解。SWD 属于调试接口连接的是芯片内部的调试访问端口DAP即使 Flash 里完全没有程序、芯片已经被锁死调试器也能连上并重新烧录。这一点对产线和售后救砖非常重要UART bootloader 则做不到因为 bootloader 本身就是烧在 Flash 里的。4.3 容易被忽略的公共耗时我推荐你在自己的板子上做速度测试时把“擦除整个 Flash”的时间和“只擦固件占用区域”的时间分开统计。很多烧录工具默认全片擦除如果固件只占 32KB芯片有 256KB Flash那无辜的擦除操作可能占掉总耗时的一多半。实测中我统一使用了“按固件实际大小擦除”的配置这样两种烧录方式才是在做同一件事。如果你在产线上想继续压时间也可以考虑只擦需要覆盖的扇区前提是旧固件和新固件的边界对齐要好不然会留下脏数据。5. 两种烧录方式的实操拆解光有数据还不够我把两种烧录方式的完整流程都走了一遍记录下每个关键步骤和可以抄作业的配置。这一节内容偏实操你可以直接对照自己的项目落地。5.1 UART bootloader 烧录完整流程UART 烧录的前提是芯片里已经有一段可用的 bootloader。ST 这类厂商的芯片出厂内置 ROM bootloader可以通过 BOOT 引脚进入系统 bootloader 模式如果是你自己写的 bootloader则需要确保它没被后续固件覆盖。我测试用的流程是典型的自研 bootloader 方案MCU 上电先从固定地址读取 bootloader 程序初始化 USART1等待 PC 端发送握手命令PC 端打开串口发送 0xAA 0x55 握手帧MCU 收到后回 0xC1 0xC2表示进入烧录模式PC 端按 256 字节一帧发送固件数据每帧带长度和 CRC32 校验值MCU 每收一帧先校验 CRC校验通过后擦除对应 Flash 页并写入数据然后回 ACK校验失败回 NAK等待重发全部数据发送完成后MCU 读回整段 Flash 做 CRC 校验最终返回成功标志核心的 MCU 端处理逻辑简化之后大致是下面这样#define FRAME_DATA_LEN 256 uint8_t frame_buf[FRAME_DATA_LEN]; while (1) { // 等待帧头 0xAA55 if (uart_recv_uint16() ! 0xAA55) continue; uint16_t len uart_recv_uint16(); uart_recv_bytes(frame_buf, len); uint32_t crc_received uart_recv_uint32(); // 校验 CRC if (crc32(frame_buf, len) ! crc_received) { uart_send_byte(NAK); continue; } // 擦除当前页写入数据 flash_erase_page(current_addr); flash_program(current_addr, frame_buf, len); // 应答 ACK uart_send_byte(ACK); current_addr len; }PC 端用 Python 写的话关键逻辑是这样的import serial ser serial.Serial(COM12, 115200, timeout1) firmware bytearray(open(firmware.bin, rb).read()) # 握手 ser.write(b\xAA\x55) assert ser.read(2) b\xC1\xC2 # 分包发送 for i in range(0, len(firmware), 256): chunk firmware[i:i256] crc zlib.crc32(chunk) 0xffffffff packet b\xAA\x55 len(chunk).to_bytes(2, little) \ bytes(chunk) crc.to_bytes(4, little) ser.write(packet) resp ser.read(1) if resp ! b\x01: # 0x01 表示 ACK raise RuntimeError(fpacket {i} failed)这套流程的可靠性是没问题的但正如前面所说“收一帧-擦写-回 ACK-再发下一帧”的串行模型是性能瓶颈所在。后面优化章节我会给一个双缓冲方案。5.2 JTAG/SWD 烧录完整流程SWD 烧录的工具链成熟得多主流方案有 OpenOCD、STM32CubeProgrammer、J-Flash 等。我这次分别用 OpenOCD 和 STM32CubeProgrammer 各测了一遍两者速度差异不大确认是 4MHz SWCLK 下的正常水平。OpenOCD 的命令行烧录方式openocd -f interface/stlink.cfg \ -f target/stm32f1x.cfg \ -c program firmware.bin 0x08000000 verify reset exit这条命令的含义是加载 ST-Link 作为调试器、加载目标芯片配置、把 firmware.bin 烧录到 0x08000000、校验后复位运行。执行完终端会输出烧录耗时和校验结果。STM32CubeProgrammer CLI 的等价写法STM32_Programmer_CLI -c portSWD modeUR resetHW \ -e all \ -w firmware.bin \ -v这里的-c portSWD modeUR resetHW表示用 SWD 连接硬件复位-e all先全片擦除-w写入固件-v校验。如果你不想全片擦除可以去掉-e all工具会按需擦除。SWD 烧录过程中调试器会先读取目标芯片的 IDCODE 做确认再接管 CPU、初始化 Flash 控制器然后把数据写入 RAM由芯片内的 Flash 加载算法完成写入。整个过程不需要目标板跑任何用户程序即使芯片里是空的也能烧录。5.3 测试过程中我踩过的坑测试中遇到几个坑记录一下。第一ST-Link 的 SWCLK 不是想设多高就多高。我一开始直接设到 8MHz结果连接成功率骤降OpenOCD 经常报SWD communication failure。排查后发现是杜邦线太长、又没有共地信号质量撑不住高速时钟。降到 4MHz 后连接稳定速度损失也不大。如果你的板子是 PCB 走线且走线较短可以再往上拉。第二UART 波特率 115200 下Python 程序的发送间隔如果控制不好容易把 MCU 的接收缓冲区打爆。我在 PC 端每发一包就等 ACK其实天然做了流控所以不会丢帧。但如果你用现成的串口助手直接发 bin 文件没有握手和流控机制经常会在中途丢字节。第三居然有人在量产环境里把 debug 接口的引脚复用成了 GPIO还调用了禁用 JTAG/SWD 的库函数导致后续完全无法连接调试器。这个问题在嵌入式项目里非常经典我把恢复方法放在了下一节。6. 常见报错与排查技巧实录固件烧录的报错信息五花八门但翻来覆去就那么几个高频问题。我把这次测试前后遇到的和网上常被问到的典型场景整理成速查希望对你有实际帮助。报错现象常见原因排查方向STM32 禁用 JTAG 后无法连接代码里调用了 SWJ 引脚释放接口按住复位下载或先擦除芯片error (209040): cant access JTAG chainJTAG 链路中断或 USB-Blaster 异常检查 JTAG 链路、驱动、供电SWD/JTAG communication failure接线、供电、引脚复用、调试器固件降时钟、短接线、查复位cant perform JTAG flash, because OpenOCD server is not running!OpenOCD 服务未正常启动查配置、释放 3333 端口USB-UART 驱动异常FT232R/FT231X驱动版本不对或芯片为仿冒重装正版 VCP 驱动6.1 STM32 禁用 JTAG 后无法连接的恢复这个场景太常见了。有人在初始化代码里写了类似这样的语句GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);目的是把 PA13、PA14、PA15、PB3、PB4 这些调试相关引脚全部释放成普通 GPIO多接几个按键、LED。结果程序烧进去之后SWD 和 JTAG 口全部失效调试器再也连不上 MCU成了“一次性开发板”。恢复方法有好几种按优先级推荐第一种按住板子上的 NRST 复位键不放在 IDE 里点击下载等进度条出现后再松开复位。原理是让 MCU 在复位期间停留在复位状态调试器趁这个窗口抢先把内核接管下来然后再释放复位执行烧录。第二种在 STM32CubeProgrammer 的连接设置里勾选 Connect Under Reset它会自动处理复位时序比手动按键更稳定。第三种如果芯片里还有 UART bootloader 可用直接通过串口把整片 Flash 擦掉恢复正常调试引脚。这个方法不需要额外硬件只需要 USB-TTL 模块。这个坑告诉我们量产固件里如果确定不再需要调试口释放引脚没问题但最好预留一个“UART 救砖入口”或者飞线焊盘否则后期升级、返修都会很难受。6.2 error (209040): cant access JTAG chain这个报错是 Intel/Altera FPGA 工具链Quartus里非常典型的 JTAG 链接错误我在测试 FPGA 板子时也遇到过。错误码 209040 表示无法访问目标 JTAG 链也就是 PC 通过 USB-Blaster 找到不到链路上的器件。排查思路按顺序来看 USB-Blaster 是否被系统识别。设备管理器里如果出现带感叹号的设备先重装驱动检查 JTAG 四根线 TCK/TMS/TDI/TDO 有没有接反、松动、虚焊。这是最容易被忽视的硬件问题确认板卡 JTAG 链路里多个器件是不是菊花链配置如果中间一个器件电源没上整条链都会断有些 FPGA 的 JTAG 引脚会被用户逻辑占用设计上要保证 JTAG 引脚不被非法驱动试试降低 JTAG 时钟频率长线、高负载时高速容易失败我以前遇到过最头疼的一次是板卡上电顺序问题导致某个器件处于高阻态JTAG 链时通时断。最后在电源时序上加了一个延迟问题才根治。这类问题不能只盯软件报错要把链路前后的电源、时钟都检查一遍。6.3 SWD/JTAG communication failure这个报错在做 STM32 开发时出现频率极高。常见原因按出现概率排序SWDIO 和 SWCLK 接反了。ST-Link 和 J-Link 的引脚定义在不同排针上可能顺序不同接线前一定要核对原理图目标板与调试器没有共地。SWD 是电平信号不共地会出现间歇性连接失败MCU 进入了低功耗模式。STOP、STANDBY 模式下调试接口可能被时钟关闭连接不上SWD 引脚被复用成复位、GPIO 等功能调试器固件太旧不认识新芯片排查时建议把 SWCLK 降到 1MHz 试试很多时候高速连接失败但低速能连上说明是信号质量问题。再用短一点的杜邦线或者直接飞到芯片引脚上测试能排除大部分接线干扰。6.4 OpenOCD 未运行与 USB-UART 驱动问题关于cant perform JTAG flash, because OpenOCD server is not running!这常见于 PlatformIO 或 VS Code 集成环境下运行烧录命令时。OpenOCD 是一个独立服务进程如果它的配置文件写错、调试器被别的程序占用或者 3333 端口被其他进程监听服务就起不来自然没法执行烧录。解决步骤先单独在终端跑一次 OpenOCD 命令看有没有报错确认没有其他 OpenOCD 实例占用调试器Windows 下检查 3333 端口是否被占用netstat -ano | findstr 3333看 interface 和 target 配置文件是否匹配你的调试器和芯片至于 FT232R、FT231X、CP2104 这类 USB-UART 芯片主要是驱动问题。Windows 10/11 有时候会自动装一个通用驱动但功能不完整串口列表里看不到或者能看到却打不开。建议去芯片原厂官网下载对应 VCP 驱动FTDI 的芯片就用 FTDI VCP DriverSilicon Labs 的 CP2104 就用 CP210x Universal Windows Driver。另外提醒一句市面上劣质 USB-TTL 模块非常多如果芯片是仿冒的某些驱动会直接禁用设备这个坑最好通过购买正品模块来规避。7. 不同场景怎么选速度不是唯一标准7.1 三类典型场景的推荐方案做完测试后我给产线和研发室推荐了不同的方案组合核心逻辑是“按场景需求选型而不是一味追求最快”。场景烧录方式理由研发调试阶段SWD/JTAG 调试器速度快、可单步调试、可在线查看变量产线量产SWD 高速烧录 离线烧录器兜底节拍优先稳定可靠小批量/售后现场UART bootloader成本低通用 USB-TTL 随处可得研发阶段不用多说调试器是刚需。产线如果对节拍有硬指标SWD 阵列烧录是值得投入的一台电脑挂 8 个 ST-Link同时烧 8 块板1 秒内完成固件写入一天几千台不是问题。售后和现场升级则建议保留 UART 通道因为你不可能让客户人手一个调试器USB-TTL 模块几块钱就能买到远程指导也方便。7.2 想把 UART 烧录变快这些参数值得调如果你的产品因为接口原因只能走 UART也不是只能干等。实测中我把波特率从 115200 拉到 921600 后传输时间能压缩到原来的 1/8整体烧录时间从 4.5 秒降到 1.2 秒左右。再配合下面几个优化UART 也没那么不堪。提高波特率到 460800 或 921600前提是双方晶振精度足够最好用内部 RC 或外部晶振校准把帧长从 256 字节增大到 1024 字节减少 ACK 往返次数用双缓冲MCU 在写上一帧 Flash 的同时通过 DMA 接收下一帧数据让传输和编程流水线化PC 端别用带大量界面刷新的串口工具用一个轻量命令行脚本反而更稳定双缓冲是效果最明显的优化。它的本质是让 MCU 的接收和 Flash 写入并行起来而不是像单缓冲那样“收完一帧、擦写一帧、干等一帧”。我自己改过一版 bootloader支持 1024 字节帧 双缓冲 921600 波特率32KB 固件从 4.5 秒压到了 0.8 秒左右已经非常接近 SWD 的水平。7.3 想把 JTAG/SWD 烧录变快从时钟和工具入手SWD 本身已经很快但如果想在产线上继续压时间可以从三个方向入手一是提高 SWCLK 频率。PCB 走线质量好的情况下STM32 系列可以跑到 8MHz 甚至更高。我建议至少做一次频率扫描找到一个稳定性和速度的平衡点。二是选用更快的调试器。ST-Link/V2 在山寨版里性能参差不齐正品或 J-Link 的高速版本在长传输上有明显优势。如果预算充足J-Link 的 RTT 和高速 Flash 下载体验确实值得。三是升级烧录工具的 Flash 算法。OpenOCD 和 STM32CubeProgrammer 都支持自定义 Flash loader。使用优化过的算法可以减少擦除和编程的等待时间。如果你批量极大甚至可以研究一下离线烧录器一台机器同时烧多块板比任何接口优化都来得直接。另外给一个产线建议烧录完成后一定要做回读校验校验时间最多增加 0.1 秒但能避免大量售后返工。用 STM32CubeProgrammer 的-v参数或者 OpenOCD 的verify关键字都是很成熟的方案。8. 最后分享一点测试之外的心得这次测试做完我最大的感受是很多团队在烧录方案上长期“惯性用串口”不是因为串口好而是因为没有认真测算过时间成本。一台 4.5 秒看起来不多但放在日产 1000 台的产线里就是两个多小时的纯等待。换个调试器 改一版 bootloader投入可能只有几百块换来的产能提升却是持续性的。如果你也想在自己的项目里复现这个对比建议先从固件大小 32KB、波特率 115200 这个配置开始测拿到基线数据后再逐步优化。别忘了把每次测试的软硬件配置记录清楚因为烧录时间和工具、线缆、芯片型号强相关跨平台比较时差异会很凌乱。另外还想强调一点高速 SWD 调试器在研发阶段就能帮你省下大量时间建议所有嵌入式开发板都预留标准的 2.54mm SWD 排针并且不要轻易在固件里禁用调试口。哪怕只是为了“以防万一”这个习惯也值回票价。