深入解析TMS320F2837xD双核MCU的启动流程与DMA配置实战

📅 2026/7/21 16:28:54
深入解析TMS320F2837xD双核MCU的启动流程与DMA配置实战
1. 项目概述从复位到运行双核MCU的启动奥秘与数据搬运的艺术在工业电机驱动、数字电源或者任何对实时性要求苛刻的嵌入式系统中TMS320F2837xD这类双核C2000微控制器扮演着“大脑”的角色。但你是否想过当按下复位键或上电的瞬间这个“大脑”是如何从一片混沌中苏醒并精确无误地开始执行你编写的代码的更进一步当ADC以每秒数百万次的速率采样或者需要将海量数据从内存搬移到通信接口时如何保证CPU的计算能力不被琐碎的数据搬运任务拖累这两个问题的答案正是启动流程与直接内存访问DMA。前者是系统可靠性的基石后者是系统性能的倍增器。对于2837xD这样的双核器件启动流程还涉及两个核心如何协同“起床”而DMA则要处理更复杂的多主控总线仲裁。理解它们意味着你能从“代码编写者”进阶为“系统架构师”真正掌控硬件的每一个时钟周期。我接触过不少工程师他们能熟练使用库函数却在系统异常复位、程序“跑飞”或者DMA传输偶尔“丢包”时束手无策。究其根源往往是对底层机制一知半解。本文将带你深入2837xD的骨髓拆解其ROM启动代码的数据流格式、多核间引导的“暗号”IPC并剖析DMA引擎如何像一位高效的“搬运工”在后台无声无息地完成数据调度。我们会绕过那些手册里冰冷的寄存器列表用实际案例和操作逻辑让你不仅知道要配置什么更明白为什么要这样配置以及配置错了会怎样。2. 启动流程深度解析双核的“开机自检”与引导协议TMS320F2837xD的启动过程远非“从Flash的0x080000地址取指令”那么简单。它是一个由固化在ROM中的引导加载程序Bootloader主导的、高度可配置的、且支持双核协同的复杂序列。这个过程决定了CPU1和CPU2从哪里获取最初的代码以及它们之间如何建立最初的通信。2.1 启动模式Boot Mode的决策逻辑芯片上电或复位后CPU1的Boot ROM代码首先运行。它做的第一件关键事就是读取特定的硬件引脚状态或OTP一次性可编程存储器中的BOOTCTRL寄存器以决定本次的启动模式。这是整个启动流程的“总开关”。核心决策流程如下引脚采样在特定的时钟周期内采样一组GPIO引脚如GPIO72-GPIO84的电平。这些引脚的状态被锁存到BOOTDEF寄存器中。OTP检查检查OTP中的BOOTCTRL寄存器是否已被编程。如果已编程非默认值则OTP配置具有最高优先级将覆盖引脚采样的结果。模式解码根据最终确定的BMODE值选择对应的引导源。输入材料中的表格Table 4-29至4-37详细列出了所有选项。例如BMODE0x0B从Flash Sector A启动入口地址为0x0008 0000。BMODE0x0A从RAM启动入口地址为0x0000 0000。这常用于仿真调试。BMODE0x01从SCI-A使用GPIO84/85启动即通过串口下载程序。BMODE0x02等待模式Wait Boot。CPU1的Boot ROM会进入一个循环等待通过IPC进程间通信寄存器接收来自CPU2或仿真器的命令。这是双核协同启动的关键。实操心得模式选择的“潜规则”在开发板上我们常用跳线帽设置GPIO电平来选择模式。但在产品中强烈建议使用OTP固化BOOTCTRL。因为引脚采样易受外部电路上电时序、噪声干扰可能导致启动模式随机化造成“有时能启动有时不能”的玄学问题。烧写OTP是一次性的务必在实验室充分验证后再进行。2.2 数据流Data Stream结构Bootloader的“食谱”当选择从外设如SCI、SPI引导时Bootloader期望主机如上位机发送一个特定格式的数据流。输入材料中的“Example 4-1”就是一个经典的8位数据流示例。理解这个结构是编写上位机引导程序或调试引导失败的基础。让我们逐行拆解这个例子AA 08 ; 关键字 (Key Value)用于同步和验证数据流开始。 00 00 00 00 ; 8个保留字 (Reserved Words)必须为0。 ... 3F 00 00 80 ; 入口地址 (EntryAddr): 0x003F8000。引导完成后PC将跳转至此执行。 05 00 ; 第一个数据块大小 (Block Size): 5个16位字。 3F 00 10 90 ; 第一个数据块的目的地址 (Destination Addr): 0x003F9010。 01 00 ; 数据内容0x0001, 0x0002, 0x0003, 0x0004, 0x0005。 02 00 03 00 04 00 05 00 02 00 ; 第二个数据块大小: 2个16位字。 3F 00 00 80 ; 第二个数据块的目的地址: 0x003F8000。 00 77 ; 数据内容0x7700, 0x7625。 25 76 00 00 ; 块大小为0标志数据流结束。关键点解析字节序C28x内核是小端模式Little-Endian。在数据流中多字节数据如地址、块大小是低字节在前。例如入口地址3F 00 00 80在内存中解释为0x003F800080 00是低16位00 3F是高16位组合后字节交换。块Block结构数据流由一个或多个块组成。每个块包含“大小-目的地址-数据”三部分。这种结构允许将代码或数据灵活地装载到内存的不同位置例如将初始化代码段.cinit和数据段.data分别装载到RAM的不同区域。入口地址最后一个装载的、且地址通常与入口地址一致的数据块其开头就是第一条执行指令。本例中第二个块被装载到0x3F8000且该地址被指定为入口地址因此CPU将从0x3F8000开始执行即执行指令0x7700这很可能是一条LB跳转指令。避坑指南数据流生成与校验在TI的编译器CCS中hex2000工具可以将输出的.out文件转换为这种数据流格式通常称为.hex或.dat格式。你需要确保链接器命令文件.cmd正确划分了内存段。一个常见的错误是代码段.text被链接到了Flash地址如0x080000但在生成引导数据流时却希望它被搬到RAM执行。这需要在.cmd文件中使用LOAD和RUN命令明确指定装载地址和运行地址并由hex2000在转换时自动处理重定位信息生成包含多个块的数据流。2.3 双核引导Dual-Core Boot与IPC机制2837xD的双核并非完全独立启动。默认情况下CPU1是主引导核心CPU2在复位后处于等待状态。CPU1的Boot ROM负责决定CPU2如何启动这是通过Boot IPC寄存器实现的。CPU2的启动路径有三种独立外设引导CPU1配置好GPIO复用并将外设控制权“移交”给CPU2通过CPUSEL寄存器然后通过IPC命令通知CPU2从该外设启动。这要求CPU2的应用程序镜像与CPU1不同。从共享内存引导CPU1通过DMA或其他方式将CPU2的程序代码从Flash或接口拷贝到共享RAM如GSx RAM或CPU2toCPU1 MSGRAM中然后通过IPC命令通知CPU2从RAM的特定地址启动。从Flash引导CPU1通过IPC命令C1C2_BROM_IPC_EXECUTE_BOOTMODE_CMD并设置C1TOC2BOOTMODE 0xB命令CPU2直接从Flash Sector A启动。此时两个核心执行同一份存储在Flash中的代码镜像但通过链接器分配到不同的内存区域运行。IPC命令详解输入材料中的Table 4-40和4-41是Boot ROM IPC的“指令集”。它允许一个核心的应用程序或Boot ROM让另一个核心的Boot ROM执行一些底层操作。命令流程发送核心如CPU1将目标地址写入IPCRECVADDR寄存器将数据写入IPCRECVDATA寄存器最后将命令码写入IPCRECVCOM寄存器。接收核心CPU2 Boot ROM检测到命令寄存器被写入解析并执行相应操作如写内存、读内存、跳转。接收核心将执行状态成功/失败码写回IPCLOCALREPLY寄存器发送核心通过轮询此寄存器或检查C1TOC2IPCFLG标志位来确认命令完成。关键命令举例C1C2_BROM_IPC_DATA_WRITE_32 (值6)CPU1让CPU2 Boot ROM向指定地址写入一个32位数据。常用于为CPU2设置启动参数。C1C2_BROM_IPC_BRANCH_CALL (值17)CPU1让CPU2 Boot ROM跳转到指定地址开始执行。这是启动CPU2最直接的方式。C1C2_BROM_IPC_EXECUTE_BOOTMODE_CMD (值19)CPU1命令CPU2 Boot ROM根据C1TOC2BOOTMODE寄存器的值自行执行相应的引导加载程序如SCI Boot、SPI Boot。注意事项IPC通信的“握手”与状态检查在进行关键操作如分支跳转前务必检查CPU2 Boot ROM的状态。通过读取C2TOC1BOOTSTS寄存器地址0x0000 0002可以确认CPU2 Boot ROM是否已运行完成并处于等待命令状态状态位3-0的值为2。盲目发送命令可能导致无响应。此外所有IPC命令操作都应在CPU2处于Wait Boot模式下进行。2.4 安全启动与安全代码拷贝Secure Copy Code对于功能安全或知识产权保护要求高的应用2837xD提供了EXEONLY仅执行内存区域和对应的安全ROM API。如输入材料中Table 4-38和4-39所示SafeCopyCodeZ1/Z2和SafeCRCCalcZ1/Z2函数允许在严格受控的环境下将代码从EXEONLY Flash安全地拷贝到EXEONLY RAM中执行或计算其CRC。使用要点中断禁用调用这些API前必须禁用全局中断。因为安全ROM代码区不允许中断向量获取否则会触发复位。内存区域匹配源Flash和目的RAM必须同属一个安全区域Zone 1或Zone 2且都必须配置为EXEONLY属性。边界对齐拷贝或CRC计算的长度不能跨越Flash扇区或RAM块的边界。返回值检查函数返回拷贝或计算的字数若返回0则表示失败需检查参数是否符合上述约束。3. DMA机制全解解放CPU的数据传输引擎如果说启动流程是让系统“站起来”那么DMA就是让系统“跑起来”的关键。DMA允许外设与内存、内存与内存之间直接交换数据无需CPU介入每次传输。3.1 DMA核心架构与通道特性2837xD每个CPU子系统CPU1和CPU2都拥有一个独立的DMA模块每个模块包含6个独立的通道Channel 1-6。如输入材料图5-1所示DMA是一个位于CPU总线与各外设总线之间的专用数据通路控制器。架构特点事件触发DMA传输不是自动循环的必须由触发事件启动。触发源可以是外设中断如ADC转换完成、SPI接收缓冲满、CPU定时器中断甚至是软件手动触发。通道优先级通道1可被配置为高优先级其余通道为普通优先级。当多个通道的触发事件同时到来时高优先级通道先被服务。同一优先级内采用轮询仲裁。数据传输单元支持16位和32位传输。但需要注意某些外设如SPI的FIFO是16位宽的因此与之相关的DMA传输通常固定为16位。吞吐量在理想无仲裁情况下DMA完成一次16位或32位数据传输仅需3个系统时钟周期远快于CPU的存取指令。3.2 触发源配置让DMA在正确的时间动起来配置DMA通道的第一步也是最重要的一步就是正确配置其触发源。这是一个两级选择过程容易配置错误。配置步骤详解一级选择Peripheral Assignment首先你需要确定产生触发事件的外设归属于哪个CPU子系统。通过CPUSELx.PERy寄存器将外设如某个SPI或ePWM模块“分配”给CPU1或CPU2。这个外设所属的子系统决定了是哪个CPU的DMA能够接收到它的触发信号。二级选择Trigger Source Selection每个DMA通道可以从海量的触发源中选择一个。这通过两个寄存器配合完成DMACHSRCSEL1和DMACHSRCSEL2这两个寄存器决定了每个通道CHx的触发源组。例如将CH1配置为选择DMACHSRCSEL1定义的源列表。CHx.MODE.PERINTSEL在选定的源列表中通过这个3-5位的字段精确选择具体是哪一个触发信号。例如PERINTSEL0可能对应ADCINT1PERINTSEL1对应ADCINT2以此类推。常见问题排查DMA不触发当DMA配置好后毫无反应请按以下顺序检查外设归属确认产生触发信号的外设如EPWM1_SOCA是否已通过CPUSEL寄存器分配给了当前CPU如果分配给了另一个CPU那么本CPU的DMA是收不到这个触发信号的。触发源映射仔细查阅数据手册的“DMA Trigger Sources”表格找到你所用外设触发信号对应的DMACHSRCSEL和PERINTSEL值。这个映射关系非常具体容易查错。外设触发使能DMA的触发只是“响应”。你必须先确保外设本身能正确产生中断或SOC事件。例如对于ADC需要配置SOC并使其触发源有效对于ePWM需要使能SOCA信号。DMA通道使能最后检查CHx.CONTROL.RUN 1了吗DMA通道需要被使能才能等待触发。3.3 传输控制与地址模式DMA的“智能”所在DMA的强大不仅在于搬运数据更在于它能以多种“模式”搬运在传输过程中自动管理地址指针。这是通过CHx.SRC_ADDR、CHx.DST_ADDR、CHx.BURST_SIZE、CHx.TRANSFER_SIZE等寄存器协同工作实现的。核心概念解析传输Transfer一次触发事件所引起的数据搬运总量由TRANSFER_SIZE定义。例如TRANSFER_SIZE 10表示每次触发DMA搬运10个数据单元16位或32位。突发Burst为了优化总线效率DMA将一个传输Transfer分成多次“突发”访问来完成。BURST_SIZE定义了每次突发访问连续搬运的数据单元数。例如TRANSFER_SIZE10且BURST_SIZE5则每次触发会进行2次突发访问每次连续搬5个数据。地址模式这是DMA灵活性的核心。源地址和目的地址都可以在每次传输或每次突发后自动调整。不变Unchanged地址不变适用于访问固定寄存器如从ADC结果寄存器读数。递增Increment地址递增适用于顺序访问数组或缓冲区。递减Decrement地址递减。索引Indexed地址增加一个可配置的偏移量。这能实现二维数据传输是处理图像、矩阵数据的利器。一个典型应用场景ADC多通道采样到数组假设ADC序列器依次采样3个通道A0, A1, A2结果存入ADCRESULT0-2寄存器。我们希望用DMA将100组这样的采样值存放到一个二维数组adcBuf[100][3]中。配置思路触发源ADC序列器转换完成中断ADCINT1。源地址起始地址为ADCRESULT0的地址模式为不。因为每次触发时ADC的3个结果都固定放在ADCRESULT0-2。目的地址起始地址为数组adcBuf的首地址模式为索引递增。BURST_SIZE 3一次触发对应ADC的3个结果所以一次突发搬3个数据。TRANSFER_SIZE 300总共需要搬运100组 * 3个 300个数据。地址索引值SRC_BURST_INDEX 和 DST_BURST_INDEX这里的关键在于目的地址的索引。我们希望每次突发搬3个数据后目的地址不是简单递增3而是回到下一行的开头。假设数组元素是16位则adcBuf[0][1]的地址比adcBuf[0][0]的地址大2字节。但一次突发搬完一行3个数据后地址应指向adcBuf[1][0]它与adcBuf[0][0]的偏移是3 * 2字节 6字节。然而由于DMA在突发内每搬一个数据地址已自动递增所以突发后的索引偏移需要抵消掉突发内的递增。因此DST_BURST_INDEX应设置为-(BURST_SIZE - 1) * 2 行间隔。更简单的做法是使用DST_TRANSFER_INDEX它在整个传输一组数据完成后才应用偏移。这里设置DST_TRANSFER_INDEX 0因为每次传输就是一行我们希望地址回到行首不对。实际上对于“源地址不变目的地址连续存放”的场景目的地址模式设为简单递增BURST_SIZE3TRANSFER_SIZE300即可。DMA会在每次触发后从固定的ADCRESULT0开始连续读3次自动递增源地址不源地址是不变的但ADC硬件会在每次DMA读取后自动更新结果寄存器索引吗这取决于ADC配置。更准确的配置是源地址配置为ADCRESULT0但使用递增模式因为ADC结果寄存器是连续映射的。这揭示了配置的复杂性必须结合外设行为。避坑指南地址计算与边界对齐DMA的地址寄存器是字节地址而BURST_SIZE和TRANSFER_SIZE计数的是数据单元数16位或32位。在计算索引偏移时务必考虑数据宽度。例如对于16位数据地址偏移量 索引值 * 2。此外确保源/目的地址和数据大小对齐到总线宽度通常32位可以避免产生不对齐异常并可能提升性能。3.4 Ping-Pong模式与中断管理Ping-Pong乒乓缓冲是DMA的进阶用法用于实现数据搬运与处理的无缝流水线。工作原理配置两个缓冲区Buffer A和Buffer B。DMA控制器交替使用这两个缓冲区。第一阶段DMA向Buffer A填充数据同时CPU处理Buffer B中的数据。第二阶段当Buffer A满一次传输完成DMA自动切换至向Buffer B填充数据并产生一个传输完成中断通知CPUCPU转而处理Buffer A中的数据。如此循环往复实现了数据采集与处理的并行几乎消除了缓冲区切换带来的延迟。在2837xD上的实现DMA通道的CONTROL寄存器中有PINGPONG使能位。当使能后你需要配置两套地址寄存器SRC_ADDR/DST_ADDRPing组和SRC_ADDR2/DST_ADDR2Pong组。DMA会在每次传输完成中断后自动在两套地址寄存器间切换。中断配置要点每个DMA通道有两个中断可配置到PIEINT1传输开始中断和INT2传输完成/半传输完成中断。在Ping-Pong模式下通常使能INT2并将其配置为在每次传输完成时触发。在中断服务程序ISR中你需要判断当前是Ping还是Pong缓冲区刚被填满。处理该缓冲区中的数据。关键一步清除DMA通道的中断标志CHx.CONTROL.INT2FLG1并确保重新使能该通道如果传输计数未耗尽。在Ping-Pong模式下DMA通常会自动切换并继续运行但确认标志位是必要的。实操心得避免DMA中断丢失DMA中断是电平敏感型。这意味着如果DMA在CPU进入ISR并清除标志之前又完成了下一次传输并再次拉高中断线那么这次新的中断事件可能被记录也可能被合并。为确保不丢失任何一次缓冲区满事件一个稳健的做法是在ISR中不仅检查中断标志还可以读取DMA的当前地址指针或传输剩余计数来辅助判断数据状态。同时ISR的处理代码必须尽可能高效确保在下一次DMA传输完成前已处理完当前缓冲区的数据并准备好交换。4. 双核系统中的DMA仲裁与资源共享在2837xD的双核系统中CPU1和CPU2各有自己的DMA控制器但它们可能需要访问共享资源如共享RAMGSRAM或某些公共外设总线。这就引入了总线仲裁问题。4.1 总线仲裁机制如图5-2所示对于连接到公共外设帧Peripheral Frame的外设如某些SPI、ePWM当CPU1、CPU1的DMA、CPU2、CPU2的DMA同时请求访问时由仲裁器Arbiter决定访问顺序。仲裁优先级规则通常如下DMA访问优先于CPU访问这是为了满足DMA对实时数据流的要求避免因CPU访问延迟导致数据丢失。输入材料中也明确指出“If CPU and DMA make an access to the same peripheral frame in the same cycle, the DMA has priority and the CPU is stalled.”同一子系统内高优先级DMA通道Channel 1优先于低优先级通道。不同子系统之间仲裁策略可能固定或可配置。需要查阅具体器件的数据手册以明确。一种常见的策略是轮询Round-Robin公平仲裁。对系统设计的影响这意味着如果一个核心的CPU正在频繁访问某个共享外设例如通过SPI连续发送日志那么另一个核心的DMA试图访问同一外设帧上的不同外设时可能会被延迟或阻塞。在设计多核任务和DMA传输时必须考虑这种总线竞争带来的潜在延迟。4.2 共享内存GSRAM与MSGRAM的DMA使用共享内存是双核通信的“高速公路”DMA是这条路上的“重型卡车”。使用DMA在共享内存与各核本地资源间搬运数据效率远高于CPU拷贝。最佳实践明确内存映射在链接器命令文件.cmd中为每个核以及共享内存区域精确定义段Section。例如定义一个MSGRAM段位于0x0000 4000CPU1 to CPU2 MSGRAM。使用软件触发或IPC同步CPU1可以将数据准备好后通过DMA使用软件触发将数据从本地RAM搬至MSGRAM。然后通过写一个IPC标志位例如IPCx.IPCSET寄存器来通知CPU2。CPU2收到通知后可以启动自己的DMA将数据从MSGRAM搬至其本地RAM进行处理。这种“生产-消费”模型清晰且高效。注意数据一致性如果两个核都可能写入同一块共享内存需要设计简单的软件互斥机制如使用一个原子操作的标志字来避免冲突。DMA传输本身是原子的一次突发访问内但多个DMA或DMA与CPU的交叉访问需要同步。5. 实战配置流程与调试技巧5.1 一个完整的DMA配置示例以CPU1的DMA Ch1搬运ADC结果为例假设我们需要将ADC序列器SEQ1的4个通道转换结果每次转换完成后立即通过DMA搬运到数组adcResults[256]中。步骤外设分配确认ADC模块已分配给CPU1默认通常是。配置ADC配置ADC的SEQ1使其在某个触发源如ePWM1 SOCA下对4个通道进行转换并使能ADCINT1作为序列转换完成中断。配置DMA通道CH1.SRC_ADDRAdcResult.ADCRESULT0// ADC结果寄存器起始地址CH1.SRC_BURST_SIZE 4 // 一次触发对应4个结果CH1.SRC_TRANSFER_SIZE 256 // 总共搬运256个数据即64组CH1.SRC_ADDR_MODEINCREMENT// 源地址递增因为ADCRESULT0到ADCRESULT15是连续寄存器CH1.DST_ADDRadcResults[0]// 目的数组首地址CH1.DST_BURST_SIZE 4CH1.DST_TRANSFER_SIZE 256CH1.DST_ADDR_MODEINCREMENT// 目的地址递增CH1.TRIGGER_MODEONESHOT_BURST// 每次触发完成一次突发4个数据传输CH1.CONTROL.ONESHOT 0 // 传输整个TRANSFER_SIZE256后才停止配置触发源查找数据手册确定ADCINT1对应的触发选择值。假设对应DMACHSRCSEL1.CH1的某个选项且PERINTSEL0。设置DMACHSRCSEL1寄存器中对应CH1的字段。设置CH1.MODE.PERINTSEL 0。使能中断配置CH1.CONTROL使能传输完成中断INT2并将其映射到PIE的相应中断线如INTx.y。启动DMA设置CH1.CONTROL.RUN 1使通道进入等待触发状态。启动ADC触发配置并启动ePWM1产生SOCA信号触发ADC转换。5.2 调试技巧与常见问题排查表现象可能原因排查步骤DMA完全不触发1. 触发源配置错误。2. 外设未产生触发信号。3. DMA通道未使能RUN位。4. 外设未分配给当前CPU。1. 检查DMACHSRCSELx和PERINTSEL配置对照手册确认映射。2. 检查外设中断标志位是否置起。可先禁用DMA用CPU中断测试触发信号是否正常。3. 检查CHx.CONTROL.RUN位。4. 检查CPUSELx.PERy寄存器。DMA只触发一次CONTROL.ONESHOT位可能被误设为1。检查CHx.CONTROL.ONESHOT位。若希望连续传输直到TRANSFER_SIZE完成应设为0。数据搬运地址错乱1. 源/目的地址模式配置错误。2. 地址索引INDEX计算错误。3. 数据宽度16/32位与地址增量不匹配。1. 单步调试在DMA触发后查看SRC_ADDR和DST_ADDR寄存器的变化是否符合预期。2. 复核BURST_SIZE和TRANSFER_SIZE以及*_BURST_INDEX和*_TRANSFER_INDEX的值。记住地址是字节地址。3. 确认MODE.DATASIZE设置与实际情况一致。Ping-Pong模式切换异常1. Ping/Pong地址寄存器未正确配对初始化。2. 中断标志未正确清除。3. 缓冲区处理太慢DMA已覆盖未处理数据。1. 在初始化时确保SRC_ADDR2和DST_ADDR2也正确配置。2. 在ISR中必须写1清除INT2FLG。3. 优化CPU处理代码或增大缓冲区或降低DMA触发频率。双核访问共享资源冲突总线仲裁导致某个核心的DMA/CPU访问被长时间阻塞。1. 使用性能分析工具或 GPIO 翻转测量访问延迟。2. 重新规划数据流让两个核的DMA访问在时间上错开或使用不同的存储区域。3. 考虑将频繁访问的数据从共享帧移到本地内存。最后一点体会启动流程和DMA是嵌入式系统底层开发中最体现功力的部分。面对2837xD这样的双核芯片清晰的启动顺序设计和高效的DMA数据流规划往往是项目成功的关键。建议在项目初期就用框图画出双核的启动协作关系和数据流向图这能帮你提前避开许多架构上的坑。调试时善用CCS的寄存器查看器和内存浏览器观察Boot Status寄存器和DMA地址寄存器的变化它们会告诉你硬件究竟在执行什么。