TMS320F28035: 中断服务函数中代码数量过多,导致DSP卡死

Part Number: TMS320F28035
    .def    _Epwm3_Isr;
    .sect   "ramfuncs"
    .global  _Epwm3_Isr
 
   
;***************************************************************
;* FNAME: _Epwm3_Isr                     FR SIZE:  18           *
;*                                                             *
;* FUNCTION ENVIRONMENT                                        *
;*                                                             *
;* FUNCTION PROPERTIES                                         *
;*                            0 Parameter,  6 Auto, 10 SOE     *
;***************************************************************
_Epwm3_Isr:
    ; entry into Isr ,TBCTR==0x00E
    ;automatic context save :
    ;ST0,T,AL,AH,PL,PH,AR0,AR1,ST1,DP,IER,DBGSTAT,return address
    ;context save      
        ASP
        MOVL      *SP++,XAR7
        SPM       0
        MOVL      *SP++,XT
        NOP       *,ARP7        
;----------------------------------------------------------------------
;中断响应
        MOVW    DP,#_PieCtrlRegs + _PIEACK ; offset = 1
        MOV     @_PieCtrlRegs + _PIEACK,#4
        CLRC    PAGE0,OVM,SXM,INTM  
        OR      IER,#0x0004 ;OK
;----------------------------------
然后再下面写了很多行代码,DSP直接卡死了,代码数量减少一点就可以正常运行了,是为什么啊,
有没有大哥知道FR SIZE:  18 这是什么意思,是这个FR SIZE的问题吗
  • 您好

    从你提供的汇编代码片段来看,_Epwm3_Isr 是 TMS320F28035 DSP 的一个中断服务例程(ISR),它位于一个特定的内存段 "ramfuncs" 中,这通常意味着该段被放置在 RAM 中以便快速执行。代码中包含了中断的初始响应和上下文保存的部分。下面是对代码的一些解释和建议:

    代码解释

    1. 中断入口
      • 当进入 _Epwm3_Isr 时,假设 TBCTR(时间基准计数器)的值为 0x00E(这通常与中断的触发条件有关,但在这里不是关键)。
    2. 自动上下文保存
      • 注释提到了自动上下文保存,但实际上在提供的代码片段中,只看到了手动保存部分寄存器的操作。ASP 指令在 TMS320F28x 系列 DSP 中并不直接存在,它可能是指“自动保存寄存器”的概念,但具体的保存操作需要手动完成。
      • 通过 MOVL  SPM 指令,代码手动保存了 XAR7(可能是 AR7 寄存器的扩展版本,具体取决于 DSP 的具体型号和编译器/汇编器的实现)和 XT(T 寄存器的扩展版本)到堆栈中。
    3. 中断响应
      • 使用 MOVW  MOV 指令向 PIEACK 寄存器写入 4,以确认接收到的 PWM3 中断。这是中断服务例程中的常见步骤,用于告诉 PIE(外设中断扩展)模块该中断已被接受并开始处理。
      • 通过 CLRC 指令清除一些状态和控制位(虽然 PAGE0OVMSXM 通常不是与中断直接相关的位,这里可能是个错误或特定于应用的设置)。
      • OR IER,#0x0004 指令可能是为了重新启用某个中断(但通常,在 ISR 内部重新启用中断是不推荐的,除非有特别的理由)。然而,这里将 IER(中断使能寄存器)的第 2 位设置为 1,这通常对应于 CPU 中断(INT2),而不是直接与 PWM3 中断相关。这可能是一个错误,或者该代码片段是从更大的上下文中摘录的,并且 IER 的操作有其特定的用途。

    潜在问题和建议

    1. 上下文保存不完整
      • 通常,中断服务例程需要保存更多的上下文信息,包括但不限于状态寄存器、程序计数器、累加器、其他辅助寄存器等。你的代码只保存了 XAR7  XT,这可能不足以在中断处理期间完全恢复 CPU 的状态。
    2. 中断启用
      • 在 ISR 内部重新启用中断(通过修改 IER)通常不是最佳实践。这可能会导致在 ISR 尚未完成时就发生新的中断,从而导致不可预测的行为或堆栈溢出。如果需要在 ISR 完成后启用中断,请考虑在 ISR 结束时设置一个标志,并在 ISR 之外根据该标志启用中断。
    3. 代码优化
      • 如果 _Epwm3_Isr 中的代码量过多,导致 DSP 卡死,你应该考虑优化代码以减少执行时间或将其分解为更小的部分,并在必要时使用 DMA 或其他硬件加速功能来减轻 CPU 的负担。
    4. 调试和测试
      • 使用调试器逐步执行 ISR,观察寄存器和变量的变化,以确保所有操作都按预期进行。
      • 在 ISR 的开始和结束处添加日志输出,以帮助跟踪执行流程和测量执行时间。

    最后,FR SIZE: 18 的确切含义仍然不明确,但它可能与中断服务例程的某种资源使用量(如堆栈帧大小)或编译器/调试器的内部度量有关。

  • 您好

          1:在 TMS320F28x 系列 DSP中其实是存在ASP这个指令。ASP(Align Stack Pointer):对齐堆栈指针。您可以在TI的《TMS320C28x CPU and Instruction Set Reference Guide》文件中找打它注释写的自动保存上下文,但是我也确实没有看到,不知道怎么保存的。

          2:此中断服务函数写的是EPW3_ISR看似是有EWPM3来触发的,其实是有EPWM4来触发的,所以通过IER重新启用了EWPM4的中断是合理。这点我忘了提到了,没有想到您看的那么仔细,这这使得您困惑了。

        3:代码优化,由于现在不确定为什么卡死了,所以没有什么头绪,

        4:使用的是CCS3.3来编译,搜索了一些资料,但是暂时还是没有搞明白,如何使用CCS3.3来仿真。

    关于FR SIZE我在TI的一些资料上面看到过这种注释,看起来与汇编程序中的代码量有强关联性,所以我很好奇这注释是什么意思。下面是我在TI的资料中看到的代码

    .sect ".text"

    .global _main;

    ****************************************************************

    ;* FNAME: _main FR SIZE: 2 *

    ;* *

    ;* FUNCTION ENVIRONMENT *

    ;* *

    ;* FUNCTION PROPERTIES *

    ;* 0 Parameter, 1 Auto, 0 SOE *

    ;***************************************************************

    :_main:

    ADDB SP,#2

    MOVB AL,#1 ; |12|

    LCR #_funcA ; |12|

    ; call occurs [#_funcA] ; |12|

    MOV *-SP[1],AL ; |12|

    MOVB AL,#1 ; |13|

    LCR #_funcB ; |13|

    ; call occurs [#_funcB] ; |13|

    MOV *-SP[1],AL ; |13|

    SUBB SP,#2

    LRETR

    ; return occurs

    .sect "codeA"

    .global _funcA

    ;***************************************************************

    ;* FNAME: _funcA FR SIZE: 1 *

    ;* *

    ;* FUNCTION ENVIRONMENT *

    ;* *

    ;* FUNCTION PROPERTIES *

    ;* 0 Parameter, 1 Auto, 0 SOE *

    ;***************************************************************

    _funcA:

    ADDB SP,#1

    MOV *-SP[1],AL ; |17|

    MOVZ AR6,*-SP[1] ; |18|

    ADD AR6,#_bufferA ; |18|

    SUBB SP,#1 ; |18|

    MOV AL,*+XAR6[0] ; |18|

    LRETR

    ;return occurs

    .sect ".text"

    .global _funcB;

    ****************************************************************

    ;* FNAME: _funcB FR SIZE: 1 *

    ;* *

    ;* FUNCTION ENVIRONMENT *

    ;* *

    ;* FUNCTION PROPERTIES *

    ;* 0 Parameter, 1 Auto, 0 SOE *

    ;***************************************************************

    _funcB:

    ADDB SP,#1

    MOV *-SP[1],AL ; |22|

    MOVZ AR6,*-SP[1] ; |23|

    ADD AR6,#_bufferB ; |23|

    SUBB SP,#1 ; |23|

    MOV AL,*+XAR6[0] ; |23|

    LRETR

    ;return occurs

  • 您好

    在 TMS320F28x 系列 DSP中其实是存在ASP这个指令。ASP(Align Stack Pointer):对齐堆栈指针。您可以在TI的《TMS320C28x CPU and Instruction Set Reference Guide》文件中找打它注释写的自动保存上下文,但是我也确实没有看到,不知道怎么保存的。

    这个要配合中断等指令和事件来实现

          2:此中断服务函数写的是EPW3_ISR看似是有EWPM3来触发的,其实是有EPWM4来触发的,所以通过IER重新启用了EWPM4的中断是合理。这点我忘了提到了,没有想到您看的那么仔细,这这使得您困惑了。

    因为您的指针给出的代码显示是EPWM3来触发的。希望您查一下避免因为这个让中断陷入死循环。

    代码优化,由于现在不确定为什么卡死了,所以没有什么头绪,

    当DSP(数字信号处理器)在代码量增加到一定程度后出现卡死现象,而减少代码量后又能正常运行,这通常指向几个可能的原因:

    1. 内存限制
      • DSP的内存资源(包括RAM和堆栈空间)可能是有限的。如果代码量过大,可能会导致堆栈溢出、堆内存耗尽或全局变量占用过多的RAM空间。
      • 堆栈溢出尤其常见于深度递归调用或大型局部变量使用不当的情况。
    2. 编译器优化问题
      • 某些编译器在优化大量代码时可能会产生意外的行为或效率问题。虽然这不太常见,但有可能发生。
      • 尝试调整编译器的优化级别或优化选项,看看是否有所改善。
    3. 中断处理
      • 如果代码中包含中断服务例程(ISR),并且ISR的实现不当(如未正确保存和恢复上下文、使用过多的堆栈空间等),则可能会在中断发生时导致卡死。
      • 确保ISR的编写符合DSP的硬件和中断处理机制的要求。
    4. 硬件资源冲突
      • 如果代码使用了大量的硬件资源(如DMA通道、GPIO引脚、定时器等),并且这些资源之间存在冲突或配置不当,可能会导致系统不稳定。
      • 检查并优化硬件资源的分配和使用。
    5. 软件逻辑错误
      • 代码中的逻辑错误(如无限循环、死锁、资源竞争等)可能在代码量较小时被掩盖,但在代码量增加时暴露出来。
      • 使用调试工具逐步执行代码,观察变量和寄存器的变化,以找到逻辑错误的位置。
    6. 代码结构问题
      • 复杂的代码结构(如过深的函数调用层次、大量的全局变量和复杂的指针操作)可能导致编译器生成的代码效率低下或难以调试。
      • 尝试重构代码,使用更清晰的函数划分、局部变量和更简单的数据结构。

    为了解决这个问题,您可以尝试以下步骤:

    • 逐步增加代码量:在减少代码量使DSP能够正常运行的基础上,逐步增加代码量,并在每次增加后都进行测试,以确定导致卡死的确切代码段。
    • 使用调试工具:利用调试工具(如CCS的调试器)来观察DSP的运行状态,包括CPU寄存器、内存、堆栈和中断等。
    • 审查和优化代码:根据调试结果,审查和优化可能导致问题的代码段。。
    • 考虑硬件资源:如果问题可能与硬件资源有关,考虑增加DSP的硬件资源或优化现有资源的使用方式。
    关于FR SIZE我在TI的一些资料上面看到过这种注释,看起来与汇编程序中的代码量有强关联性,所以我很好奇这注释是什么意思。下面是我在TI的资料中看到的代码

    注释中的 FR SIZE 通常指的是函数的框架(Frame)大小。这个大小指的是函数在执行过程中,为了保存局部变量、寄存器状态等而在栈(Stack)上分配的空间大小(以字节为单位)。

    解释 FR SIZE

    • FR SIZE: 1  FR SIZE: 2 这样的注释,表明函数在栈上分配了1个或2个字节的空间用于存储局部变量或临时数据。这个大小是编译器或汇编器根据函数内部的需求自动计算的,但也可以由程序员显式地通过栈操作(如增加或减少SP寄存器)来管理。

    • 在你给出的代码中,_funcA  _funcB 函数都通过 ADDB SP,#1  SUBB SP,#1 指令在函数开始时和结束时分别向栈上分配和释放了1个字节的空间。这通常用于存储函数的返回值或传递参数给子函数。

  • 非常感谢您的解答。我想通过仿真查看寄存器如何变换排查为什么代码量多就会卡死,您知道该怎么用CCS3.3进行仿真吗?

  • 您好

    https://software-dl.ti.com/ccs/esd/documents/users_guide/index.html

    这是官方ccs的用户指导手册,请您参考