深入解析66AK2E0x启动配置与系统互联:从硬件引脚到多核协同
1. 项目概述与核心价值
在嵌入式系统开发,尤其是基于德州仪器(TI)KeyStone II架构的高性能多核异构处理器(如66AK2E05/66AK2E02)的设计中,系统启动配置与互联机制是决定项目成败的基石。这不仅仅是“上电跑个程序”那么简单,它直接关系到整个系统的稳定性、性能上限以及后续软件开发的复杂度。想象一下,你设计了一个集成了多核ARM Cortex-A15和多个C66x DSP的复杂通信或图像处理平台,硬件焊接完毕,满怀期待地通电,结果发现某个核心没起来,或者DDR内存访问异常,甚至根本找不到启动镜像——这些问题十有八九都源于启动流程的配置失误。
我接触过不少团队,在项目初期将大量精力放在应用算法上,却对底层的启动引导(Bootloader)和系统互联(System Interconnect)一笔带过,结果在集成调试阶段耗费数周甚至数月去排查一些诡异的、时好时坏的问题。66AK2E0x系列芯片的启动与互联机制,其技术价值恰恰在于它提供了一套高度灵活但同时也异常复杂的配置体系。它允许你从I2C EEPROM、SPI Flash、NAND Flash、以太网、PCIe乃至HyperLink等多种外设启动,并能精细地控制ARM与多个C66x DSP核心的初始化顺序、内存映射以及彼此间的通信通路。理解并正确配置这些机制,意味着你能从硬件层面为软件搭建一个稳固、高效且可预测的运行舞台,避免后期出现“地基不稳,地动山摇”的窘境。
本文将从一个一线工程师的视角,深入拆解66AK2E0x的启动配置精髓与系统互联的工作机制。我们不会停留在数据手册的简单翻译上,而是结合实际的工程场景,告诉你每个配置位背后的设计意图、不同启动模式的选择考量,以及在调试中遇到“启动失败”或“性能瓶颈”时,应该如何顺藤摸瓜,从系统互联的总线优先级和启动参数表这两个核心线索入手进行排查。无论你是正在评估该平台的新手,还是正在为现有设计寻找优化方向的老手,相信这些从实际项目中沉淀下来的细节和经验都能带来直接的帮助。
2. 系统互联架构与总线优先级深度解析
在深入启动流程之前,必须先理解66AK2E0x内部的“交通网络”——系统互联(System Interconnect)。你可以把它想象成一个高度复杂的高速公路网,ARM核心、DSP核心、DMA控制器、各种外设(如USB、以太网、UART)都是需要上路行驶的“车辆”(主设备Master),而内存(如DDR、MSMC)、配置寄存器空间则是它们要前往的“目的地”(从设备Slave)。如果这个网络没有合理的交通规则(即总线仲裁策略),那么当多个主设备同时发起访问时,就会发生拥堵甚至撞车(数据冲突、访问超时),导致系统性能骤降或功能异常。
2.1 TeraNet互联与优先级寄存器
66AK2E0x系列的核心互联骨干是基于TI的TeraNet交换结构。数据手册中提到的“所有主设备外设流量的优先级在TeraNet边界定义”,这句话点明了关键:优先级仲裁发生在数据流量进入核心交换网络的那一刻。每个主设备在发起交易时,都必须携带一个优先级标识。
这个优先级通常是一个3位的值(PRI[2:0]),其中000b代表最高优先级(Urgent),111b代表最低优先级(Low)。这个设计非常直观,数值越小,优先级越高。在芯片内部,像C66x CorePac这样的高性能计算核心,其访问内存的请求通常会被软件配置为高优先级,以确保其计算流水线不被阻塞;而一些后台的、非实时性的数据搬运任务则可以配置为低优先级。
注意:这里有一个极易混淆的点。数据手册提到“所有其他主设备直接提供其优先级,不需要默认优先级设置。例如,C66x CorePac的优先级通过UMC控制寄存器中的软件设置”。这意味着像C66x核心这类“智能”主设备,其优先级是动态可编程的,软件可以根据运行时任务的重要性灵活调整。而另一些“简单”主设备,其优先级可能在硬件设计时就被固定了,或者需要通过特定的配置寄存器(如
CHIP_MISC_CTL0中的QM_PRIORITY字段)来设定。在规划系统带宽时,必须查阅每个主设备对应的用户指南,明确其优先级配置方式。
2.2 配置空间互联与访问控制
你提供的表格片段(表8-4)是理解外设间相互访问权限的关键。它描述的是“配置空间互联”(Configuration Space Interconnect),这是系统互联中一个专门用于访问各个模块内部配置寄存器(MMR)的网络。我们以USB0_MMR_CFG这一行和QM_SEC这一列交叉处的“12”为例,来解读其背后的含义。
这个表格是一个主从访问矩阵。行(SLAVES)代表“目的地”,即各个模块的配置寄存器空间;列(MASTERS)代表“发起者”,即哪些主设备有权访问这些目的地。表格中的数字(如12)并非随意填写,它通常代表了通往该从设备的“接口号”或“路径标识符”。在软件上,这个数字可能对应一个特定的路由配置或防火墙规则。
例如,QM_SEC(可能是Queue Manager的安全相关模块)作为主设备,其访问USB0_MMR_CFG(USB0模块配置寄存器)的请求,会被路由到接口12。而USB0和USB1作为主设备,其对应的表格条目是“-”,这很可能意味着它们没有权限直接访问自身的配置寄存器空间(或者需要通过其他特定路径),这是一种常见的安全设计,防止外设意外篡改自身的核心配置。
实操心得:在调试外设驱动时,如果发现无法正确读写某个模块的配置寄存器,除了检查时钟、电源、引脚复用外,还应该考虑系统互联的访问权限。虽然大多数情况下默认配置是通的,但在一些涉及安全启动或特定低功耗场景下,这些访问路径可能被关闭。这时就需要查阅完整的系统互联手册,确认你的主CPU(如ARM)是否在目标从设备的允许访问主设备列表中。
2.3 基于Packet DMA与Multicore Navigator的流量管理
对于66AK2E0x这种多核异构处理器,高效的数据搬运至关重要,这主要由Packet DMA和Multicore Navigator子系统负责。数据手册特别指出了“Packet DMA secondary port”这个主端口的优先级分配方式,它内部没有优先级分配寄存器,其优先级由芯片级杂项控制寄存器CHIP_MISC_CTL0中的QM_PRIORITY字段统一描述。
这揭示了一个重要的设计模式:对于高度集成、管理大量数据流的核心子系统,其内部多个主端口的优先级可能会被“打包”管理。QM_PRIORITY这个位域可能控制着整个Queue Manager子系统发起事务的默认优先级。在优化系统实时性时,如果你发现通过Navigator队列传递的数据包延迟过大,除了检查队列本身,还应该审视CHIP_MISC_CTL0寄存器中这个全局优先级设置是否合理。将其适当调高,可能立竿见影地改善DSP与ARM间通信的延迟。
3. 设备启动流程全解析:从硬件引脚到软件执行
启动流程是66AK2E0x上电后上演的第一幕“大戏”。这个过程决定了芯片从哪里、以何种方式、加载什么代码、以及各个核心如何被唤醒。整个过程是硬件逻辑与固化在ROM中的软件(RBL, ROM Bootloader)紧密协作的结果。
3.1 启动模式的核心:BOOTMODE引脚与DEVSTAT寄存器
芯片上电或热复位后,硬件首先会采样一组特定的引脚BOOTMODE[15:0]的电平状态,并将其锁存到设备状态寄存器DEVSTAT[16:1]中(DEVSTAT[0]独立用于配置系统端序)。这16个位(实际使用15个,因为Boot Master位固定)就是引导ROM代码解读“用户意图”的唯一依据。这是一个一次性、硬件级别的配置,在复位解除后软件无法更改。因此,硬件设计时必须根据产品选定的启动方式,通过上拉或下拉电阻准确配置这些引脚。
BOOTMODE引脚的定义非常丰富,它不仅仅选择了启动设备(如I2C、SPI、NAND等),还编码了该设备的具体工作参数。例如,选择I2C启动时,这些引脚还指定了使用的是I2C0、I2C1还是I2C2端口,以及从设备的地址。这种设计减少了对外部配置元件(如EEPROM)的依赖,将关键配置“固化”在硬件连接中,提高了可靠性。
3.2 启动主控与内存映射:ARM CorePac的绝对主导
一个关键限制是:在66AK2E0x的非安全设备上,只支持ARM CorePac作为启动主控(Boot Master)。C66x DSP核心不能作为启动主控。这意味着上电后,是ARM CorePac(具体是Core 0)首先从ROM地址开始执行引导代码,而所有的C66x CorePac则处于执行空闲指令的等待状态。
ARM CorePac在启动过程中扮演着“管家”的角色。它负责初始化系统关键硬件(如PLL、DDR3控制器),从指定的外部设备读取引导镜像,并根据镜像中的信息,决定如何唤醒和配置C66x DSP核心。为此,芯片内部为ARM和C66x的启动过程分别预留了专门的RAM区域,如你提供的表9-1和表9-2所示。
C66x DSP Boot RAM(起始于0x0080_0000)主要包含:
- Boot Master Table:覆盖在Scratch区域,用于引导主控(ARM)与从核(DSP)之间的通信。
- Boot Data/Stack/Parameter Table:存放引导参数、临时数据和栈空间。
- DDR3 Configuration Structure:非常重要!如果引导镜像需要被加载到外部DDR内存,ARM RBL会使用这个结构体中的参数来初始化DDR3控制器。如果配置错误,后续加载会失败。
ARM Boot RAM(起始于0x0C18_0000附近)区域则复杂得多,因为它要管理最多4个ARM Cortex-A15核心:
- 页表(Page Table):为每个核心配置了非安全模式下的内存转换表,这是ARM架构开启MMU(内存管理单元)的基础。
- 各核心私有区域:每个ARM核心都有自己独立的栈空间(Supervisor Stack, Abort Stack等)、引导版本字符串、状态、日志和参数表。这种“每核一份”的设计支持了各核心独立或协同的启动流程。
- 共享结构:如DDR3配置结构、主机数据地址等,是全局信息。
避坑指南:在编写自定义二级引导程序(如U-Boot)或直接加载应用程序时,必须严格避开这些ROM Bootloader使用的内存区域。特别是0x0080_0000开始的128KB和0x0C18_0000开始的几百KB区域。误用这些区域会导致RBL运行异常,表现为启动失败或行为不可预测。最好的做法是在链接脚本(linker script)中明确排除这些地址段。
3.3 两种核心启动模式:公共ROM启动与安全ROM启动
根据BOOTMODE的配置和芯片是否支持安全特性,存在两种主要的启动流程:
1. 公共ROM启动(Public ROM Boot):这是最常见的模式。ARM CorePac Core 0作为唯一的活动核心执行RBL,完成所有初始化并加载用户镜像。在此期间,C66x DSP核心处于休眠状态。当ARM完成加载后,它通过处理器间通信(IPC)寄存器向C66x核心发送中断或信号。C66x核心被唤醒后,从预定义的地址(通常由ARM在加载时指定)开始执行自己的代码。这种模式清晰地将ARM作为主管理核心。
2. 安全ROM启动(Secure ROM Boot):当芯片运行在安全模式下,启动流程会更加复杂。ARM CorePac Core 0和C66x CorePac 0会同时从安全ROM中释放并开始执行代码。ARM Core 0仍然主导启动流程,但C66x CorePac 0会参与对加密或签名的引导镜像进行认证和解密的工作,然后再开始执行。这利用了C66x DSP在加密算法上的高性能,实现了安全性与效率的平衡。
重要提示:无论哪种模式,C66x CorePac和ARM CorePac都需要读取BOOTMODE寄存器(或其镜像)来决定如何继续引导过程。这意味着即使在安全启动中DSP核心较早参与,它也需要知晓整体的启动配置。通常,这个信息由ARM核心通过共享内存或IPC传递。
4. 启动参数表详解:RBL的“行动指南”
ROM Bootloader(RBL)的强大与灵活,很大程度上体现在它对“启动参数表”(Boot Parameter Table)的支持上。你可以把RBL看作一个高度可配置的加载器,而启动参数表就是写给它的、详细描述了“从哪里、怎么读、读出来放哪里、之后怎么办”的说明书。这张表通常存储在启动设备的固定位置(如I2C EEPROM的特定扇区、SPI Flash的开头、NAND的特定块)。
4.1 参数表的通用结构
如表9-15所示,所有启动模式的参数表都有一个共同的头部(Common Parameters):
- Length & Checksum:表长度和校验和,用于RBL验证表的完整性。
- Boot Mode & Port Num:进一步细化的启动模式和端口号,是对
BOOTMODE引脚信息的补充或确认。 - PLL Configuration:系统时钟和核心时钟的PLL配置值。这里是性能调优的第一个关键点。虽然
BOOTMODE引脚可以设置一个粗略的PLL配置(SYS PLL Setting字段),但参数表中的SW PLL和频率字段允许进行更精细的调整。例如,你可以让芯片以一个较低的保守频率启动以确保稳定性,然后在参数表中配置更高的目标频率,由RBL在初始化DDR前完成PLL的重锁。 - Boot Master:明确指定启动主控。对于66AK2E0x,此字段应设为
FALSE(或0),因为ARM是固定的启动主控。
4.2 各启动模式的专属参数解析
通用头部之后,就是各个启动模式特有的参数。这部分内容直接决定了RBL如何与具体的外设进行交互。
以以太网(SGMII)启动为例(表9-17): 这是一个非常复杂的启动方式,常用于远程更新或网络化设备。其参数表长达数十个字段,涵盖了从MAC地址、UDP端口到SGMII SerDes物理层配置的方方面面。
- MAC地址与端口:
MAC High/Med/Low定义了本设备接收TFTP引导包的MAC地址。Dest Port指定目的UDP端口。Device ID是一个标识字符串,会包含在RBL发送的“Ethernet Ready Frame”中,主机端TFTP服务器可以据此识别设备。 - 网络配置:
Lane Enable和SGMII Config等字段用于配置具体的网络物理接口。例如,在只有一个SGMII端口连接的板卡上,你需要正确启用对应的Lane并关闭其他Lane。 - Packet Subsystem PLL:独立于系统PLL,用于配置网络协处理器(NETCP)的时钟,这对以太网链路能否正确建立至关重要。
避坑指南:以太网启动失败排查:
- 物理链路:首先确认SGMII SerDes参考时钟(如156.25MHz)是否稳定,幅度是否达标。这是最常见的问题根源。
- 参数表配置:检查
Lane Enable是否与实际硬件连接匹配。检查SGMII Config中的速率、双工模式是否与对端设备(交换机)兼容。 - 网络环境:确保主机TFTP服务器与设备在同一子网,且防火墙未阻止TFTP端口(默认69)。在主机端抓包,观察是否收到了设备发出的包含正确
Device ID的“Ethernet Ready Frame”。 - 镜像格式:确认通过TFTP传输的镜像文件是RBL支持的格式(通常是纯二进制bin文件或带特定头部的格式)。
以NAND Flash启动为例(表9-23): NAND启动常用于需要大容量存储且成本敏感的应用。其参数表的核心是描述NAND芯片的几何结构。
- Geometry vs. Query:
Options字段的Bit 0是关键选择。如果设为0,RBL将使用参数表中numColumnAddrBytes、numRowAddrBytes、numofDataBytesperPage等字段提供的值。如果设为1,RBL会尝试向NAND芯片发送Read ID和Read Parameter Page命令,自动查询这些信息。对于新型号的NAND Flash,强烈建议使用查询模式(设为1),因为不同厂商、不同制程的页大小、块大小可能不同,手动配置极易出错。 - ClearNAND标志:如果使用带内建ECC引擎的ClearNAND芯片,需要将
Options的Bit 1设为1,告知RBL不要尝试进行软件ECC校验。 - First Block:指定RBL从哪个物理块开始读取镜像。这允许你将引导程序放在NAND的任意位置,避开可能有坏块的区域。
4.3 DDR3配置表:性能与稳定的基石
表9-24的DDR3配置表是另一个重中之重。如果用户镜像需要被加载到外部DDR3内存中运行(这几乎是必然的),那么RBL在加载镜像之前,必须依据此表正确初始化DDR3控制器和PHY。
这张表包含了DDR3初始化的几乎所有关键寄存器值:
- PLL配置(
pllprediv,pllMult,pllPostDiv):设置DDR3控制器的时钟频率,必须与DDR3芯片的额定频率和板卡布线质量匹配。 - 时序参数(
sdRamTiming1/2/3):包括tRCD,tRP,tRAS,tRFC,tWTR等一系列关键时序。这些值必须严格遵循你所使用的DDR3芯片数据手册中的推荐值。计算这些值时,需要根据DDR3时钟周期进行转换。 - 阻抗校准(
sdRamOutImpdedCalcfg):对于高速DDR3接口,驱动器和接收器的阻抗需要与传输线特性阻抗匹配,通常需要通过校准流程来找到最佳值。参数表允许你提供初始配置。
实操心得:生成DDR3配置表: 手动计算这些寄存器值极其繁琐且容易出错。TI通常会提供一套名为“SPI Flasher and Initialization”的工具,或者在其处理器SDK中包含一个DDR3 Register Configuration Calculator的Excel表格或脚本。你只需要输入DDR3芯片型号、时钟频率、板卡拓扑等信息,工具就会生成正确的寄存器值。绝对不建议手动填写此表。一个错误的时序参数就可能导致DDR3工作不稳定,表现为随机数据错误、系统随机崩溃等极难调试的问题。在最终量产前,务必使用内存压力测试工具(如Memtest86+适配版)对DDR3进行长时间满负荷测试。
5. 工程实践:从原理到配置的完整工作流
理解了上述原理后,我们来看一个典型的66AK2E0x项目启动配置工作流。
5.1 硬件设计阶段的引脚配置
在绘制原理图时,就需要确定启动方案。假设我们选择从SPI NOR Flash启动,并希望使用最低引脚配置(Min=1)。
- 确定BOOTMODE[15:0]:查阅
表9-7。Boot Device(Bits[3:1]) =010b(SPI)。Min(Bit 4) =1b(启用最小引脚配置)。Boot Master(Bit 8) =0b(必须下拉,ARM启动)。- 其他位(如
Width,Csel,Mode,Port,Param Idx)在Min=1时会采用默认值(24位地址、CS0、模式2、SPI0端口、参数表索引0)。 Lendian(Bit 0) 根据软件需求选择,假设选小端1b。SYS PLL Setting(Bits[7:5]) 根据输入时钟频率选择,假设输入时钟为50MHz,查表9-25(虽未在提供片段中,但原理一致)得到配置值,假设为100b。- 最终,我们需要配置的引脚是:
BOOTMODE[15:8]根据PLL等设置,BOOTMODE[7:1]=100 0 000 010,BOOTMODE[0]=1。在原理图上,将这些引脚通过电阻上拉或下拉到VDD或GND。
5.2 创建启动镜像与参数表
使用TI的编译工具链(如TI ARM Compiler)编译生成你的应用程序(如二级引导程序U-Boot)的二进制文件(.bin)。
- 使用
hex6x工具:TI的hex6x工具可以将链接器输出的.out文件转换为各种可引导的格式。关键是要为它提供一个正确的.cmd命令文件,在其中指定输出格式为--boot,并关联相应的参数表。 - 编写参数表:对于SPI启动,我们需要创建一个符合
表9-20格式的二进制参数表。这通常通过编写一个C结构体,并在代码中初始化,或者使用一个单独的配置文件,由镜像制作工具解析并打包。// 示例:SPI Boot Parameter Table 结构(部分字段) #pragma DATA_SECTION(spiBootTable, ".boot:spi_table") const uint32_t spiBootTable[] = { 0x0000002C, // Length (44 bytes) 0x0000XXXX, // Checksum (计算后填充) 0x0000000A, // Boot Mode (内部值,SPI) 0x00000000, // Port Num (SPI0) 0x12345678, 0x9ABCDEF0, // SW PLL Config (根据目标频率计算) 0x00000000, 0x00000000, // Reserved 0x000003E8, // System Freq (1000 MHz) 0x000001F4, // Core Freq (500 MHz) 0x00000000, // Boot Master (FALSE for ARM) // SPI特有字段开始 0x00000000, // Options (默认模式) 0x00000018, // Address Width (24-bit = 0x18) 0x00000004, // NPin (4-pin mode) 0x00000000, // Chipsel (CS0) 0x00000002, // Mode (SPI mode 2) ... // 其余字段 }; - 合成最终镜像:使用TI的
mkimage或SDK中的tiimage工具,将参数表、应用程序二进制、可能还有DDR3配置表等,按照RBL期望的格式(如TI .bin格式,包含大小端头、目标地址、入口点等)打包成一个最终的.bin或.ti文件。
5.3 烧录与调试
- 烧录:通过JTAG接口(如XDS560v2仿真器)和CCS(Code Composer Studio)将最终镜像烧写到SPI Flash的起始地址(通常是
0x0)。确保烧录工具正确配置了SPI Flash的型号、页大小和擦除/编程算法。 - 上电调试:
- 第一步:确认RBL执行。连接仿真器到ARM Core 0,进行上电复位。在CCS中暂停程序,查看PC指针是否在ROM地址范围(如
0x20B0_0000附近)。单步执行,观察是否进入RBL代码。 - 第二步:观察初始化过程。在RBL代码中,对DDR3初始化、SPI外设初始化等关键函数设置断点。观察寄存器配置是否正确,SPI读写是否成功。
- 第三步:镜像加载与跳转。在RBL将镜像加载到DDR内存的代码段设置断点,确认数据被正确读取和搬运。最后,在RBL跳转到用户镜像入口点的指令处设置断点,确认跳转地址正确。
- 使用串口调试:在UART初始化后,通过串口输出打印信息,是追踪RBL和早期启动代码执行流的有效手段。确保参数表中UART的波特率、数据位等配置与你的串口终端设置一致。
- 第一步:确认RBL执行。连接仿真器到ARM Core 0,进行上电复位。在CCS中暂停程序,查看PC指针是否在ROM地址范围(如
6. 常见问题排查与实战技巧
即使按照手册操作,启动过程仍可能遇到问题。以下是一些常见故障的排查思路:
问题一:芯片上电后毫无反应,仿真器也无法连接。
- 检查电源与复位:测量所有核心电压、IO电压、PLL模拟电压是否稳定且在容差范围内。检查复位信号(RESETn)的时序是否符合要求,是否有毛刺。
- 检查时钟:测量主输入时钟(如晶振或时钟发生器输出)是否起振,频率和幅度是否正常。
- 检查BOOTMODE引脚:用万用表或示波器确认
BOOTMODE[15:0]和LENDIAN引脚在上电复位期间的电平是否与原理图设计一致。特别注意,这些引脚可能有内部上拉/下拉,要确认外部电阻值足够强以覆盖内部阻抗。 - 检查仿真器连接:确认JTAG的
TCK、TMS、TDI、TDO、nTRST信号连接正确,特别是上拉电阻。
问题二:仿真器可以连接ARM核心,但PC指针停在ROM起始地址,单步执行不久后跑飞或死循环。
- 排查PLL配置:这是最常见的原因。RBL早期代码会配置PLL。如果
BOOTMODE引脚中的SYS PLL Setting或参数表中的SW PLL配置值与实际的输入参考时钟频率不匹配,会导致PLL无法锁定或输出错误频率,进而导致后续所有基于时钟的操作(包括内存访问)失败。仔细核对输入时钟频率和配置值。 - 检查启动设备初始化:如果RBL在尝试初始化SPI/I2C/NAND等外设时失败,也会卡住。在CCS中查看相关外设控制寄存器的状态位,确认初始化是否完成,是否有错误标志(如NAND的
ECC错误,SPI的TX/RX错误)。可能是启动设备的供电、片选信号或时序不匹配。
问题三:RBL似乎执行完毕,但程序没有跳转到我的应用程序,或者跳转后立即崩溃。
- 检查镜像加载地址:确认你的应用程序的链接地址(Load Address)和RBL将其加载到的地址(在参数表中指定或由RBL决定)是否一致。如果不一致,代码中的绝对地址引用会全部错乱。
- 检查DDR3初始化:如果应用程序被加载到DDR3中运行,那么DDR3初始化失败是罪魁祸首。即使能加载,不稳定的DDR3也会导致随机崩溃。使用CCS的内存浏览器查看DDR3区域,尝试写入再读回一个已知模式(如
0xAA55AA55),看数据是否一致。运行DDR3压力测试。 - 检查向量表和栈指针:对于ARM核心,确保在跳转到C代码入口点之前,栈指针(SP)已被正确设置到一段可用的内存(如片上SRAM),并且异常向量表已就位。对于C66x DSP,同样需要检查其栈和中断向量表的配置。
- 参数表校验和错误:虽然不常见,但参数表的校验和计算错误会导致RBL拒绝使用该表。使用工具重新计算并填充正确的校验和。
问题四:多核启动问题,只有ARM Core 0起来了,其他ARM核心或DSP核心没有启动。
- 检查核间通信(IPC):ARM Core 0在完成自身初始化后,需要通过写IPC寄存器或发送中断来释放(release)其他核心。确认你的启动代码中包含了唤醒其他核心的步骤。对于C66x DSP,通常需要ARM为其设置好
Boot Magic Address(见表9-1中的0x87_fffc),然后发送一个事件(event)或中断。 - 检查每个核心的私有启动数据:如
表9-2所示,每个ARM核心都有自己独立的Boot Magic Address(0xc1a_d00x)。ARM Core 0需要为Core 1/2/3分别设置正确的跳转地址。 - 检查内存一致性:确保所有核心看到的关键共享数据结构(如描述系统资源分配的设备树或配置表)位于一段对所有核心都可见且缓存一致的内存中(如MSMC SRAM或已正确配置缓存一致性的DDR区域)。
一个实用的调试技巧:利用ROM Bootloader的“最小启动”模式。许多Bootloader支持一种最小化或诊断模式。对于66AK2E0x,可以尝试配置BOOTMODE进入一种最简单的模式(如配置为无效模式,有时会进入串口下载模式),或者通过仿真器直接加载并运行一个极其简单的、只操作片内SRAM的测试程序,绕过复杂的DDR和外部Flash初始化。这可以帮你快速隔离问题:如果最小程序能跑,问题就在DDR、Flash或参数表;如果最小程序也不能跑,问题就在更底层的时钟、电源或芯片本身。