1. 项目概述与核心价值
在电机控制、数字电源或者任何对时序有苛刻要求的实时嵌入式系统里,有两个概念是工程师的“心头肉”,也是调试时的“老大难”:一个是外部中断(XINT),另一个是同步触发(SYNC/SOC)。前者是你与外部世界紧急通信的“热线电话”,后者则是协调内部各个功能模块(如PWM、ADC、捕获单元)步调一致的“指挥棒”。很多朋友在开发TMS320F2837xD这类高性能DSP时,往往把重心放在算法和PWM波形生成上,却对底层这些关键的配置寄存器一知半解,结果就是系统运行时总有些“说不清、道不明”的时序错乱或响应延迟。
今天,我们就抛开库函数和配置工具,直接“解剖”TMS320F2837xD系统控制模块中最核心的两组寄存器:XINT_REGS和SYNC_SOC_REGS。我会结合自己这些年调试伺服驱动器和光伏逆变器的实际经验,带你从芯片设计者的角度,理解每一个配置位的意图,并给出能直接抄作业的代码片段和避坑指南。你会发现,一旦掌握了这些寄存器的“脾气”,你就能精准地驾驭这颗双核DSP,实现纳秒级的事件响应和模块间无缝协同,这才是发挥其200MHz主频和丰富外设优势的真正钥匙。
2. 外部中断(XINT)寄存器组深度解析
外部中断是DSP响应异步事件最直接的方式。F2837xD提供了最多5个独立的外部中断源(XINT1-XINT5),每个都拥有独立的配置和计数器。理解其寄存器是避免误触发和实现精准事件计时的第一步。
2.1 XINTxCR:中断的“开关与极性控制器”
每个外部中断都有一个对应的配置寄存器(XINT1CR - XINT5CR),结构完全一致。我们以XINT1CR为例,其16位结构看似简单,却藏着关键细节。
寄存器位域精讲:
- 位0 - ENABLE:中断总开关。这是最容易被忽略的初始化步骤之一。很多工程师配置了GPIO复用、设置了极性,但忘了将此位置1,导致中断死活不触发。务必在完成所有其他配置(包括PIE向量表)后,最后才将此位置1,以避免初始化过程中的毛刺信号导致误中断。
- 位[3:2] - POLARITY:触发边沿选择。这是理解中断行为的核心。
00:下降沿触发。当输入信号从高电平跳变到低电平时,产生中断。01:上升沿触发。当输入信号从低电平跳变到高电平时,产生中断。10:再次是下降沿触发。这里手册的重复列出(00和10都是下降沿)可能源于不同芯片型号的兼容性设计,在F2837xD上,我们通常只使用00和01。11:双边沿触发。任何电平跳变(上升或下降)都会产生中断。这个模式非常有用,例如用于测量一个未知频率的方波周期,无需预先知道其占空比。
实操心得:选择触发边沿时,必须考虑外部信号的硬件特性。例如,一个机械按键通常连接成低有效(按下时接地),那么就应该配置为下降沿触发。如果使用光耦隔离的信号,则需要根据光耦的输出类型(常开/常闭)来判定有效边沿。务必用示波器确认实际信号波形与你的配置匹配,这是排查“中断不触发”或“中断过于频繁”问题的首要步骤。
配置代码示例(寄存器直接操作):
// 假设XINT1对应GPIO0,我们配置为上升沿触发 EALLOW; // 解除寄存器保护 // 首先,确保中断禁用,避免配置过程中的干扰 XintRegs.XINT1CR.bit.ENABLE = 0; // 配置触发极性为上升沿 (01b) XintRegs.XINT1CR.bit.POLARITY = 1; // ... (此处配置GPIO0为XINT1功能,配置PIE中断等) // 最后,使能中断 XintRegs.XINT1CR.bit.ENABLE = 1; EDIS; // 恢复寄存器保护2.2 XINTxCTR:被低估的“事件间隔计时器”
这是XINT模块一个极具价值但常被忽略的功能。每个外部中断都有一个16位的自由运行计数器(XINT1CTR - XINT3CTR,XINT4/5无此计数器),它以系统时钟(SYSCLKOUT)频率递增。
工作机制:
- 计数器始终在运行(只要对应中断被使能)。
- 当检测到你所设定的有效触发边沿(由POLARITY位决定)时,计数器立即复位到0x0000。
- 然后继续计数,直到下一个有效边沿到来,再次复位。
- 如果中断被禁用(ENABLE=0),计数器停止。
这个计数器能做什么?
- 精确测量脉冲周期或频率:无需启用捕获单元。在中断服务函数(ISR)中读取XINTxCTR的值,这个值就是从上一次触发边沿到当前边沿所经过的系统时钟周期数。结合系统时钟频率,可以直接计算出外部信号的周期。这对于测量低频或中频信号(如编码器Z脉冲、风速传感器脉冲)特别方便。
- 诊断与调试:你可以定期读取计数器值,监控外部事件是否如期发生。如果计数器值持续增长到一个异常大的值(接近65535并翻转),可能意味着外部信号丢失或触发条件未满足。
- 滤除抖动:通过软件判断两次中断之间的计数器值是否大于某个阈值,可以有效地实现硬件信号去抖。
使用示例:测量两个下降沿之间的时间
volatile unsigned int last_counter_value = 0; volatile float signal_period_us = 0.0; // 信号周期,单位微秒 #define SYSTEM_CLK_MHZ 200.0 // 假设系统时钟200MHz interrupt void xint1_isr(void) { unsigned int current_counter = XintRegs.XINT1CTR.bit.INTCTR; // 计算时间间隔 (单位:微秒) // 注意:计数器在中断发生时已复位,current_counter是上一次的计数值 signal_period_us = (float)current_counter / SYSTEM_CLK_MHZ; // 如果需要,可以保存当前值供下次使用 // last_counter_value = current_counter; // 清除中断标志(在PIE模块) PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; }重要提示:
XINTxCTR是一个只读寄存器。你无法直接写入它来设定初始值。它的复位只能通过有效的信号边沿或整个系统的复位(SYSRSn)来实现。这意味着你无法“手动”启动一次测量,必须依赖外部信号的真实边沿。
3. 同步与启动转换(SYNC/SOC)寄存器组实战指南
在复杂的控制系统中,经常需要让多个模块在精确的同一时刻启动某项操作,例如让多个ADC模块同时采样,或者让PWM波形与某个外部事件同步。F2837xD的SYNC_SOC_REGS寄存器组就是为此而生的“联动指挥中心”。
3.1 SYNCSELECT:同步信号的路由交换机
这个32位寄存器是同步系统的核心。它决定了同步输入信号(SYNCIN)的来源和同步输出信号(SYNCOUT)的去向。理解它,就理解了芯片内部同步信号的流向。
核心功能拆解:
SYNCOUT输出选择(位[28:27]):决定哪个内部事件可以作为全局同步信号输出到外部引脚(SYNCOUT)或给其他模块使用。
00: EPWM1的SYNCOUT作为源。01: EPWM4的SYNCOUT作为源。10: EPWM7的SYNCOUT作为源。11: EPWM10的SYNCOUT作为源。- 应用场景:假设你有一个主控EPWM1,希望它的时基零点信号能同步其他三个从属EPWM模块(EPWM2, EPWM3)以及另一个芯片。你可以将EPWM1配置为产生SYNCOUT事件,并在此选择
00,那么这个同步信号就会被广播出去。
同步输入源选择(位[14:0]):这组位域(ECAP4SYNCIN, ECAP1SYNCIN, EPWM10SYNCIN, EPWM7SYNCIN, EPWM4SYNCIN)分别用于配置特定模块的同步输入信号来自哪里。这是一个多路选择器(MUX)��
- 每个字段通常有8个选项(3位宽),源包括:EPWM1/4/7/10的SYNCOUT、ECAP1的SYNCOUT、外部引脚EXTSYNCIN1/2。
- 关键逻辑:例如,
EPWM4SYNCIN位域配置的是EPWM4模块的同步输入源。你可以将它设置为001,这意味着EPWM4模块将接收来自EPWM4自身的SYNCOUT作为同步信号(通常用于自同步或测试),或者设置为000,接收来自EPWM1的SYNCOUT,从而实现EPWM1主控,EPWM4跟随的同步关系。
配置案例:构建一个主从EPWM同步链目标:EPWM1作为主机,EPWM4和EPWM7作为从机,同步启动。
EALLOW; // 1. 配置SYNCOUT输出源为主机EPWM1 SysCtrlRegs.SYNCSELECT.bit.SYNCOUT = 0; // 00 = EPWM1SYNCOUT // 2. 配置从机EPWM4的同步输入源为主机EPWM1的输出 SysCtrlRegs.SYNCSELECT.bit.EPWM4SYNCIN = 0; // 000 = EPWM1SYNCOUT // 3. 配置从机EPWM7的同步输入源为主机EPWM1的输出 SysCtrlRegs.SYNCSELECT.bit.EPWM7SYNCIN = 0; // 000 = EPWM1SYNCOUT // 4. (在EPWM模块配置中)需要使能主机EPWM1的SYNCOUT事件产生, // 以及配置从机EPWM4/7在接收到SYNCIN时复位时基计数器(TBCTR=0)。 // 这部分配置在EPWM模块的TBCTL寄存器中,例如: // EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_OUT; // EPWM1输出同步脉冲 // EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // EPWM4禁用输出 // EPwm4Regs.TBCTL.bit.PHSEN = TB_ENABLE; // EPWM4使能相位同步 // EPwm4Regs.TBPHS.half.TBPHS = 0; // 相位偏移设为0,完全同步 EDIS;避坑指南:
SYNCSELECT寄存器受EALLOW保护,且通常由SYNCSOCLOCK寄存器锁定(见3.3节)。务必在系统初始化早期,完成所有同步路由配置后,再将其锁定,防止程序跑飞后意外修改同步关系,导致系统时序崩溃。
3.2 ADCSOCOUTSELECT:ADC外部触发信号的“发射器”
这个寄存器用于将内部EPWM模块产生的ADC启动转换(SOC)信号,映射到特定的外部引脚(ADCSOCAO/ADCSOCBO)上,用以触发片外ADC芯片。每个EPWM模块(1-12)都有两个SOC信号:SOCA和SOCB。
寄存器结构解读:
- 位[27:16]:
PWMxSOCBEN(x=12 to 1)。置1使能对应EPWM模块的SOCB信号连接到ADCSOCBO输出引脚。 - 位[11:0]:
PWMxSOCAEN(x=12 to 1)。置1使能对应EPWM模块的SOCA信号连接到ADCSOCAO输出引脚。
重要特性:当某个SOC信号被选中输出时,它会在触发事件发生时,产生一个持续32个SYSCLK周期的低电平脉冲。这个设计非常贴心,直接满足了大多数外部ADC芯片的触发引脚要求(低有效脉冲触发)。
应用场景:在交错并联PFC或三相逆变器中,你可能使用多个EPWM模块产生互补的PWM驱动信号,并希望在每个PWM周期的特定时刻(如计数器为零时)触发外部高精度ADC采样母线电压或电流。
EALLOW; // 假设我们使用EPWM1的SOCA事件(在TBCTR=0时产生)来触发外部ADC SysCtrlRegs.ADCSOCOUTSELECT.bit.PWM1SOCAEN = 1; // 使能EPWM1 SOCA输出到ADCSOCAO引脚 // 同时,我们还想用EPWM4的SOCB事件(在CMPB匹配时产生)触发另一个ADC通道 SysCtrlRegs.ADCSOCOUTSELECT.bit.PWM4SOCBEN = 1; // 使能EPWM4 SOCB输出到ADCSOCBO引脚 // 注意:需要确保对应的GPIO引脚已复用为ADCSOCAO/ADCSOCBO功能。 EDIS;注意事项:
ADCSOCOUTSELECT寄存器同样受EALLOW保护,且可被锁定。一个常见的错误是同时使能了多个EPWM模块的SOC信号到同一个输出引脚。虽然硬件上允许,但这会导致“线与”逻辑,如果多个信号源不同步,会产生不可预期的短脉冲。通常建议一个输出引脚只连接一个信号源,除非你明确需要逻辑“或”的关系。
3.3 SYNCSOCLOCK:配置锁,安全卫士
这是一个至关重要的安全寄存器。它包含两个“一次性写入”锁定位:
- 位0 - SYNCSELECT:锁定
SYNCSELECT寄存器。置1后,SYNCSELECT寄存器将变为只读(写入操作被忽略),直到下一次系统复位。 - 位1 - ADCSOCOUTSELECT:锁定
ADCSOCOUTSELECT寄存器。功能同上。
“一次性写入”(WSonce)机制:这些锁定位的特点是,你只能从0写成1,而不能从1写成0(除非系统复位)。这意味着锁定的操作是不可逆的。
为什么需要锁定?在实时控制系统中,同步关系和ADC触发时序是系统稳定性的基石。如果在程序运行时(尤其是双核系统中),这些配置被意外修改(例如由于指针错误、堆栈溢出或另一个内核的误操作),可能导致PWM失步、ADC采样错乱,进而引发炸机等严重事故。锁定机制就是为了防止这种灾难性的软件错误。
标准配置流程:
EALLOW; // 1. 配置同步和ADC触发路由 SysCtrlRegs.SYNCSELECT.all = ...; // 你的详细配置 SysCtrlRegs.ADCSOCOUTSELECT.all = ...; // 你的详细配置 // 2. 锁定这些配置,防止后续被篡改 SysCtrlRegs.SYNCSOCLOCK.bit.SYNCSELECT = 1; SysCtrlRegs.SYNCSOCLOCK.bit.ADCSOCOUTSELECT = 1; EDIS; // 从此以后,对SYNCSELECT和ADCSOCOUTSELECT的写入将无效,但读取正常。核心安全原则:“早配置,早锁定”。在系统初始化阶段,完成所有外设时钟、GPIO、PIE的配置后,就应该立即配置并锁定这些关键的全局路由寄存器。这应该成为F2837xD项目开发中一个铁打的习惯。
4. 高级应用:DMA与CLA的触发源选择
F2837xD的强大之处还在于其辅助处理单元(CLA)和直接内存访问(DMA),它们可以独立于CPU工作,极大减轻CPU负担。而让它们高效工作的关键,是为其任务或通道分配合适的触发源。DMA_CLA_SRC_SEL_REGS寄存器组就是用来做这件事的。
4.1 CLA任务触发源选择(CLA1TASKSRCSEL1/2)
CLA有8个任务(TASK1-TASK8),每个任务都可以由一个特定的硬件事件触发。CLA1TASKSRCSEL1(控制TASK1-4)和CLA1TASKSRCSEL2(控制TASK5-8)寄存器,每个8位字段对应一个任务,用于选择其触发源。
触发源编码:这8位值是一个编码,对应芯片内部庞大的触发源列表(在技术参考手册的“Interrupts and Triggers”章节有完整列表)。例如:
0x0000: 无触发(软件启动)0x0007: EPWM1的SOCA事件0x000B: EPWM1的SOCB事件0x0800: ADCINT1(ADC序列1中断)0x2A00: CPU Timer 0周期中断0x2B07: 外部中断XINT1
配置示例:让ADC转换完成自动触发CLA任务进行滤波计算
EALLOW; // 假设我们希望ADC序列1转换结束(ADCINT1)触发CLA的TASK1 // 首先查找手册,ADCINT1的触发源编码可能是 0x0800 (此处需查表确认) SysCtrlRegs.CLA1TASKSRCSEL1.bit.TASK1 = 0x0800; // 同样,可以配置其他任务,例如用EPWM1的周期事件触发TASK2做电流环计算 // EPWM1时间基准计数器等于零(TBCTR=0)事件的触发源编码可能是 0x0001 SysCtrlRegs.CLA1TASKSRCSEL1.bit.TASK2 = 0x0001; EDIS; // 随后,需要在CLA的代码(.cla文件)中,配置TASK1和TASK2的MPC函数, // 并在主CPU中使能CLA及其对应任务。4.2 DMA通道触发源选择(DMACHSRCSEL1/2)
DMA有6个通道(CH1-CH6),其触发源选择原理与CLA任务类似,通过DMACHSRCSEL1(CH1-4)和DMACHSRCSEL2(CH5-6)寄存器配置。
典型应用:使用PWM事件触发DMA搬运ADC结果在���机控制中,通常在每个PWM周期中点采样相电流。我们可以配置ADC在该时刻转换,并用同一个PWM事件触发DMA,将ADC结果寄存器自动搬运到指定的内存数组,完全无需CPU干预。
EALLOW; // 假设使用EPWM1的SOCA事件(发生在PWM周期中点)来触发DMA通道1 // EPWM1 SOCA的DMA触发源编码可能是 0x07 (需查表确认) SysCtrlRegs.DMACHSRCSEL1.bit.CH1 = 0x07; EDIS; // 然后,需要配置DMA通道1:设置源地址为ADC结果寄存器,目标地址为内存数组, // 设置搬运数据量、地址增量模式等。具体配置在DMA模块寄存器中完成。4.3 锁定机制(CLA1TASKSRCSELLOCK, DMACHSRCSELLOCK)
与SYNCSOCLOCK类似,这两个寄存器分别用于锁定CLA任务和DMA通道的触发源选择寄存器。一旦锁定,配置将不可更改,确保了触发逻辑的确定性。
EALLOW; // 配置完CLA和DMA触发源后,立即锁定 SysCtrlRegs.CLA1TASKSRCSELLOCK.bit.CLA1TASKSRCSEL1 = 1; SysCtrlRegs.CLA1TASKSRCSELLOCK.bit.CLA1TASKSRCSEL2 = 1; SysCtrlRegs.DMACHSRCSELLOCK.bit.DMACHSRCSEL1 = 1; SysCtrlRegs.DMACHSRCSELLOCK.bit.DMACHSRCSEL2 = 1; EDIS;5. 双核系统中的资源协调与Flash泵信号量
对于F2837xD双核芯片,两个CPU核(CPU1和CPU2)可能都需要访问共享资源,最典型的就是Flash编程泵(Flash Pump)。在对Flash存储器进行擦写操作时,需要泵来提供高压,这个泵是共享资源。PUMPREQUEST寄存器就是一个简单的信号量(Semaphore),用于协调双核对Flash泵的访问。
5.1 PUMPREQUEST寄存器工作机制
- 位[31:16] - KEY:密钥域。任何对信号量位(
PUMP_OWNERSHIP)的写操作,必须同时向KEY域写入0x5A5A,否则写操作被忽略。这是一种写保护机制。 - 位[1:0] - PUMP_OWNERSHIP:泵所有权状态。
00或11:只读状态。表示CPU1当前控制着泵,但CPU2可以随时发起“夺取”请求。01:CPU2独占。CPU2获得了泵的独占控制权,并且锁定了信号量寄存器本身。只有CPU2可以将其释放回00或11。10:CPU1独占。CPU1获得了泵的独占控制权,并且锁定了信号量寄存器本身。只有CPU1可以将其释放回00或11。- 非法转换:
01->10或10->01是不允许的。这防止了所有权的强制抢夺,必须由当前所有者释放。
5.2 双核Flash编程的规范流程
假设CPU1需要执行Flash擦写操作:
- CPU1尝试获取所有权:它向
PUMPREQUEST寄存器写入0x5A5A0002(KEY=0x5A5A,OWNERSHIP=10)。 - 操作成功条件:只有当当前状态是
00或11时,这个操作才会成功将状态变为10(CPU1独占)。如果当前状态已经是01(CPU2独占),则写入无效,CPU1需要等待或与CPU2协商。 - CPU1执行操作:获得独占权后,CPU1可以安全地使用Flash泵进行擦写。
- CPU1释放所有权:操作完成后,CPU1写入
0x5A5A0000,将状态恢复为00,释放泵资源。
代码示例(CPU1侧):
#define PUMP_KEY 0x5A5A // 函数:请求Flash泵独占权 bool acquire_flash_pump(void) { EALLOW; // 读取当前状态 uint16_t current_state = SysCtrlRegs.PUMPREQUEST.bit.PUMP_OWNERSHIP; // 只有状态为00或11时,CPU1才能请求独占 if (current_state == 0x0 || current_state == 0x3) { // 写入密钥和请求独占位(10) SysCtrlRegs.PUMPREQUEST.all = (PUMP_KEY << 16) | 0x2; // 再次读取确认 if (SysCtrlRegs.PUMPREQUEST.bit.PUMP_OWNERSHIP == 0x2) { EDIS; return true; // 获取成功 } } EDIS; return false; // 获取失败(可能被CPU2占用) } // 函数:释放Flash泵 void release_flash_pump(void) { EALLOW; // 只有所有者才能释放。写入密钥和状态00。 SysCtrlRegs.PUMPREQUEST.all = (PUMP_KEY << 16) | 0x0; EDIS; }双核协作要点:这个机制非常原始,它只解决了硬件资源的互斥访问,但没有解决“等待”问题。在实际双核通信中,通常需要结合更高级的软件协议(如通过共享内存设置标志、使用IPC中断)来通知另一个核心“我需要使用Flash,请释放”,以避免死锁或长时间忙等待。
6. 常见问题排查与调试技巧实录
即使理解了所有寄存器,实际调试中依然会遇到各种问题。下面是我在项目中总结的一些典型故障和排查思路。
6.1 外部中断不触发
这是最常见的问题。请按照以下清单逐项检查:
- GPIO复用是否正确?首先确认用于XINT的GPIO引脚是否已通过
GPyMUX或GPyGMUX寄存器正确配置为外设功能(通常是异步输入)。一个关键细节:F2837xD的XINT输入引脚通常需要配置为“异步”模式,因为中断检测是边沿敏感的,与系统时钟可能不同步。检查GPyQSEL寄存器,确保输入量化器被旁路(设置为异步)。 - XINTxCR.ENABLE位是否置1?这是最容易被遗忘的一步。用CCS的寄存器视图直接查看。
- 触发极性(POLARITY)设置是否正确?用示波器测量实际引脚波形,确认边沿方向与配置一致。注意信号是否有抖动,抖动可能导致多次误触发。
- PIE中断配置是否完整?XINT中断信号需要经过PIE(外设中断扩展)模块路由到CPU。
- 确认PIE向量表中对应XINT的中断服务程序(ISR)地址已正确填写。
- 确认PIEIER(中断使能)和CPU IER(全局中断使能)位已置位。
- 最后,一定要记得在ISR末尾清除PIEACK对应位,否则该组中断将被屏蔽,无法响应下一次中断。
- 信号电气特性是否满足?检查信号电压电平(是否在GPIO容忍范围内)、上升/下降时间是否过慢(可能导致无法识别边沿)。
6.2 同步(SYNC)功能失效,PWM模块不同步
- 检查SYNCSELECT寄存器配置:确认“输出源”(SYNCOUT)和各个模块的“输入源”(如EPWM4SYNCIN)配置正确,路径是通的。例如,你希望EPWM4同步EPWM1,那么EPWM1必须配置为产生SYNCOUT事件(通过
EPwm1Regs.TBCTL.bit.SYNCOSEL),并且SYNCSELECT寄存器中EPWM4SYNCIN必须选择EPWM1SYNCOUT。 - 检查EPWM模块自身的同步配置:
- 主机(Master):
TBCTL.SYNCOSEL应配置为输出同步信号(如TB_SYNC_OUT)。 - 从机(Slave):
TBCTL.SYNCOSEL应配置为TB_SYNC_IN或TB_SYNC_DISABLE(如果它不从外部同步)。最关键的是,TBCTL.PHSEN必须置为TB_ENABLE,才能使能从机的相位加载功能。当从机检测到SYNCIN信号时,会将其时基计数器(TBCTR)加载为TBPHS寄存器的值。若想完全同步,应将TBPHS设为0。
- 主机(Master):
- 确认SYNCSOCLOCK寄存器是否已锁定?如果已锁定,你的后续配置写入是无效的。尝试在初始化序列中,将锁定操作移到所有同步配置完成之后。
- 使用CCS的寄存器实时视图和图形化工具:TI的CCS IDE提供了寄存器实时刷新功能和系统配置视图,可以直观地查看SYNCSELECT等寄存器的值,以及EPWM模块的时基计数器是否在同步点同时复位。
6.3 ADC外部触发(ADCSOCXO)无输出
- 引脚复用:确认ADCSOCAO和ADCSOCBO对应的GPIO引脚已正确复用为外设输出功能。
- 源使能:仔细检查
ADCSOCOUTSELECT寄存器,是否已将正确的PWMxSOCAEN或PWMxSOCBEN位置1。一个引脚只能有一个源被使能输出清晰的信号。 - EPWM SOC事件配置:外部触发信号源于EPWM模块的SOC事件。你必须在对应的EPWM模块中(例如
EPwm1Regs.ETSEL和ETPS寄存器)使能SOCA或SOCB事件,并配置其触发条件(如时基计数器等于零、等于CMPA等)。 - 示波器测量:这是最直接的验证方法。在ADCSOCXO引脚上,你应该能看到一个低电平脉冲(宽度为32个SYSCLK周期)。如果没有,则按上述顺序逆向排查。
6.4 DMA/CLA不被触发
- 触发源编码错误:
CLA1TASKSRCSELx和DMACHSRCSELx寄存器中的8位值是一个编码,必须严格对应技术参考手册“Interrupts and Triggers”章节的触发源映射表。一个常见的错误是直接填写了中断号,而不是触发源编码。 - 触发事件是否真的发生?先用简单的方法验证触发源本身。例如,如果你用EPWM1周期中断触发CLA,可以先在CPU的PIE中断服务程序中设置一个标志位,确认该中断能正常发生。
- DMA/CLA模块本身是否使能?触发源配置只是“敲门”,门本身得开着。确保DMA通道或CLA任务已被正确初始化和使能。
- 锁定寄存器:同样,检查
CLA1TASKSRCSELLOCK和DMACHSRCSELLOCK是否在配置完成前就被意外锁定,导致你的配置写入失败。
6.5 双核Flash访问冲突
如果双核都需要操作Flash(例如运行在Flash中的程序进行擦写),必须严格遵守PUMPREQUEST信号量协议。
- 症状:一个核的Flash操作失败,或系统运行不稳定。
- 排查:
- 在每次Flash操作前后,添加调试语句,打印或通过GPIO输出
PUMP_OWNERSHIP的状态。 - 确保两个核的代码在访问Flash前都调用了
acquire_flash_pump类似的函数,并检查返回值。 - 设计清晰的软件协议。例如,规定只有CPU1负责Flash更新,CPU2只读;或者通过IPC中断进行请求和授权。
- 绝对避免在一个核持有泵的所有权时发生复位另一个核的情况,这可能导致泵被永久锁定。
- 在每次Flash操作前后,添加调试语句,打印或通过GPIO输出