第12章 · 播客 第4集
嵌入式系统设计 · 交叉开发环境与调试方法上半场
🎙️ 本集播客:第4集:为什么嵌入式开发必须交叉——宿主机、目标机和连接三件套;交叉编译怎么生成 COFF 与 ELF 目标文件;调试方法上半场:最原始的直接调试法、插桩法(调试监控器)的四条缺点,以及为救插桩法而生的 ROM 仿真器。 语音由微软 Edge 神经网络语音预生成(女声·晓伊,男声·云希)。点击下方任意对话可直接从该句开始播,当前句朗读时下一句已预先加载,无缝衔接。
明
阿明
上集预告说的交叉平台开发方法 CPD,就是这个集的主角?先说说为什么嵌入式不能像写桌面程序那样在自己电脑上开发?
雅
小雅
因为目标机资源受限,跑不动开发工具。所以嵌入式系统的软件开发采用交叉平台开发方法 Cross Platform Development,CPD,即软件在一个通用的平台上开发,而在另一个嵌入式目标平台上运行。这个用于开发嵌入式软件的通用平台通常叫作宿主机系统,被开发的嵌入式系统称为目标机系统。反过来,当软件执行环境和开发环境一致时,开发过程称为本地开发 ND,Native Development。
明
阿明
练习题问「交叉平台开发方法是指什么」,四个选项里有「在宿主机上开发,目标机上运行调试」,就是它了吧?
雅
小雅
就选它,其他三个选项「在目标机上直接开发和调试」「仅在宿主机上开发和运行」「通过网络远程开发」全是坑。一个典型的交叉平台开发环境通常包含三个高度集成的部分:第一,运行在宿主机和目标机上的强有力的交叉开发工具和实用程序;第二,运行在目标机上的高性能、可裁剪的实时操作系统;第三,连接宿主机和目标机的多种通信方式,例如以太网、串口线、ICE 在线仿真器或 ROM 仿真器等。
明
阿明
宿主机上都有什么工具?
雅
小雅
宿主机提供的基本开发工具是交叉编译器、交叉链接器和源代码调试器;作为目标机的嵌入式系统则可能提供一个动态装载器、链接装载器、监视器和一个调试代理等。在目标机和宿主机之间有一组连接,通过这组连接程序代码映像从宿主机下载到目标机,这组连接同时也用来传输宿主机和目标机调试代理之间的信息。
雅
小雅
交叉编译的流程要能复述:交叉编译器将用户编写的 C、C++、Java 源代码文件,根据目标机的 CPU 类型生成包含二进制代码和程序数据的目标文件;在此过程中交叉编译器会建立一个符号表,包含所产生的目标文件中指向映像地址的符号名。通常还可以使用归档工具将这些目标文件收集到一起形成一个库;最后,链接器将这些目标文件作为输入来产生一个可执行的映像。一般用户会先编辑一个链接脚本文件,用来指示链接器如何组合和重定位各个代码段以便生成最终文件。
明
阿明
目标文件的格式有讲究吗?
雅
小雅
有,必背:目前嵌入式系统中常用的目标文件格式是 COFF,Common Object File Format,公共对象文件格式,和 ELF,Executable Linking Format,可执行链接格式。另外,一些系统还需要有一些专门的工具将上述格式转换成二进制代码格式才可使用。还有一句考点,通常一个目标文件包含四类内容:一是关于目标文件的通用信息,如文件尺寸、启动地址、代码段和数据段;二是机器架构特定的二进制指令和数据;三是符号表和重定位表;四是调试信息。
明
阿明
COFF、ELF 加「目标文件四内容」,记下了。开发环境搭好就该调试了,原文列了好几种调试方法?
雅
小雅
五种:直接测试法、调试监控法、在线仿真法、片上调试法及模拟器法。先记住这个五件套名单,练习题常问「以下哪种不属于嵌入式常用调试方法」。先说最原始的:直接调试法,就是将目标代码下载到目标机上让其执行,通过观察指示灯来判断程序的运行状态,是嵌入式系统发展早期采用的方式。
雅
小雅
它的基本步骤六步:在宿主机上编写程序;在宿主机上编译、链接生成目标机可执行程序代码;将可执行代码写入目标机的存储器中;在目标机运行程序代码;判断程序的运行情况,如有错误则纠正错误,重复以上步骤直到正确为止;最后将可执行代码固化到目标机,开发完成。原文的评语很扎心:程序运行时产生的问题只有通过检查源代码来解决,因而开发效率很低。
明
阿明
看灯猜状态,想想就崩溃。后来升级成什么样了?
雅
小雅
升级版是调试监控法,也叫插桩法。目标机和宿主机一般通过串行口、并行口或以太网相连接;采用这种方法需要在宿主机的调试器内和目标机的操作系统上分别启动一个功能模块,然后通过这两个功能模块的相互通信来实现对应用程序的调试。在目标机上添加的模块叫作桩,也叫调试服务器或调试监控器。桩有两个作用:其一,监视和控制被调试的程序;其二,跟宿主机上调试程序通信,接收控制指令,返回结果。
雅
小雅
调试的时候,宿主机上的调试器通过连接线路向调试监控器发送各种请求,实现目标机内存读写和寄存器访问、程序下载、单步跟踪和设置断点等操作,宿主机的请求和目标机的响应都按照预定的通信协议进行交互。插桩法能设断点能单步,相对于直接测试法明显提高了开发效率、降低了调试难度、缩短了开发周期、有效降低了开发成本。
明
阿明
那练习题说插桩法的主要缺点是「不能响应外部中断,难以调试实时性问题」,对应原文哪里?
雅
小雅
插桩法有四条缺点,这条是第三条。完整四条:第一,调试监控器本身的开发是个技术难题;第二,调试监控器在目标机中要占用一定的系统资源,如 CPU 时间、存储空间及串口或网络接口等外设资源;第三,调试时不能响应外部中断,对有时间特性的程序不适用——这就是题目的答案句;第四,被调试的程序实际上在调试监控器所提供的环境中运行,这个环境可能会与最终运行环境有一定差异,这种差异有可能导致调试通过的程序最后仍不能运行。
明
阿明
占了资源、关了中断、环境还可能失真,难怪要改良。
雅
小雅
于是出现了改良方法:ROM 仿真器法。ROM 仿真器可以被认为是一种用于替代目标机上 ROM 芯片的硬件设备,一端跟宿主机相连,一端通过 ROM 芯片的引脚插座与目标机相连。对嵌入式处理器来说,ROM 仿真器像是一个只读存储器;而对宿主机来说,像一个调试监控器。它的地址可以实时映射到目标机的 ROM 地址空间里,所以可以仿真目标机的 ROM。
雅
小雅
ROM 仿真器在目标机和宿主机之间建立了一条高速信息通道,典型应用就是跟插桩法相结合形成功能更强的调试方法,有四条优点:第一,不必再开发调试监控器;第二,通过 ROM 仿真器上的串行口、并行口或网络接口与宿主机连接,不必占用目标机上的系统资源;第三,ROM 仿真器代替了目标机上原来的 ROM,不必占用目标机上的存储空间来保存调试监控器;第四,即使目标机本身没有 ROM,调试依然可以进行,并且不需要使用专门工具向 ROM 写入程序和数据。
明
阿明
等于把「占资源」和「环境差异」两个坑都填了。
明
阿明
等于把「占资源」和「环境差异」两个坑都填了。那 ROM 仿真器还有什么要背的?
雅
小雅
把身份句再钉一遍:对嵌入式处理器来说,ROM 仿真器像是一个只读存储器;而对于宿主机来说,像一个调试监控器。这句双向身份是判断题的改写点,比如改成「对宿主机来说像只读存储器」,方向反了就是错。它的典型应用是与插桩法相结合,形成一种功能更强的调试方法。
明
阿明
插桩法的连接方式和直接调试法的差别,我总结下:插桩法目标机和宿主机通过串行口、并行口或以太网相连接,全程有调试器交互;直接调试法连交互都没有,看灯。
雅
小雅
总结到位。再把容易漏的一个小点补上:插桩法开发的基本步骤有七步,和直接调试法六步相比,多了「使用调试器进行调试」和「在调试器帮助下定位错误」两步,程序下载之后不是直接固化,而是先进调试循环。简答题让你列插桩法步骤,按写源代码、编译链接、下载、调试、定位错误、修改重复、固化七步答。
明
阿明
宿主机和目标机之间那组连接,除了下载代码还干什么?
雅
小雅
双职能:一是程序代码映像从宿主机下载到目标机,二是传输宿主机和目标机调试代理之间的信息。判断题问「交叉编译环境的连接只用于下载程序映像」,错,还传调试信息。目标机这边可能提供的东西也记一下:动态装载器、链接装载器、监视器和一个调试代理等。
雅
小雅
本集必背:嵌入式软件开发用交叉平台开发方法 CPD,在宿主机开发、目标机运行,执行环境和开发环境一致时叫本地开发 ND;交叉开发环境三部分是交叉开发工具、目标机上的可裁剪实时操作系统、宿主机与目标机的连接;宿主机三工具是交叉编译器、交叉链接器、源代码调试器;目标文件格式 COFF 和 ELF。五种调试方法:直接测试法、调试监控法、在线仿真法、片上调试法、模拟器法。直接调试法看指示灯、效率低;插桩法的桩有两个作用——监视控制被调试程序、跟宿主机通信,缺点四条,核心一条是调试时不能响应外部中断;ROM 仿真器替代 ROM 芯片,对处理器像只读存储器、对宿主机像调试监控器。
明
阿明
编译流程里归档和链接脚本的顺序,我理下:编译器根据目标机 CPU 类型生成目标文件并建符号表,归档工具把目标文件收进库,链接器最后产出可执行映像,链接脚本指挥它怎么组合重定位。
雅
小雅
顺序完全正确,再补一句可考的:链接器还可以将多个目标文件组合成一个更大的重定位目标文件或一个共享目标文件。「根据目标机的 CPU 类型」这几个字是交叉编译的定义性短语,判断题把它改成「根据宿主机 CPU 类型」,一眼错。
明
阿明
上半场结束,还剩在线仿真、片上调试、模拟器三种。
雅
小雅
下一集就把它们仨讲完:在线仿真器 ICE 凭什么贵还受欢迎,片上调试的 BDM 两种运行模式——调试模式和执行模式怎么考,JTAG 都用在哪些芯片上,模拟器的指令级和系统调用级又怎么分。