This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28062:ISR 在下电上电后不会清除中断标志和其他奇怪的东西。

Guru**** 2024750 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/570895/tms320f28062-isr-not-clearing-interrupt-flag-and-other-strange-after-power-cycle

器件型号:TMS320F28062

我有一个使用28062来控制大型电源稳压器的项目。 部分测试会以长达5秒的间隔中断器件的输入电源。

第一期:

实时中断例程将在下电上电后不久停止运行(后台代码仍在运行)。 我似乎通过更改清除 PWM 中断并设置 PIEACK 的行来解决了这一问题。 虽然 ISR 在 RAM 中、但这些行最初在闪存之外运行。

原始代码使用我自己的驱动程序函数、当我移动 ISR 时、我忘记将这些函数移动到 RAM:

PWM_CLEAR_EVENT (PWM_3、EVENT_INT);

Interrupts_PIEACK (PI_Group3);

我用通常的方法替代了这些方法:

EPwm3Regs.ETCLR.ALL = 1;

PieCtrlRegs.PIEACK.ALL = M_INT3;

这是某种管道问题吗?

第二期:  

在我似乎解决了第一个问题之后,立即出现了另一个问题。 所有中断都在运行(我可以通过切换外部引脚来看到这一点)、但一些函数停止工作。 例如、我有一个通过 CAN 获取数据的显示屏。 即使引脚信号告诉我该环路仍在运行、到显示屏的所有数据也会停止。 此函数恰好位于 RAM 中。 我将在明天测试将其移动到闪存中、并在该特定函数中看到仍然存在问题。 现在、这只是一个理论。

