尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

嵌入式主板免测试板自检:调试口、JTAG边界扫描与寄存器脚本

嵌入式主板免测试板自检:调试口、JTAG边界扫描与寄存器脚本 刚拿到打样回来的主板5 片摊在桌面上还没来得及庆祝现实问题就来了怎么在不专门做一块测试板、也不写一整套复杂测试驱动的前提下快速判断每片主板是不是真的活着、每一路 IO 和接口是不是真的通。做过主板测试的人都知道传统路子是给每一版设计配一套专属测试工装上面挂满探针和治具再配一套专门的测试固件板子一改版工装和代码跟着重来。这套流程对量产线是合理的但对研发阶段、小批量验证、甚至个人玩家自己设计的 TC264 主控板、小蜜蜂主板这类嵌入式主板来说成本高得离谱。这篇就聊我自己现在更常用的思路把测试这件事从再造一块硬件和重写一套驱动里解放出来靠主板自带的调试口、边界扫描能力加上一套能跨板复用的自检框架把绝大多数连接性和功能性问题测出来。1. 先算清专属测试板 专属驱动这笔账到底亏在哪很多人一说到主板测试第一反应就是做块测试板不就完了。这个思路在量产环节没问题但放到研发和小批量场景里它隐藏的时间成本往往被严重低估。我在实际项目里反复算过这笔账结论是对迭代频繁的板子专属测试工装是最不划算的一种投入。1.1 一块专属测试板吃掉的不只是钱先看硬件层面。一块测试板看起来简单无非是把探针、限流电阻、上拉下拉、负载电路摆上去但真做起来它必须跟被测主板的接口定义严格对应。主板一改版——哪怕只是把某个排针从 2.0mm 间距换成 1.25mm或者把 CAN 收发器的位置挪了——测试板的机械结构和走线就得重做。研发阶段的板子改版有多频繁做过嵌入式的人心里都有数通常三五个版本下来测试板的迭代次数比主板本身还多。再说治具。探针治具讲究压合力度、共面度、接触电阻稍微松一点就出现这片板子测着不通、换个位置又通了的假故障。我见过不少团队在这上面耗掉大量时间最后测出来的数据自己都不敢信。所以对研发阶段来说专属测试板真正的成本不在物料而在于它把设计主板和设计测试变成了两个必须同步迭代的项目任何一个卡住都会拖慢整体节奏。1.2 测试驱动才是更深的那口坑比测试板更麻烦的是测试驱动。传统做法是给被测主板烧一套专用测试固件里面针对每一路 IO、每一个外设都写好激励和判定逻辑。听起来很直接问题在于这套固件和硬件是强耦合的引脚映射改了驱动得改外设型号换了驱动得改连芯片的时钟树配置变了都可能让原本能跑的测试代码卡在初始化里。更现实的问题是你为了测主板等于要先把主板的底层驱动全部调通一遍。这就陷入一个循环——测试驱动本身需要主板能正常工作才能跑而主板能不能正常工作恰恰是你要测的。我早期的做法是分开写一个极简测试固件绕过业务层只做引脚翻转和寄存器读写但即便是这样每换一颗芯片、每换一套开发环境这套极简固件也得重写一遍。所以真正值得追求的是让测试手段尽量贴着芯片本身的能力走——芯片自带的调试接口、芯片自带的边界扫描逻辑、芯片自带的启动自检能力这些东西不依赖你写多少业务代码也不依赖外部工装。下面几节就围绕这个思路展开。1.3 什么样的场景适合零测试板路线先把适用范围说清楚免得误导。这套思路最适合研发阶段的样板验证、小批量试产的首件确认、个人开发者的板子自检、以及需要频繁改版的迭代验证。它不太适合已经定型的高产量产线终检那种场景探针床的效率依然无可替代。两者的区别在于量产追求的是单位时间测得多、测得稳而研发追求的是改版后能立刻测、问题能定位到具体网络。我下面讲的所有方法都是冲着后一个目标去的。2. 把调试口当测试口现成的调试探针能顶掉大半个测试板主板只要带一颗 MCU 或 SoC就几乎一定有调试接口——ARM 系一般是 SWD 或 JTAGAURIX 这类是 DAP某些处理器是 cJTAG。很多人把调试口只当成下载程序和单步调试的工具其实它本身就是一根通向芯片内部几乎所有资源的管子用好它测试板上的很大一部分功能可以直接省掉。2.1 调试接口本来就是全芯片的后门调试探针能做的事远超下载固件它可以暂停 / 运行内核、读写任意内存地址、访问所有外设寄存器、甚至在某些芯片上直接控制 GPIO 的输入输出。这意味着什么意味着你不需要主板跑起任何应用代码只要芯片供电正常、调试链路连上了探针就能直接去戳寄存器把某一路 GPIO 拉高、把某个 ADC 通道读出来。我常用的做法是这样的先把主板通电探针连上直接用调试器的命令行或脚本访问寄存器。比如要确认某颗 LED 的驱动引脚是不是焊好了我不写任何固件而是通过调试器把该引脚对应的 GPIO 方向寄存器设为输出、输出数据寄存器写 1看 LED 亮不亮。亮说明引脚到 LED 的整条通路没问题不亮再进一步区分是引脚没焊、电阻断路还是 LED 装反。整个过程不需要一行测试驱动只需要知道这颗芯片的 GPIO 寄存器地址。2.2 探针选型与接线别在第一步翻车探针这块按芯片选。ARM Cortex-M 用 CMSIS-DAP、J-Link、ST-Link 都行AURIX TC26x / TC27x 一般用 DAP miniWiggler 或兼容的 DAP 探针RISC-V 用支持 RISC-V 调试的探针。选型上唯一要提醒的是别图便宜买那种只支持单一芯片的杂牌探针跨项目会很难受。接线是第一个大坑。调试接口一般至少四根SWCLK/SWDCK、SWDIO/SWDAT、GND、以及可选的复位。新手最容易犯的错是只接三根信号线忘了接 GND或者把探针的供电脚和主板的供电脚同时接上导致对灌。我的习惯是调试探针只做信号连接主板自己独立供电探针不对外供电除非主板确实需要探针供电的场景。这样能避免一大堆莫名其妙的连不上。还有一点值得强调调试链路的走线要短、要远离功率器件。TC264 这类常用于电机控制的主板板上有大量 PWM 和功率级如果调试线从功率区旁边绕过很容易出现偶尔掉线。我一般会把调试排针放在主板边缘走线尽量直必要时加地线包围。2.3 用调试口验证芯片活着的最快路径拿到一片新板我最先做的不是测外设而是确认三件事供电对不对、时钟起没起、内核能不能被探针挂住。这三件事只要用探针就能验证不需要任何固件。具体操作给主板上电用万用表或者示波器确认各路电源在正常范围这一步是模拟量探针替不了然后让探针连接目标。如果探针能识别到芯片 ID、能读到内核寄存器基本说明供电、时钟、复位、调试链路都是通的这颗芯片活着。如果连芯片 ID 都读不到问题几乎一定在供电、时钟、复位或调试走线这四件事里跟你的应用代码没关系。这一条判断极大缩小了排查范围是我做板子自检时最先建立的分水岭。3. 边界扫描把连接性测试从针床搬到 JTAG 链路上如果说调试口解决的是芯片内部资源怎么访问那边界扫描Boundary ScanIEEE 1149.1解决的就是另一件事——芯片引脚到板级网络之间的连接性。这恰恰是测试板最擅长、也最贵的那部分功能而边界扫描能在很大程度上把它替代掉。3.1 边界扫描到底在测什么支持 JTAG 边界扫描的芯片每一个 IO 引脚内部都串了一个边界扫描单元这个单元可以截获引脚的输出、也可以强加一个值到引脚上。所有芯片的边界扫描单元串成一条链通过 JTAG 的 TDI/TDO/TCK/TMS 四根线访问。你可以把它想象成每个引脚都装了个可以远程控制的开关和探针你不用真的在板子上扎探针就能读到某个引脚当前的逻辑电平、或者强制它输出高低。它能测出来的典型故障包括引脚虚焊、网络断路、相邻网络短路、上下拉异常。测不了的包括模拟量精度、高速信号完整性、以及不参与边界扫描的器件。把这两句话记住你就知道什么时候该用它、什么时候别指望它。3.2 上手流程BSDL 文件是钥匙边界扫描能不能用关键看芯片厂商有没有提供 BSDL 文件。BSDL 是一份用 VHDL 语法描述的芯片引脚与边界扫描单元映射文件几乎所有正经的 MCU、FPGA、CPLD 都会提供。拿到 BSDL 之后流程大致是找出主板上所有支持边界扫描的器件按 JTAG 链的顺序把它们串起来。给每个器件准备对应的 BSDL 文件。用边界扫描工具开源的有 UrJTAG商业的也有专门软件读取链上的器件 ID确认链路连通。执行 EXTEST 指令让器件把边界扫描单元的值驱动到引脚上同时读回相邻器件引脚的状态判断网络通断。这里有个细节必须提前设计边界扫描要求被测网络至少有一端能驱动、另一端能读取。如果两个器件之间只是普通相连你测不出中间断没断因为两端在同一个网络上电平一样。所以电路设计阶段最好给关键测试网络加一个隔离点或者让两端的引脚在测试模式下朝相反方向驱动。这一点如果设计时没考虑后期只能靠拆掉某个器件来凑得不偿失。3.3 什么时候别硬上边界扫描边界扫描不是万能的。第一它只测数字逻辑连接模拟电路和高频信号它管不了。第二它需要芯片支持并开放 BSDL有些低成本芯片不提供。第三链路越长、器件越多测试向量的生成和维护越麻烦板子上五六个支持边界扫描的器件串一起光理清楚顺序就能劝退一部分人。我的经验是把边界扫描用在器件互联密集、网络多、用探针测很费劲的主板上比如那种一堆排针加一堆外设芯片的扩展主板。如果板子上只有一颗 MCU 加几个简单外设用调试口直接点 IO 反而更快。工具要用来省事不能让工具变成新的负担。4. 用脚本驱动寄存器不写完整驱动也能让主板动起来前面说的调试口和边界扫描本质上都是绕过应用层来碰硬件。这一节讲怎么把这套思路工程化——用脚本加调试器直接操控寄存器把一块主板从没跑任何程序测到关键外设通了。4.1 脚本加调试器的工作方式裸金属编程里读写寄存器通常是写*(volatile uint32_t*)0x40000000 value;这样的代码然后编译、烧录、运行。而脚本化的方式是把这套动作放到调试器侧调试器提供 API能直接对目标内存做读写。Python 生态里有 pyOCD配合 CMSIS-DAP 探针一行target.write32(addr, value)就能写寄存器OpenOCD 提供了完整的命令接口也能用脚本调用。这样做的好处是零编译、零烧录、即时反馈。改一个引脚状态不用重新编译固件再等下载直接脚本执行就生效。对快速验证连接性来说这比任何测试固件都快。当然脚本化不适合跑复杂时序逻辑但恰恰连接性测试不需要复杂时序。4.2 一个实测例子点灯 读回我把实际用的脚本骨架抽象成下面这样以常见的 Cortex-M 举例寄存器地址只是示例实际要查手册import pyocd from pyocd.core.helpers import ConnectHelper # 连接探针和芯片 session ConnectHelper.session_with_chosen_probe() session.open() target session.target target.halt() # 使能 GPIO 时钟示例寄存器 GPIO_CLK_EN 0x40021018 target.write32(GPIO_CLK_EN, target.read32(GPIO_CLK_EN) | (1 2)) # 把 PA5 配置为推挽输出 GPIOA_MODER 0x40020000 val target.read32(GPIOA_MODER) target.write32(GPIOA_MODER, (val ~(3 10)) | (1 10)) # 拉高 PA5观察 LED GPIOA_ODR 0x40020014 target.write32(GPIOA_ODR, target.read32(GPIOA_ODR) | (1 5))这段脚本跑完如果 LED 亮了就证明从芯片引脚到 LED 的整条链路是通的。想测按键就把引脚配成输入脚本轮询读回来判断按下状态。想测 UART就配置波特率后往发送寄存器写数据外部用 USB 转串口接收。整套操作不需要编译任何固件改哪个引脚改脚本里的位就行。4.3 把重复动作封装成可复用的测试动作库脚本化的价值在复用。第一次为某颗芯片查清楚寄存器地址后我把这些地址和操作封装成一个board_test模块里面按功能分成power、gpio、uart、adc、can几个函数。下一块板子只要芯片一样脚本改个引脚映射常量就能用。这就把每块板子写一套测试驱动变成了维护一个测试动作库成本从每次重写降到了每次改配置。这一点对频繁改版的团队尤其重要。你把寄存器操作和业务绑定解耦之后测试代码的生命周期就不再跟着主板版本走而是跟着芯片型号走。同一颗芯片的项目复用同一个库越用越顺手新项目几乎是拿来就测。5. 一份能跨板复用的上电自检清单工具和手段讲完了最后落到到底测哪些项。我这些年攒了一份自检清单结构上从电源到内核再到外设逐层递进任何一块新主板都能按这个顺序过一遍。下面这份清单是我按反复实践整理的顺序本身就是排查逻辑。5.1 电源域与上电时序一切从电源开始。多电压系统比如同时有 5V、3.3V、1.2V 内核必须确认上电顺序符合芯片要求否则可能内核还没起、IO 就先上电导致漏电流甚至闩锁。我的做法是上电瞬间用示波器多通道同时抓各路电源的上升沿看顺序和斜率。常见的判定标准是各路电源稳态值在规格内、上电斜率不过缓也不过陡、没有明显的过冲。这里有个容易被忽略的点空载上电和带载上电可能不一样。有些电源芯片在空载时输出飘高一带负载就掉下来。所以测电源最好在主板已经装上主要器件、甚至外设都接好的状态下测别只测一块裸板。5.2 时钟、复位与内核唤醒电源正常之后接着确认时钟和复位。用示波器或者频率计确认晶振起振、频率准确再看复位信号是不是在电源稳定后才释放。这一步如果出错探针是连不上芯片的会表现成读不到芯片 ID。时钟复位都对了让探针连接并暂停内核读一下内核的系统寄存器确认芯片真的在跑。这个阶段能过说明主板最核心的供电时钟复位调试链路四要素齐了可以往下测外设。5.3 外设连通性从 IO 到总线外设这块我按由简到繁排测试项手段判定标准常见故障GPIO 点灯脚本切输出LED 亮灭可控虚焊、LED 反装按键输入脚本读输入寄存器按下状态变化上拉缺失、按键短路UART 回环脚本发数据 外部接收收发一致收发接反、波特率错SPI 回环短接 MOSI/MISO收到发送内容片选悬空CAN 回环两板互发或自环帧收发正常收发器方向错、终端电阻ADC 采样加已知电压读数在误差内分压电阻错、基准未接存储读写脚本写读内存数据一致地址线虚焊、片选错这张表我基本每个项目都会覆盖到具体做哪几项看主板带了什么外设。每测一项就勾掉一项最后没勾上的地方就是问题所在非常直观。5.4 把清单做成可勾选的验证表清单本身要能被复用我的习惯是把上面这些项做成一份带通过/失败/备注三列的表格每块板子测完填一遍。多块样板对比哪块板子在哪一项异常一目了然。批次性的故障多块板子同一项失败多半是设计或焊接工艺问题个别性故障多半是单板装配问题这个区分对定位根因非常关键。6. 实测踩坑那些让你误判主板坏了的测试陷阱最后这一节是我认为最有价值的部分——很多所谓的主板坏了其实是测试方法本身的问题。下面这几个坑我都亲自踩过写出来帮大家少走弯路。6.1 探针接触不良制造的假故障调试连接不稳是最常见的假故障来源。表现是同一块板子探针稍微动一下就从能连变成不能连然后你就开始怀疑芯片焊没焊好。我的排查顺序是先换一根已知好的调试线和探针再确认调试排针焊点最后才动芯片。实测下来绝大多数连不上都是线材或者探针接触问题不是芯片问题。另外一个现象是读寄存器读回 0xFFFFFFFF 或 0x00000000很多人以为芯片挂了其实往往只是连接丢了、读了个空。遇到这种读数先别下结论重新连接一次再看。6.2 复位状态和未初始化引脚带来的误判芯片刚上电时很多引脚处于复位默认状态可能是高阻、可能是内部上拉。如果你不先配置方向寄存器就直接去读读到的值和实际你想测的状态可能完全不是一回事。我就吃过这个亏测一个按键输入读回来一直是高以为按键坏了后来发现是那个引脚默认内部上拉、而按键另一端接的是高电平逻辑刚好反了。配置对方向、搞清楚默认状态再下结论。还有一种情况是外设时钟没使能。你在脚本里写寄存器写进去读回来发现没变化第一反应是芯片坏了其实是没打开该外设的时钟门控。这类问题属于寄存器写了没反应的经典原因查手册确认时钟使能位是第一件事。6.3 别把配置问题当成硬件故障这是我见过最多的误判。CAN 通信不通可能是终端电阻没装、可能波特率不匹配也可能是收发器方向引脚没配置I2C 读不到从机可能是上拉电阻缺失也可能是地址搞错。这些全是配置或者外围电路问题跟主板本身的质量无关。我的处理准则是任何通信不通先从物理层往上查别一上来就怀疑 MCU。先看电平对不对、再看时序有没有、最后才看协议。按这个顺序查能排除掉大部分虚假的硬件故障。6.4 给测不准留一个缓冲最后一个经验是心态上的。测试本身有误差模拟量的测量尤其如此。ADC 读数偏个几个 LSB 很正常别拿出厂图纸的精度要求去卡研发阶段的自检。测试的目的是判断通不通、活没活、能不能进入下一阶段不是给主板出质检报告。把标准定得贴合目的既省时间又不会被一堆无意义的误差干扰判断。等你对某块主板有疑问再针对那一项做精细测量这样效率最高。这套不专门做测试板、不专门写测试驱动的路子我从研发阶段用到现在最大的感受就是把测试的重心从造工具转移到用芯片自己的能力。调试口、边界扫描、脚本化寄存器操作这三样东西组合起来足以覆盖研发和小批量场景下绝大多数主板自检需求剩下的精细测量再交给专门的仪器。主板改版的时候只要芯片没换我那套脚本和清单基本原样能用改几个引脚映射就能上省下来的时间都够多测好几版板子了。
返回列表