我正在试着在dsPIC30f3011微控制器上运行和调试一个C程序。当我在MPLAB中运行我的代码时,代码总是倾向于停止在这个ISR中,并且我完全没有输出任何变量,我的代码甚至没有执行这似乎是一种“陷阱”程序,我认为是为了捕捉简单的错误(即振荡器故障等),我使用的是MPLABBICD3处于调试模式的MPLABB8.5。值得一提的是,MPLAB显示我同时连接到目标(dsPIC)和ICD3。有人能告诉我为什么会发生这个问题吗?
以下是ISR:

void _ISR __attribute__((no_auto_psv))_AddressError(void)
{

        INTCON1bits.ADDRERR = 0;
        while(1);
}

这是我的代码,先初始化,然后使用PID,然后使用DSP函数,
然后是得到语法/算法的实际DSP头文件在我定义责任循环的时候,也有一些问题。
///////////////////////////////初始化/////////////////////////////////////////////
  #include "dsp.h"    //see bottom of program


    tPID SPR4535_PID;                   // Declare a PID Data Structure named, SPR4535_PID, initialize the PID object
    /* The SPR4535_PID data structure contains a pointer to derived coefficients in X-space and */
    /* pointer to controller state (history) samples in Y-space. So declare variables for the */
    /* derived coefficients and the controller history samples */
    fractional abcCoefficient[3] __attribute__ ((space(xmemory)));          //  ABC Coefficients loaded from X memory
    fractional controlHistory[3] __attribute__ ((space(ymemory)));          //  Control History loaded from Y memory
    /* The abcCoefficients referenced by the SPR4535_PID data structure */
    /* are derived from the gain coefficients, Kp, Ki and Kd */
    /* So, declare Kp, Ki and Kd in an array */
    fractional kCoeffs[] = {0,0,0};
//////////////////////////////////PID variable use///////////////////////////////

void ControlSpeed(void)
{
    LimitSlew();
    PID_CHANGE_SPEED(SpeedCMD);
    if (timer3avg > 0)
        ActualSpeed = SPEEDMULT/timer3avg;
    else
        ActualSpeed = 0;
    max=2*(PTPER+1);
    DutyCycle=Fract2Float(PID_COMPUTE(ActualSpeed))*max;
    // Just make sure the speed that will be written to the PDC1 register is not greater than the PTPER register
    if(DutyCycle>max)
        DutyCycle=max;
    else if (DutyCycle<0)
        DutyCycle=0;
}


//////////////////////////////////PID functions//////////////////////////////////

        void INIT_PID(int DESIRED_SPEED)
    {
        SPR4535_PID.abcCoefficients = &abcCoefficient[0];    //Set up pointer to derived coefficients
        SPR4535_PID.controlHistory = &controlHistory[0];     //Set up pointer to controller history samples

        PIDInit(&SPR4535_PID);                               //Clear the controller history and the controller output

        kCoeffs[0] = KP;                                  // Sets the K[0] coefficient to the KP
        kCoeffs[1] = KI;                                  // Sets the K[1] coefficient to the KI
        kCoeffs[2] = KD;                                  // Sets the K[2] coefficient to the Kd
        PIDCoeffCalc(&kCoeffs[0], &SPR4535_PID);             //Derive the a,b, & c coefficients from the Kp, Ki & Kd

        SPR4535_PID.controlReference = DESIRED_SPEED;        //Set the Reference Input for your controller
    }

    int PID_COMPUTE(int MEASURED_OUTPUT)
    {
        SPR4535_PID.measuredOutput = MEASURED_OUTPUT;             // Records the measured output
        PID(&SPR4535_PID);
        return SPR4535_PID.controlOutput;                                      // Computes the control output
    }

    void PID_CHANGE_SPEED (int NEW_SPEED)
    {
        SPR4535_PID.controlReference = NEW_SPEED;                   // Changes the control reference to change the desired speed
    }

/////////////////////////////////////dsp.h/////////////////////////////////////////////////

    typedef struct {
            fractional* abcCoefficients;    /* Pointer to A, B & C coefficients located in X-space */
                                            /* These coefficients are derived from */
                                            /* the PID gain values - Kp, Ki and Kd */
            fractional* controlHistory;     /* Pointer to 3 delay-line samples located in Y-space */
                                            /* with the first sample being the most recent */
            fractional controlOutput;       /* PID Controller Output  */
            fractional measuredOutput;      /* Measured Output sample */
            fractional controlReference;    /* Reference Input sample */
    } tPID;

    /*...........................................................................*/

    extern void PIDCoeffCalc(               /* Derive A, B and C coefficients using PID gain values-Kp, Ki & Kd*/
            fractional* kCoeffs,            /* pointer to array containing Kp, Ki & Kd in sequence */
            tPID* controller                /* pointer to PID data structure */
    );

    /*...........................................................................*/

    extern void PIDInit (                   /* Clear the PID state variables and output sample*/
            tPID* controller               /* pointer to PID data structure */
    );


    /*...........................................................................*/

    extern fractional* PID (                /* PID Controller Function */
            tPID* controller               /* Pointer to PID controller data structure */
    );

最佳答案