我意识到这些是奇怪的问题,但有人看到过这样的问题吗? BOR 电路应该处理掉电问题、但在我看来、在这些功率损耗测试中、一些代码、特别是 RAM 函数、正在损坏。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    大家好、Traver、

    如果 BOR 跳闸、器件将复位。 您能否对 VDDIO、VDD 和 XRSn 信号进行范围控制? 这将告诉您 BOR 是否跳闸。

    此致、
    Adam Dunhoft
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    收发器、

    是否在启用中断前设置闪存等待状态?

    您的 CAN 中断来自 CAN 模块本身、还是使用计时器中断?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    该中断不是由 CAN 驱动、是 ePWM CTR_ZERO 触发的中断。 通过直接在函数中(而不是函数调用)将中断清零、这个问题似乎可以得到解决。

    我在3.3V 上捕获到了一个奇怪的上电事件、这就是为什么我要查看 BOR、但是很多锁定也发生在一个干净、快速、上电启动中。

    主要问题是、在下电上电后、我的器件(稳压器)会随机关闭。 同时、CAN 会冻结。 有时会在没有关机的情况下发生 CAN 冻结。 由于我要移除输入电源、调试器会断开连接、因此很难对其进行故障排除。 当我重新连接时、MCU 复位、一切正常。 如果我在启动 MCU 之前连接并查看存储器、我会看到控制器输出和电压反馈等存储器位置损坏(它们中有一些随机的巨大值)。 这是关断原因、因为稳压器认为它是过压的。 我无法调查 CAN 寄存器、因为当我连接时、寄存器都被复位。 也许我可以通过将一些值保存到 CAN 影子中来进一步查看。

    我认为我发现了这个问题,因为与旧版本的代码相比,我使用计时器2将 DELAY_US()函数更改为我自己的函数。 我注意到在设置计时器 PRD 之前调用函数的情况。 移动 PRD 的设置会使问题消失、但当我仔细观察时、如果我的设置为我的设置、则从未调用 delay 函数。

    现在、我处在一个艰难的位置、移动一行代码会导致失败、但没有合理的理由。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这可能是一个红色的错误、但下面是我为使问题出现并消失所做的工作:
    在 main 中、我在计时器2周期被设置前意外调用 microsecond_delay()函数(使用计时器2)。

    system_init();
    GPIO_init();
    adc_init();

    Timer_Set_Period (CPU_TIMER_2、90UL);

    下面的更改似乎使问题消失:

    system_init();

    GPIO_init();
    Timer_Set_Period (CPU_TIMER_2、90UL);
    adc_init();

    所有相关功能如下。 我的问题是、这为什么起作用? 完全删除两个 microsecond_delay()也有效,因此这似乎与存在或不存在的实际延迟时间无关。 当 PRD 为0时、发出计时器重新加载是否存在问题? 调用此函数为何会导致系统范围内的故障? 较旧版本的代码使用了 TI 提供的 DELAY_US(),并且通过数百次电源故障测试从未出现过此问题。

    ADC 初始化函数:
    void ADC_init (void)

    EALLOW;

    ADC_regs.ADCCTL1.bit.ADCBGPWD = 1U;
    ADC_regs.ADCCTL1.bit.ADCREFPWD = 1U;
    ADC_regs.ADCCTL1.bit.ADCPWDN = 1U;
    ADC_regs.ADCCTL1.bit.ADCENABLE = 1U;
    ADC_regs.ADCCTL1.bit.ADCREFSEL = 0U;

    Microsecond_delay (1000);

    adc_regs.adCCTL2.bit.CLKDIV2EN = 1U;


    Microsecond_delay (1000);

    // ACQPS 位设置采样窗口、以 ADC 时钟为单位。 总转换
    //时间为 ACQPS + 1 + 13。
    adc_regs.adcsOC0CTL.bit.ACQPS= 8U;
    ADC_regs.ADCSOC1CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC2CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC3CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC4CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC5CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC6CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC7CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC8CTL.bit.ACQPS= 8U;
    adc_regs.adcsOC9CTL.bit.ACQPS= 8U;
    。 。 。

    延迟和计时器功能:
    void microsecond_delay (uint32_t microsecond_count)

    Timer_reload (CPU_TIMER_2);

    while (microsecond_count > 0)

    while (timer_check_intflag (CPU_timer_2)== 0U);
    Timer_clear_intflag (CPU_timer_2);

    microsecond_count--;


    返回;


    uint16_t TIMER_CHECK_intflag (uint16_t TIMER_NUMBER)

    uint16_t flag_status;

    switch (timer_number)

    案例 CPU_TIMER_0:

    flag_status = CpuTimer0Regs.tcr.bit.TIF;
    中断;

    案例 CPU_TIMER_1:

    flag_status = CpuTimer1Regs.tcr.bit.TIF;
    中断;

    案例 CPU_TIMER_2:

    flag_status = CpuTimer2Regs.tcr.bit.TIF;
    中断;

    默认值:

    FLAG_STATUS = 0U;
    中断;



    返回 FLAG_STATUS;


    void timer_clear_intflag (uint16_t timer_number)


    switch (timer_number)

    案例 CPU_TIMER_0:

    CpuTimer0Regs.TCR.bit.TIF = 1U;
    中断;

    案例 CPU_TIMER_1:

    CpuTimer1Regs.TCR.bit.TIF = 1U;
    中断;

    案例 CPU_TIMER_2:

    CpuTimer2Regs.TCR.bit.TIF = 1U;
    中断;

    默认值:

    中断;




    void timer_reload (uint16_t timer_number)


    switch (timer_number)

    案例 CPU_TIMER_0:

    CpuTimer0Regs.TCR.bit.TRB = 1U;
    中断;

    案例 CPU_TIMER_1:

    CpuTimer1Regs.TCR.bit.TRB = 1U;
    中断;

    案例 CPU_TIMER_2:

    CpuTimer2Regs.TCR.bit.TRB = 1U;
    中断;

    默认值:

    中断;




    void timer_set_period (uint16_t timer_number、uint32_t period)


    switch (timer_number)

    案例 CPU_TIMER_0:

    CpuTimer0Regs.PRD.All =周期;
    中断;

    案例 CPU_TIMER_1:

    CpuTimer1Regs.PRD.All =周期;
    中断;

    案例 CPU_TIMER_2:

    CpuTimer2Regs.PRD.All =周期;
    中断;

    默认值:

    中断;


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我还在研究这一点、但请注意、F2806x 上的 RAM 在复位时不会自动清除。 如果在程序启动时需要内存中的有效值、则会遇到问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我不希望在加电时设置 RAM。 由于我正在运行的测试是断电、因此调试器显然不会保持连接以调查问题。 电源恢复后、我看到问题出现、我可以重新连接调试器、但 MCU 复位、清除所有寄存器。 由于 RAM 不受复位的影响、我尝试将其用作故障排除工具。

    我的问题至少有一部分是由 RAM 位置导致的、该位置保存稳压器的反馈值已损坏。 它看起来是一个数组索引运行的典型情况、但这些存储器位置附近没有数组、这并不能解释 CAN 冻结。 CAN 更难进行故障排除、因为当我重新连接时、所有寄存器都被复位。

    如果这是指针问题或某种问题、我会期望更多的随机行为、我会希望问题发生得比它发生的频率更频繁。 这是令人不安的,因为我知道,除非我找到根本原因,否则它肯定会再次出现。

    您是否知道任何允许您在不引起处理器复位的情况下进行连接的调试器? 即使未选中复选框以在连接时复位、器件也会与 XDS100和 XDS510同时复位。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它听起来不像看门狗问题、但您可以在该序列期间再次检查看门狗是否被禁用或馈送。 您还可以在设置计时器之前验证计时器中断是否未启用。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    抱歉、存在一些串扰。 我刚刚看到了您最近的消息。

    您可以通过编辑 GEL 文件来防止调试器在连接时复位。 在 CCS 中、转到"Tools"->"GEL Files"。 这将打开一个包含 GEL 文件列表的框架。 右键单击列出的选项、然后选择"打开"。 语法基本上是 C。您需要注释掉 OnTargetConnect()中对 GEL_Reset()的调用。 完成此操作后、保存文件、在 GEL Files 框中右键单击 GEL 文件的名称、然后选择 Reload。 您现在应该能够在不复位 MCU 的情况下进行连接。

    如果需要加载符号或其他代码而不进行重置,请注释掉对 OnPreFileLoaded()中 GEL_Reset()的调用。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您提供所有信息。 在我阅读您的最后一条消息之前、我已经有了一个连续的运气、并且能够在连接调试器的情况下导致故障并解决问题。

    我的问题实际上是指针溢出散列内存。 我有一个串行状态机、用于与系统中另一个 PCB 上的电压传感器进行通信。 串行状态机中的一个状态存在错误、它正在检查数据长度、并应在数据超出范围时返回函数。 大约一年前、我开始修改 MISRA C 合规性的代码。 由于 MISRA 只规定了一个返回;从一个函数中、我修改了原始格式的串行代码并犯了错误。

    这个问题的出现取决于许多因素:
    1) 1)必须连接外部传感器并发送消息。
    2) 2)发送器和接收器必须以特定方式退出同步。
    3) 3)错误的数据长度值必须大于数据的保持阵列。

    这就是为什么它如此罕见的原因。 我想我在加电时看到了这一点、因为串行通信的两端在不同的时间加电。 即使是这样,这种情况仍然很少见。 并非产品的所有版本都具有此外部传感器、因此永远不会出现问题。

    编辑 GEL 文件以防止重置将是一个非常有用的工具、可用于在将来进行故障排除。

    谢谢、

    摊铺机
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    哇、这是一个糟糕的错误! 很高兴你能找到它!