
1. 项目概述与核心价值在嵌入式系统开发尤其是工业控制、电机驱动和汽车电子这些对实时性与可靠性要求极高的领域系统上电后的第一行代码——引导加载程序Bootloader——其重要性怎么强调都不为过。它不仅仅是把程序从Flash搬到RAM那么简单更是整个系统安全、可靠、可维护的基石。我接触过不少项目早期因为对Bootloader重视不够要么是现场升级固件失败导致设备“变砖”要么是系统轻易被恶意代码侵入损失惨重。这次我们聚焦于TI的TMS320F28003x系列微控制器。这颗芯片在C2000™ DSP家族中定位中高端性能强劲外设丰富但与之对应的其启动与安全架构也更为复杂。很多工程师拿到芯片照着例程把程序下载到Flash能跑起来就以为万事大吉直到需要设计串口升级、或者产品面临安全审计时才一头扎进上千页的技术参考手册对着BOOT_DEF、Secure ROM、DCSM这些术语发懵。实际上F28003x的Boot ROM提供了一个非常强大的工具箱。它支持从多种外设启动SCI、SPI、I2C、CAN、并行IO也支持从内部Flash安全启动。更重要的是它集成了安全引导Secure Boot和双代码安全模块DCSM能够为你的核心知识产权IP和系统完整性提供硬件级别的保护。理解并正确配置这些机制意味着你能设计出启动更快、更安全、并且支持远程安全更新的产品。这不仅仅是“会不会用”的问题而是决定了你的产品能否满足现代工业领域日益严苛的安全与可靠性标准。本文将从一个一线开发者的视角彻底拆解F28003x的启动模式配置与安全引导实践。我不会照本宣科地翻译数据手册而是结合我实际踩过的坑和项目经验告诉你每个配置项背后的“为什么”以及如何根据你的硬件设计和应用需求做出最合适的选择。我们会从最基础的GPIO引脚分配和BOOT_DEF配置讲起一直深入到Secure ROM的安全API调用和DCSM安全分区管理目标是让你读完就能在自己的板子上动手实现。2. 启动模式整体设计与配置逻辑2.1 启动流程全景图在深入细节之前我们必须先建立起F28003x上电后的“世界观”。芯片复位释放后CPU并不是直接跑你的main()函数而是先跳转到Boot ROM中一段固化好的代码执行。这段ROM代码会执行一系列关键操作其决策逻辑可以用一个简化的流程图来理解但更重要的是理解其背后的设计哲学。首先Boot ROM会进行基本的CPU内核初始化并检查复位源。这里有一个极易忽略的细节只有上电复位POR和外部复位XRS会触发完整的时钟初始化流程例如默认使用10MHz的内部振荡器INTOSC2。如果是看门狗复位、软件复位等其他复位源Boot ROM会保持复位前的时钟配置不变。这意味着如果你的应用在运行时修改了PLL配置以获得更高主频发生看门狗复位后系统会以这个高主频继续运行Boot ROM代码这可能带来时序问题。因此在用户应用程序初始化时重新配置时钟到已知状态是一个好习惯。接着Boot ROM会读取一个至关重要的非易失性存储区域——BOOT_DEF。这个区域位于OTPOne-Time Programmable存储器中具体有两个位置Z1-OTP-BOOTDEFZone 1和Z2-OTP-BOOTDEFZone 2。芯片会使用哪个呢这取决于DCSM中哪个Zone是安全状态以及相应的配置。简单来说Boot ROM会尝试从有效的、已配置的BOOT_DEF位置获取启动模式。这个值决定了芯片下一步要去哪里找你的应用程序。2.2 BOOT_DEF详解与模式选择BOOT_DEF是一个8位的值每一位或每一组位都对应着一种启动方式。数据手册中的表格如SCI Boot Options, CAN Boot Options等给出了具体映射。但只看表格容易迷糊我们需要理解其编码规律。BOOT_DEF的位域通常这样划分位[7:5] 有时用于标识外设类型或特殊模式如等待模式。位[4:0] 具体定义所选外设的引脚映射MUX选项。例如对于SCI引导BOOTDEF 0x01 选择SCI-A使用默认引脚GPIO28 (RX) 和 GPIO29 (TX)。BOOTDEF 0x21 选择SCI-A但使用备用引脚GPIO17 (RX) 和 GPIO16 (TX)。这里就是第一个实操关键点你选择的BOOTDEF值必须与你硬件原理图上实际连接的引脚以及该引脚在所用芯片封装上支持的复用功能完全一致。F28003x有不同的封装如100-pin PZP80-pin PM不是所有GPIO在所有封装上都可用。如果你在100脚封装上设计使用GPIO8/9作为SCI但在80脚封装上这个引脚可能不存在那么批量生产时换用不同封装的芯片就会导致无法启动。务必在选型和画图阶段就对照芯片数据手册的“Pin Multiplexing”章节确认你计划用于Bootloader的引脚在目标封装上是否可用。2.3 各种启动模式的应用场景分析Flash启动 (BOOTDEF 0x00???): 最常见的方式程序已预先烧录在内部Flash。Boot ROM会直接跳转到Flash的特定入口地址通常是0x080000执行。这是产品量产时的标准模式。SCI/UART启动: 通过串口下载程序。优势是接口简单几乎任何电脑都有串口。缺点是速度相对较慢且需要主机端有对应的发送工具。适合用于现场调试、小批量生产或作为备份升级通道。SPI启动: 从外部SPI Flash或通过另一个MCU的SPI接口加载程序。速度比SCI快适合需要从低成本外部存储器启动的应用或者在大系统中由主控制器为DSP加载程序。I2C启动: 从外部EEPROM加载。常用于存储小规模的配置程序或第二阶段的Bootloader。I2C EEPROM成本低电路简单。CAN/CAN-FD启动: 在汽车电子或工业网络中极为重要。可以直接通过车载网络或工业总线对控制器进行固件刷新实现无接触式远程升级。CAN-FD提供了更高的数据吞吐量。并行启动: 通过并行的数据/地址总线从外部存储器如FPGA或CPLD快速加载大型程序。提供最高的加载速度但占用大量IO引脚硬件设计复杂。RAM启动: 主要用于仿真调试。程序通过JTAG直接加载到RAM中运行省去了烧写Flash的时间极大提升调试效率。等待模式: Boot ROM完成后进入低功耗等待状态等待通过特定外设如SCI、CAN的指令来唤醒并接收程序。这是一种灵活的“待命”启动方式。选择建议对于大多数产品我推荐采用“Flash主启动 一种通信接口作为升级通道”的组合策略。例如将BOOT_DEF默认配置为Flash启动但在应用程序中预留一个“固件升级模式”。当检测到升级触发条件如某个GPIO上拉、接收到特定CAN报文时软件主动触发一个软复位并在复位前通过某个非易失性标志如Flash中的一个字告诉Boot ROM这次进入SCI或CAN启动模式。这样正常上电直接运行需要升级时则进入Bootloader接收新固件。3. GPIO分配与硬件设计要点3.1 引脚复用冲突与排查配置BOOT_DEF后Boot ROM在初始化相应外设时会按照你选择的选项去配置GPIO的复用功能。这个过程发生在你的用户应用程序运行之前。这就引出了一个核心矛盾Boot ROM的引脚配置可能会与你应用程序中对该引脚的配置相冲突。举个例子你设置BOOTDEF0x01使用SCI-A引引脚为GPIO28/29。同时你的应用程序里可能将GPIO28初始化为一个普通的输出引脚来控制LED。如果系统从SCI启动模式正常加载并运行了你的程序那么程序初始化时重新配置GPIO28覆盖了Boot ROM的SCI配置这没问题。但是如果SCI引导失败比如没有收到主机数据Boot ROM可能会超时后回退到其他模式如Flash启动。此时GPIO28/29的状态可能已经被Boot ROM部分初始化而你的应用程序又试图将其配置为GPIO就可能出现不可预知的行为。规避策略物理隔离如果PCB空间允许为Bootloader通信专用预留一组引脚不在应用程序中复用它们。这是最干净的做法。软件检测与恢复在应用程序初始化序列的最开始读取BOOTSTAT寄存器地址0x0000 0002判断系统是从何种模式启动的。如果是从你计划用于Bootloader的外设启动的那么在初始化GPIO时就要格外小心可能需要先恢复到一个已知的输入状态再重新配置。后面我们会详细讲BOOTSTAT。使用备用引脚F28003x为许多外设提供了多组引脚映射。如果你的应用必须占用某组引脚可以尝试为Bootloader选择另一组备用引脚如SCI引导不用默认的GPIO28/29而用GPIO16/17。3.2 上拉/下拉电阻配置Bootloader通信接口的稳定性很大程度上取决于引脚在启动瞬间的电平状态。I2C的SDA/SCL需要上拉电阻这是常识。但对于SCI、SPI、CAN等接口TX、RX、CLK、CS等引脚在Boot ROM初始化前的状态浮空可能导致误触发。实践经验SCI/UART: TX引脚在初始化前应为高阻或输出高电平。RX引脚建议通过一个弱上拉电阻如10kΩ拉到VCC避免因噪声误触发起始位。特别是如果你的板子环境噪声较大这个上拉能显著提高启动可靠性。SPI: SPI的片选信号SPISTE通常是低电平有效。Boot ROM在SPI引导模式下会将其配置为输出并拉高不选中。为确保在Boot ROM控制前它处于无效状态高电平建议在硬件上增加一个上拉电阻。MOSI/MISO/CLK引脚在未初始化时状态不定但一般问题不大Boot ROM会快速接管。CAN: CANH和CANL需要终端电阻通常120Ω。这对总线通信的完整性至关重要Bootloader阶段也不例外。I2C: 必须加上拉电阻阻值根据总线速度和布线电容计算通常范围在2.2kΩ到10kΩ之间。一个真实的坑我曾调试一块板子SCI引导时好时坏。最终发现是RX引脚在连接器端悬空且板内走线较长耦合了开关电源的噪声。在Boot ROM采样起始位时噪声导致误判。增加一个10kΩ上拉电阻后问题彻底解决。所以不要吝啬这些电阻它们在批量生产时带来的稳定性收益远超其成本。3.3 电平转换与隔离考虑如果你的Bootloader主机如PC、网关与F28003x的IO电平不匹配如主机是5V TTL芯片是3.3V LVCMOS必须使用电平转换电路。同时在工业环境中通信线路可能较长或环境恶劣需要考虑隔离以保护核心控制板。电平转换 可使用专用的双向电平转换芯片如TXS0108E或简单的MOSFET电路。确保转换电路在Boot ROM初始化期间和初始化后都能正确传递信号。隔离 对于CAN、RS-485可复用SCI等接口通常使用隔离型的收发器芯片如ISO1050。需要注意隔离芯片的电源VCC2需要在Boot ROM运行前就已稳定建立否则通信无法进行。确保电源时序正确。4. 安全引导机制深度解析4.1 EXEONLY内存与安全启动流程F28003x的安全引导不仅仅是验证一个签名那么简单它构建了一个从存储到执行的全链条保护环境其核心是EXEONLY内存属性。什么是EXEONLY简单说就是一块内存区域可以是Flash Sector或RAM Block被配置为“仅可执行”。CPU可以从这里取指令运行但任何试图读取其数据的操作包括通过调试器JTAG、DMA传输、或CPU的数据读指令都将被阻止或者返回零值。这有效防止了攻击者通过内存读取来窃取你的核心算法。安全引导流程大致如下Boot ROM从启动介质如Flash读取最初的引导代码Bootloader。这段初始代码通常很小其职责是初始化最基本的环境然后调用Secure ROM中的安全API。安全API如CPU1BROM_calculateCMAC被调用来验证主应用程序镜像的完整性和真实性。验证通过一个存储在安全区域的“黄金签名”Golden CMAC Signature进行。验证通过后如果需要可以调用SecureCopyCodeZx函数将加密或受保护的主程序代码从EXEONLY Flash安全地拷贝到EXEONLY RAM中执行通常是为了提升性能。最后跳转到已验证的应用程序入口点执行。为什么需要安全拷贝因为Flash执行速度可能慢于RAM尤其是需要高性能计算的段落。SecureCopyCodeZx函数保证了这段关键代码在从Flash搬运到RAM的过程中不会被恶意代码篡改或窃听。4.2 Secure ROM关键API实战详解Secure ROM提供了一系列函数但最常用的是SecureCopyCodeZx和CPU1BROM_calculateCMAC。调用它们有严格的限制稍不注意就会导致系统复位。4.2.1 SecureCopyCodeZ1/Z2 函数这个函数用于将代码从EXEONLY Flash安全地复制到EXEONLY RAM。uint16_t SecureCopyCodeZ1(uint32_t size, uint16_t *dst, uint16_t *src);参数:size: 要复制的16位字的数量。dst: 目标地址EXEONLY RAM。必须按16位字对齐。src: 源地址EXEONLY Flash。必须按16位字对齐。返回值: 成功则返回实际复制的字数失败返回0。失败原因返回0:复制长度为0。复制操作跨越了Flash扇区边界。这是最常见的错误Flash和RAM不属于同一个安全ZoneZone1或Zone2。Flash和/或RAM没有设置为EXEONLY属性。复制过程中发生错误。关键限制与实操要点扇区边界 F28003x的Flash被划分为多个扇区。SecureCopyCodeZx要求一次复制操作不能跨扇区。这意味着你的函数或代码块必须完全位于一个Flash扇区内。在链接器命令文件.cmd中分配代码段时必须使用SECTION指令的RUN_START和LOAD_START来精确控制代码的加载地址Flash和运行地址RAM并确保加载地址范围在一个扇区内。中断禁用在调用任何Secure ROM函数前必须禁用全局中断DINT;。因为如果CPU在Secure ROM函数内部响应中断NMI、ITRAP等会导致整个子系统复位RSN。这会使调试变得异常困难因为系统会无声无息地重启。务必在调用前DINT调用后根据需要EINT。Zone一致性 Zone1的Flash只能拷贝到Zone1的RAM不能跨Zone操作。这要求你在规划内存布局时就要明确代码的安全归属。4.2.2 CPU1BROM_calculateCMAC 函数这个函数用于计算一段内存区域的CMACCipher-based Message Authentication Code签名并与预存的“黄金签名”比对是验证代码完整性的核心。uint32_t CPU1BROM_calculateCMAC(uint32_t startAddress, uint32_t endAddress, uint32_t signatureAddress);参数:startAddress: 待计算内存区域的起始地址。endAddress: 待计算内存区域的结束地址注意是结束地址不是长度。signatureAddress: 存储“黄金签名”的地址。签名长度为128位4个32位字。返回值:0x00000000U: 成功签名匹配。0xFFFFFFFFU: 失败计算出的签名与黄金签名不匹配。0xA5A5A5A5U: 失败内存范围未对齐到128位边界或长度为0。0xE1E1E1E1U: 失败AES引擎超时硬件故障。实操要点地址对齐startAddress必须是128位16字节对齐的。链接器脚本中需要验证你的代码段或数据段的起始地址是16字节对齐的。可以使用ALIGN(16)指令。签名存储 “黄金签名”必须预先计算好并存储在安全的位置通常是OTP或受保护的Flash区域。这个签名的生成需要在开发主机上完成使用与芯片内部相同的AES-CMAC密钥和算法。TI提供了相关的工具和库来生成这个签名。验证范围 你需要决定对哪些内存区域进行验证。通常是整个应用程序的文本段.text。但要注意如果应用程序包含在运行时会被修改的数据如.cinit这些区域不应该包含在CMAC验证中因为它们的初始值在运行时可能被覆盖导致验证失败。4.3 DCSM双区安全与密码管理DCSM是F28003x安全架构的看门人。它将芯片资源Flash扇区、RAM块划分为两个独立的安全区域Zone1和Zone2。每个区域有自己独立的128位密码。资源分配GRABRAMx/GRABSECTx 通过配置USER OTP中的GRABRAMx控制RAM和GRABSECTx控制Flash扇区寄存器你可以决定每一块内存属于哪个Zone或者不加密。01/10: 表示资源属于Zone1。10/01: 表示资源属于Zone2。10/10: 资源不加密Unsecure。11/11:危险如果任何一个Zone设置了密码此资源将无法访问。切勿在编程后保留此默认值。密码匹配流程PMF 要解锁一个Zone必须执行密码匹配流程。流程大致是将正确的128位密码写入对应的CSMKEY寄存器CSMKEY0-3然后向CSMKEY寄存器执行一个假的写操作写入任意值来触发比较。如果匹配成功该Zone即被解锁。关于密码的致命细节全1密码0xFFFF...不再是万能钥匙 在早期C2000器件中全1密码表示禁用安全。在F28003x上全1密码会导致该Zone进入“锁定”BLOCKED状态永远无法解锁这是为了应对某些攻击手段而做的安全强化。全0密码0x0000...是永久锁 如果你将密码设置为全0该Zone将进入“永久锁定”LOCKED状态即使你知道密码也无法通过PMF解锁。这意味着代码无法调试Flash无法再编程。绝对不要使用全0密码TI出厂默认值 TI在出厂时已经在每个Zone Select Block的CSMPSWD1密码的第二部分中编程了特定的值非全1以防止意外进入BLOCKED状态。Boot ROM会使用这个默认值来初始化CSMKEY寄存器使得芯片在用户未编程自定义密码前处于解锁状态。用户编程自己的密码时可以修改这些位但通常建议保留TI编程的位为0只修改其他位。安全开发流程建议开发阶段 保持DCSM未编程使用TI默认密码或使用一个已知的测试密码。这样可以通过JTAG自由调试和烧写。测试阶段 在最终代码确定后生成一个强密码使用真随机数生成器并更新链接器脚本将密码字嵌入到工程中一个特定的段例如.csm_pswd。量产编程 a. 使用编程工具如TI的Uniflash配合XDS调试器先烧写用户程序到Flash。 b. 然后通过调试器脚本或专用命令将密码写入OTP的CSMPSWD区域。OTP一旦写入无法擦除c. 最后根据需要配置GRABRAMx/GRABSECTx寄存器将Flash和RAM分配给对应的Zone。密码备份 将密码安全地离线存储例如使用硬件安全模块HSM或打印出来密封保存。一旦丢失芯片将无法再次调试或更新。5. 从理论到实践配置与调试全流程5.1 硬件设计与BOOT_DEF烧写假设我们要设计一个支持SCI串口升级的产品硬件上使用GPIO16 (TX) 和 GPIO17 (RX) 作为SCI-A。原理图设计连接GPIO16到UART收发器的TXGPIO17到RX。在GPIO17RX上放置一个10kΩ上拉电阻至3.3V。确保UART收发器的电源在芯片上电后能快速稳定。确定BOOT_DEF值查表对应项目正文中的Table 4-39SCI Boot Option 1对应的BOOTDEF Value是0x21。这意味着我们需要将OTP中的BOOT_DEF位置编程为0x21。烧写BOOT_DEF到OTPOTP编程是不可逆的务必谨慎。通常使用TI的CCSCode Composer Studio配合XDS调试器来完成。在CCS中连接到目标板打开Memory Browser。导航到BOOT_DEF的OTP地址例如Zone1的0x00078040。重要 OTP通常按128位4个字为一个单元进行编程并且需要先擦除写为0再编程写为1。直接写入0x21可能不够需要查看具体OTP扇区的编程规则。更可靠的方法是使用TI提供的Flash API或Uniflash工具中的OTP编程脚本。一个典型的脚本步骤是解锁OTP扇区 - 擦除 - 写入数据包括BOOT_DEF值和其他保留位 - 验证 - 锁定。5.2 生成可引导的应用程序镜像你的应用程序需要被转换成Boot ROM能够识别的数据流格式。这通过TI的hex2000工具完成。编译链接 正常编译你的工程生成.outELF格式文件。在链接器命令文件.cmd中你需要明确定义程序的入口点_c_int00或自定义函数。合理分配代码段和数据段到Flash和RAM特别是注意EXEONLY区域的划分。使用hex2000转换hex2000.exe my_app.out -boot -sci8 -a -o my_app_boot.hex-boot: 将所有段转换为可引导格式。-sci8: 指定为SCI 8位模式引导表格式。-a: 输出ASCII-Hex格式便于查看和通过串口发送。-o: 指定输出文件名。生成的my_app_boot.hex文件就包含了数据流头Key Value, Entry Point等和你的程序数据。你可以使用串口工具如Tera Term、SecureCRT的发送文件功能将这个文件发送给处于SCI引导模式下的F28003x。数据流结构回顾 转换后的文件结构遵循严格的格式Word 0: 关键值Key Value0x08AA代表8位流。Word 1-8: 8个保留字用于初始化外设寄存器SCI引导通常为0。Word 9-10: 22位入口点地址程序开始执行的地址。后续数据: 以块Block形式组织每个块包含【块大小16位字数量】-【目标地址32位】-【数据...】。以块大小为0表示结束。5.3 安全引导镜像的生成与验证流程要实现安全引导步骤更复杂准备应用程序 编写你的主程序并在链接器中将其文本段.text分配到EXEONLY Flash区域例如Zone1 Flash的一个扇区。生成原始二进制文件 使用hex2000和ofd2000工具从.out文件生成纯二进制.bin文件。计算CMAC签名使用TI提供的安全工具链通常包含在C2000Ware或独立的Security Tool中指定AES密钥这个密钥是芯片出厂时烧录在PUF或EFUSE中的或由你指定并安全存储和你的.bin文件计算其CMAC签名。这个生成的签名就是“黄金签名”。嵌入签名 将“黄金签名”写入到你的工程中的一个特定数据段例如.cmac_signature并确保链接器将其放置在一个安全的、已知的地址例如EXEONLY Flash的末尾。构建安全引导加载器编写一个小的Bootloader程序。它的职责是 a. 初始化最基本的硬件如时钟、GPIO。 b.禁用中断。 c. 调用CPU1BROM_calculateCMAC验证主应用程序区域的签名。 d. 如果验证通过可选地调用SecureCopyCodeZ1将关键代码段拷贝到EXEONLY RAM。 e. 跳转到主应用程序入口点。这个Bootloader本身可能也需要被签名通过另一个签名或者被放置在受信任的、较小的引导扇区中。完整镜像打包 将安全Bootloader和已签名的主应用程序一起生成最终的烧写镜像。这个镜像可以通过JTAG烧写到Flash也可以通过安全通信通道如已建立安全会话的CAN进行现场更新。5.4 调试技巧与状态信息读取调试Bootloader尤其是安全相关的部分非常具有挑战性因为一旦使能安全功能JTAG调试访问就会受到限制。充分利用BOOTSTAT寄存器地址0x0000 0002(M0RAM)。这个32位寄存器记录了Boot ROM执行过程中的各种状态。在应用程序开头读取并打印/保存这个值。通过解析其位域见Table 4-51你可以知道系统是从哪种模式启动的Flash, SCI, CAN等对应位[3:0]或特定状态位。启动过程中是否发生了NMI如缺失时钟、RAM错误。PLL是否成功使能。DCSM初始化是否出错。例如如果SCI引导总是失败你可以检查BOOTSTAT看是否进入了SCI引导流程位0x00000006还是直接回退到了Flash启动。逐步使能安全功能绝对不要一开始就编程密码和配置DCSM。先让整个系统在不安全模式下完全跑通。然后逐步添加安全特性先测试SecureCopyCode不设EXEONLY再测试CMAC验证使用一个已知的测试密钥最后再配置DCSM和OTP。使用GPIO作为调试指示灯在Bootloader和应用程序的关键步骤如开始、验证成功、验证失败、跳转前设置不同的GPIO电平或翻转信号。用示波器或逻辑分析仪观察这些引脚可以清晰地看到代码执行流程在哪里中断是验证失败还是拷贝出错。处理Secure ROM API调用失败SecureCopyCodeZx或SecureCRCCalcZx返回0表示失败。失败原因很多。除了检查参数对齐、Zone属性、EXEONLY设置外最容易被忽略的是中断。确保在调用前执行了DINT并且没有不可屏蔽中断NMI在此时发生。可以在调用前后读取特定的状态寄存器或设置标志位到非安全RAM中以便在复位后检查。6. 常见问题排查与避坑指南以下是我在多个项目中总结的典型问题及其解决方案希望能帮你节省大量调试时间。问题现象可能原因排查步骤与解决方案系统无法启动停留在Boot ROM1. BOOT_DEF值错误或未编程。2. 用于引导的GPIO引脚被硬件拉死如对地短路。3. 时钟未就绪如外部晶振失效。1. 检查BOOTSTAT寄存器确认Boot ROM识别出的启动模式。2. 测量引导引脚电压确认在Boot ROM初始化前处于高阻或正确状态。3. 如果是POR复位检查INTOSC2是否正常。测量CLKOUT引脚如果使能看是否有10MHz时钟输出。SCI/CAN等外设引导失败超时后跳转1. 主机发送的数据流格式错误Key Value、波特率等。2. 波特率不匹配。3. 硬件连接问题线序反、电平不匹配。4. GPIO复用冲突引脚未被正确初始化为外设功能。1. 用逻辑分析仪抓取Boot ROM初始化后的引脚波形看是否有正确的起始位/数据。2. 确认主机发送工具的数据格式8位/16位MSB/LSB顺序与hex2000生成的文件一致。3. Boot ROM使用默认波特率如SCI是9600。确认主机端波特率设置正确。4. 检查原理图和PCB确认TX/RX交叉连接电平转换电路工作正常。调用SecureCopyCode返回01. 源或目标地址未按16位字对齐。2. 复制操作跨越了Flash扇区边界。3. 源或目标内存未设置为EXEONLY。4. 源和目标不属于同一个安全Zone。5.全局中断未禁用。1. 在调试器中查看src和dst地址最低位应为0地址为偶数。2. 计算srcsize*2是否超过了当前Flash扇区的结束地址。需要调整链接器脚本让要拷贝的代码段完整地位于一个扇区内。3. 检查DCSM的EXEONLY配置位是否已正确设置。4. 检查GRABSECT和GRABRAM配置确保Flash扇区和RAM块属于同一Zone。5.在调用前插入asm(“ DINT”);调用后根据需要asm(“ EINT”);。这是最高频的错误CMAC验证始终失败1. “黄金签名”计算错误或存储地址错误。2. 验证的内存范围startAddress,endAddress与生成签名时使用的范围不一致。3. 内存范围未128位对齐。4. 用于计算签名的AES密钥与芯片内部密钥不匹配。1. 使用TI安全工具重新计算签名并确保工具版本与芯片ROM版本兼容。2. 仔细核对链接器脚本中代码段的LOAD_START和LOAD_END或长度确保CPU1BROM_calculateCMAC调用参数与之完全一致。3. 确保startAddress是16的倍数。4. 确认你使用的是正确的密钥源PUF, OTP Key Store等。开发阶段可能使用测试密钥。使能DCSM后JTAG无法连接1. Zone已锁定密码错误或未执行PMF。2. 要调试的代码/数据所在的Flash/RAM被配置为属于一个已锁定的Zone。3. JTAG端口被锁定如果使能了JTAGLOCK。1. 这是预期行为。安全模式下JTAG访问被阻断。你需要通过一个已知的安全入口点如未加密的Bootloader来执行PMF解锁Zone或者完全擦除Flash这会清除安全配置但可能也擦除了你的代码。2. 检查GRABSECT/GRABRAM配置确保你试图访问的内存区域对当前CPU上下文是可访问的。3. 如果启用了JTAGLOCK需要提供JTAG密码才能解锁调试接口。系统在Secure ROM函数中随机复位极高概率是因为在Secure ROM函数执行期间发生了中断。1. 检查所有中断源定时器、外设、NMI。在调用Secure ROM API前确保禁用所有可屏蔽中断。2. 检查是否有硬件故障触发了NMI如时钟丢失、RAM不可纠正错误。这些NMI无法通过DINT屏蔽需要在进入安全操作前确保系统状态稳定。从RAM调试正常烧写到Flash后失败1. Flash等待状态Wait-states未正确配置。2. 代码中有关键段未正确从Flash复制到RAM对于需在RAM中运行的函数。3. Flash扇区安全属性配置错误导致代码无法读取或执行。1. 确保系统初始化代码在Flash中运行的部分正确配置了Flash控制寄存器的等待状态以匹配你的CPU主频。2. 使用#pragma CODE_SECTION将性能关键函数分配到特定段并在链接器命令文件中用RUN指令指定其在RAM中运行用LOAD指令指定其在Flash中加载。并在启动时正确拷贝。3. 检查DCSM配置确保应用程序所在的Flash扇区对当前Zone是可读/可执行的。最后一个人心得启动和安全配置是嵌入式系统的“地基”。地基没打牢上层建筑再漂亮也容易崩塌。对于F28003x这类功能丰富的芯片强烈建议在项目初期就建立一个专门的测试工程这个工程不实现业务逻辑只做三件事1) 测试所有你计划使用的启动模式2) 测试安全API的调用流程3) 验证DCSM配置后的系统行为。把这个测试工程当作硬件bring-up和软件框架验证的标准步骤能极大避免在项目后期集成时遇到令人头疼的启动或安全问题。毕竟在逻辑复杂的应用程序中调试一个Bootloader问题无异于大海捞针。