dsPIC陷阱不提供免费的信息,所以我倾向于在开场白前添加一些汇编语言来增强ISRs。(请注意,堆栈错误陷阱有点不正确,因为它在堆栈已经无序时使用RCALL并返回指令。)

/**
 * \file trap.s
 * \brief Used to provide a little more information during development.
 *
 * The trapPreprologue function is called on entry to each of the routines
 * defined in traps.c.  It looks up the stack to find the value of the IP
 * when the trap occurred and stores it in the _errAddress memory location.
 */

.global __errAddress
.global __intCon1

.global _trapPreprologue

.section .bss

__errAddress:   .space 4
__intCon1:      .space 2

.section .text

_trapPreprologue:
; Disable maskable interrupts and save primary regs to shadow regs
    bclr    INTCON2, #15            ;global interrupt disable
    push.s                          ;Switch to shadow registers

; Retrieve the ISR return address from the stack into w0:w1
    sub     w15, #4, w2             ;set W2 to the ISR.PC (SP = ToS-4)
    mov     [--w2], w0              ;get the ISR return address LSW (ToS-6) in w0
    bclr    w0, #0x0                ;mask out SFA bit (w0<0>)
    mov     [--w2], w1              ;get the ISR return address MSW (ToS-8) in w1
    bclr    w1, #0x7                ;mask out IPL<3> bit (w1<7>)
    ze      w1, w1                  ;mask out SR<7:0> bits (w1<15..8>)

; Save it
    mov     #__errAddress, w2       ;Move address of __errAddress into w2
    mov.d   w0, [w2]                ;save the ISR return address to __errAddress

; Copy the content of the INTCON1 SFR into memory
    mov     #__intCon1, w2          ;Move address of __intCon1 into w2
    mov     INTCON1, WREG           ;Read the trap flags into w0 (WREG)
    mov     w0, [w2]                ;save the trap flags to __intCon1

; Return to the 'C' handler
    pop.s                           ;Switch back to primary registers
    return

然后,我将所有陷阱ISR保存在一个trap s.c文件中,该文件使用traps.s中的前序。注意,实际的陷阱可能与微控制器不同-请查看数据表以查看实现了哪些陷阱。
/**
 * \file traps.c
 * \brief Micro-controller exception interrupt vectors.
 */

#include <stdint.h>

#include "traps.h"      // Internal interface to the micro trap handling.

/* Access to immediate call stack.  Implementation in trap.s */

extern volatile unsigned long _errAddress;
extern volatile unsigned int _intCon1;

extern void trapPreprologue(void);

/* Trap information, set by the traps that use them. */

static unsigned int _intCon2;
static unsigned int _intCon3;
static unsigned int _intCon4;

/* Protected functions exposed by traps.h */

void trapsInitialise(void)
{
    _errAddress = 0;
    _intCon1 = 0;
    _intCon2 = 0;
    _intCon3 = 0;
    _intCon4 = 0;
}


/* Trap Handling */
// The trap routines call the _trapPreprologue assembly routine in traps.s
// to obtain the value of the PC when the trap occurred and store it in
// the _errAddress variable.  They reset the interrupt source in the CPU's
// INTCON SFR and invoke the (#defined) vThrow macro to report the fault.

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _OscillatorFail(void)
{
    INTCON1bits.OSCFAIL = 0;        /* Clear the trap flag */
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _StackError(void)
{
    INTCON1bits.STKERR = 0;         /* Clear the trap flag */
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _AddressError(void)
{
    INTCON1bits.ADDRERR = 0;        /* Clear the trap flag */
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _MathError(void)
{
    INTCON1bits.MATHERR = 0;        /* Clear the trap flag */
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _DMACError(void)
{
    INTCON1bits.DMACERR = 0;        /* Clear the trap flag */
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _HardTrapError(void)
{
    _intCon4 = INTCON4;
    INTCON4 = 0;                    // Clear the hard trap register
    _intCon2 = INTCON2;
    INTCON2bits.SWTRAP = 0;         // Make sure the software hard trap bit is clear
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

void __attribute__((interrupt(preprologue("rcall _trapPreprologue")),no_auto_psv)) _SoftTrapError(void)
{
    _intCon3 = INTCON3;
    INTCON3 = 0;                    // Clear the soft trap register
    vThrow(_intCon1, _intCon2, _intCon3, _intCon4, _errAddress);
}

vThrow宏的实现取决于您。但是,它不应该使用堆栈,因为这可能不可用(因此不puts()调试调用!)在开发过程中,合理的做法是使用一个简单的无止境循环,循环中包含一个NOP语句,您可以在其中断点。
(在生产构建中,myvThrow macro将参数记录到RAM的一个保留区域,该区域在启动时不被链接器脚本归零,并重置微控制器。在启动过程中,程序检查保留区域,如果非零,则记录错误事件以进行诊断。)
一旦您得到一个陷阱,检查_errAddress变量的内容将给您ISR的返回地址,该地址紧跟生成中断的指令然后,您可以检查映射文件以找到例程,如果您非常感兴趣,可以检查反汇编以找到特定的指令。在那之后,调试就取决于你了。

关于c - 地址错误ISR,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24633622/

10-11 22:23