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.

CCS/TMS320F28379D: ILLEGAL_ISR when integrating CLA, ADC and HRPWM

Part Number: TMS320F28379D

Dear all,

I am running into an ILLEGAL_ISR when trying to integrate the HRPWM, ADC and CLA all together although they seemingly occupy different interrupt slots in the PieVectTable. After a search through the forum, I am suspecting that a register value is overwritten somewhere by a value that points to the ILLEGAL_ISR routine. Could you please have a look at my code below (excerpt from the main{} routine), as I am unable to figure out where the mistake is.

Thanks in advance.
Giel Van den Broeck

 

Tool/software: Code Composer Studio

//
// Initialize System Control for Control and Analog Subsystems
// Enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
    EALLOW; // This is needed to write to EALLOW protected registers
    InitSysCtrl();
    EDIS;

// Disable CPU interrupts
	DINT;

//
// Initialize GPIO
//

    // PWM
    InitEPwmGpio();

    // Setup LED2
    GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
	GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);

//
// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
//

//
// This function is found in the F2837xD_PieCtrl.c file.
//
    InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
    EALLOW;
    IER = 0x0000;
    IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
    InitPieVectTable();
    EDIS;

    //
    // CLA configuration
    // Configure the CLA memory spaces first followed by
    // the CLA task vectors
    //
	CLA_configClaMemory();
	CLA_initCpu1Cla1();

    // Enable interrupts

	EALLOW;
	PieVectTable.ADCA1_INT 		= &adca1_isr; //function for ADCA interrupt 1
	PieVectTable.EPWM1_INT 		= &epwm1_isr; //function for EPWM1 interrupt
	PieVectTable.CLA1_1_INT   	= &cla1Isr1;
	PieVectTable.CLA1_2_INT   	= &cla1Isr2;
	PieVectTable.CLA1_3_INT   	= &cla1Isr3;
	PieVectTable.CLA1_4_INT   	= &cla1Isr4;
	PieVectTable.CLA1_5_INT   	= &cla1Isr5;
	PieVectTable.CLA1_6_INT   	= &cla1Isr6;
	PieVectTable.CLA1_7_INT   	= &cla1Isr7;
	PieVectTable.CLA1_8_INT   	= &cla1Isr8;
	EDIS;

	// Enable global Interrupts and higher priority real-time debug events
	IER |= M_INT1; //Enable group 1 interrupts (ADC interrupts)
	IER |= M_INT3; //Enable group 3 interrupts (ePwm interrupts)
	IER |= M_INT11;//Enable group 11 interrupts (CLA interrupts)
	//EINT;  // Enable Global interrupt INTM
	//ERTM;  // Enable Global realtime interrupt DBGM

	// Enable PIE interrupt
	PieCtrlRegs.PIEIER1.bit.INTx1 = 1; 	// enable ADCA1 interrupt (consult technical reference manual p.94)
	PieCtrlRegs.PIEIER3.bit.INTx1 = 1; 	// enable EPWM1 interrupt
	//PieCtrlRegs.PIEIER11.bit.INTx1 = 1;
	PieCtrlRegs.PIEIER11.all  = 0xFFFF; // enable CLA interrupts

//
// Initialize system variables, enable HRPWM
//
	UpdateFine = 1;
	PeriodFine = 0;
	status = SFO_INCOMPLETE;

//
// Enable global Interrupts and higher priority real-time debug events:
//
EINT;   // Enable Global interrupt INTM
ERTM;   // Enable Global realtime interrupt DBGM

//
// Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor.
// HRMSTEP must be populated with a scale factor value prior to enabling
// high resolution period control.
//
    //while(status == SFO_INCOMPLETE) // Call until complete
    //{
        //status = SFO();
        //if (status == SFO_ERROR)
        //{
            //error();    // SFO function returns 2 if an error occurs & # of MEP
        //}               // steps/coarse step exceeds maximum of 255.
    //}

//
// ADC configuration
//
	ADC_Config();		// Configure the ADC SOC channels
	SetupADCChannels();	// Link the SOC channels to ADCIN channels

//
// ePWM and HRPWM register configuration
//
	HRPWM_Config(PWM_PERIOD);   // ePWMx target
	EALLOW;

// CLA test
	//CLA_runTest();

  • I would like to add following information:

    During debugging, I experienced that the issue disappears when the CLA_configClaMemory function is disabled. However, then we lose the CLA functionality of course.

    void CLA_configClaMemory(void)
    {
    	extern uint32_t Cla1funcsRunStart, Cla1funcsLoadStart, Cla1funcsLoadSize;
    
    	EALLOW;
    
    	#ifdef _FLASH
    		// Copy over code from FLASH to RAM
    		memcpy((uint32_t *)&Cla1funcsRunStart, (uint32_t *)&Cla1funcsLoadStart,
    				(uint32_t)&Cla1funcsLoadSize);
    	#endif //_FLASH
    
    	// Initialize and wait for CLA1ToCPUMsgRAM
    	MemCfgRegs.MSGxINIT.bit.INIT_CLA1TOCPU = 1;
    	while(MemCfgRegs.MSGxINITDONE.bit.INITDONE_CLA1TOCPU != 1){};
    
    	// Initialize and wait for CPUToCLA1MsgRAM
    	MemCfgRegs.MSGxINIT.bit.INIT_CPUTOCLA1 = 1;
    	while(MemCfgRegs.MSGxINITDONE.bit.INITDONE_CPUTOCLA1 != 1){};
    
    	// Select LS5RAM to be the programming space for the CLA
    	// First configure the CLA to be the master for LS5 and then
    	// set the space to be a program block
    	//MemCfgRegs.LSxMSEL.bit.MSEL_LS5 = 1;
    	//MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS5 = 1;
    
    	//
    	// Select LS4 and LS5RAM to be the programming space for the CLA
    	// First configure the CLA to be the master for LS4/LS5 and then
    	// set the space to be a program block
    	//
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS4 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS4 = 1;
    
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS5 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS5 = 1;
    
    	//Next configure LS0RAM and LS1RAM as data spaces for the CLA
    	// First configure the CLA to be the master for LS0(1) and then
        // set the spaces to be code blocks
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS0 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS0 = 0;
    
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS1 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS1 = 0;
    
    	EDIS;
    
    }

  • Hello,

    Have you been able to step through the code to find at what point you end up in the ILLEGAL_ISR()? The ILLEGAL_ISR() usually indicates that an invalid instruction has been decoded, so somewhere along the line you started executing out of memory that doesn't contain actual code.

    Are you running from flash or RAM?

    Whitney
  • Dear Whitney,

    Thank you for your reply.

    I have tried commenting different code blocks to identify when the illegal interrupt service routine is entered and actually it keeps appearing at different lines when commenting different blocks. For instance, at the line status = SFO(); the error appears.

    I am running the code from RAM.

    To identify which line exactly triggers the ILLEGAL_ISR, I have found following code:

    void ILLEGAL_ISR(void) 
    // Illegal operation TRAP
    {
    // Insert ISR Code here
    // Next two lines for debug only to halt the processor here
    asm (" ESTOP0");
    // in order for code to halt also when not in debug mode
    asm (" B $,UNC");
    // place PC here to continue the execution
    asm (" NOP");
    }

  • Can you use the memory browser to look for possible stack overflow or buffer overflow? Those can be common causes of an ITRAP.

    Whitney
  • Hi Whitney,

    Based upon your recommendations (thank you!), I arrived at following conclusions after debugging:

    • The ILLEGAL_ISR occurs at the ADC_ISR which handles the completion of an ADC conversion (see screenshot below).
    • No stack overflow occurs: I have added a watchpoint to _stack_end-2 and monitored the stack in the memory browser.
    • I was unable to find an application note to check for buffer overflow

  • I am really unable to find the errors in my code. Therefore, I upload the whole main.c file.

    5344.main.c
    /*
     * main.c
     *
     *  Created on: 1-feb.-2017
     *      Author: gvandenb
     */
    
    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "SFO_V8.h"
    
    // ****************************************************************************
    // CONTROL LAW ACCELERATOR
    // ****************************************************************************
    
    #include "cla_vminfloat_shared.h"
    
    //*****************************************************************************
    // defines
    //*****************************************************************************
    
    //CLA defines
    #define WAITSTEP 	asm(" RPT #255 || NOP")
    
    //*****************************************************************************
    // globals
    //*****************************************************************************
    //Task 1 (C) Variables
    #ifdef __cplusplus
    	// CLA Input Data
    	#pragma DATA_SECTION("CpuToCla1MsgRAM");
    	#pragma DATA_SECTION("CpuToCla1MsgRAM");
    	float  vector1[] = {1.0,-11.3,6.2,10.8,2.5};
    	int32  length1 = 5;
    	// Length 3 and 4 are #defined in vmaxfloat_shared.h
    
    	// CLA Output Data
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	float32 min1;
    	int32   index1;
    #else
    	// CLA Input Data
    	#pragma DATA_SECTION(vector1,"CpuToCla1MsgRAM");
    	#pragma DATA_SECTION(length1,"CpuToCla1MsgRAM");
    	float  vector1[] = {1.0,-11.3,6.2,10.8,2.5};
    	int32  length1 = 5;
    	// Length 3 and 4 are #defined in vmaxfloat_shared.h
    
    	// CLA Output Data
    	#pragma DATA_SECTION(min1,"Cla1ToCpuMsgRAM");
    	#pragma DATA_SECTION(index1,"Cla1ToCpuMsgRAM");
    	float32 min1;
    	int32   index1;
    #endif
    
    //Task 2 (C) Variables
    #ifdef __cplusplus
    	// CLA Input Data
    	#pragma DATA_SECTION("CpuToCla1MsgRAM");
    	#pragma DATA_SECTION("CpuToCla1MsgRAM");
    	float  vector2[] = {2.0,-11.3,16.2,10.8,2.5,-12.5}
    	int32  length2 = 6;
    
    	// CLA Output Data
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	float32 min2;
    	int32   index2;
    #else
    	// CLA Input Data
    	#pragma DATA_SECTION(vector2,"CpuToCla1MsgRAM");
    	#pragma DATA_SECTION(length2,"CpuToCla1MsgRAM");
    	float  vector2[] = {2.0,-11.3,16.2,10.8,2.5,-12.5};
    	int32  length2 = 6;
    
    	// CLA Output Data
    	#pragma DATA_SECTION(min2,"Cla1ToCpuMsgRAM");
    	#pragma DATA_SECTION(index2,"Cla1ToCpuMsgRAM");
    	float32 min2;
    	int32   index2;
    #endif
    
    //Task 3 (C) Variables
    #ifdef __cplusplus
    	// CLA Input Data
    	#pragma DATA_SECTION("CpuToCla1MsgRAM");
    	float  vector3[] = {0.2,2.3,9.6,9.2,6.2,10.8,2.5}
    	int32 length3 = 7;
    
    	// CLA Output Data
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	int32   index3;
    	float32 min3;
    #else
    	// CLA Input Data
    	#pragma DATA_SECTION(vector3,"CpuToCla1MsgRAM");
    	float  vector3[] = {0.2,2.3,9.6,9.2,6.2,10.8,2.5};
    	int32 length3 = 7;
    
    	// CLA Output Data
    	#pragma DATA_SECTION(min3,"Cla1ToCpuMsgRAM");
    	#pragma DATA_SECTION(index3,"Cla1ToCpuMsgRAM");
    	int32   index3;
    	float32 min3;
    #endif
    
    //Task 4 (C) Variables
    
    //Task 5 (C) Variables
    
    //Task 6 (C) Variables
    
    //Task 7 (C) Variables
    
    //Task 8 (C) Variables
    
    //Common (C) Variables
    #ifdef __cplusplus
    	#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
    	int32   i;
    #else
    	#pragma DATA_SECTION(i,"Cla1ToCpuMsgRAM");
    	int32   i;
    #endif
    uint16_t pass=0;
    uint16_t fail=0;
    
    //*****************************************************************************
    // function prototypes
    //*****************************************************************************
    void CLA_runTest(void);
    void CLA_configClaMemory(void);
    void CLA_initCpu1Cla1(void);
    
    __interrupt void cla1Isr1();
    __interrupt void cla1Isr2();
    __interrupt void cla1Isr3();
    __interrupt void cla1Isr4();
    __interrupt void cla1Isr5();
    __interrupt void cla1Isr6();
    __interrupt void cla1Isr7();
    __interrupt void cla1Isr8();
    
    //
    // Defines
    //
    #define PWM_CH            9        // # of PWM channels (8+1)
    #define STATUS_SUCCESS    1
    #define STATUS_FAIL       0
    #define PWM_PERIOD		  1520	   // 1520 corresponds to 65 kHz
    #define DEADBAND		  20	   // Deadband
    #define CIRCUIT_MODE	  0		   // 0=step-down three-level converter, 1=full-bridge three-level converter, 2=half-bridge three-level converter
    
    #define RESULTS_BUFFER_SIZE 16	   // Buffer size of the ADC conversions (make sure the number is low enough so that all measurements occur within a single switching cycle)
    #define RESULTS_BUFFER_SHIFT 4	   // Buffer size as a power of two for division with low computational effort
    
    //
    // Globals
    //
    Uint16 UpdateFine, PeriodFine, status;
    
    // Measurement result buffers
    int16 AdcaResults[RESULTS_BUFFER_SIZE];
    
    int32 Voltage_p[RESULTS_BUFFER_SIZE];
    int32 Voltage_n[RESULTS_BUFFER_SIZE];
    int32 Voltage_2[RESULTS_BUFFER_SIZE];
    int32 Current_p[RESULTS_BUFFER_SIZE];
    int32 Current_n[RESULTS_BUFFER_SIZE];
    int32 Current_2[RESULTS_BUFFER_SIZE];
    
    Uint16 resultsIndex;
    volatile Uint16 bufferFull;
    Uint16 sampleNo = 1;
    
    // Temporary value to store the duty cycle
    Uint16 duty;
    
    // Measurement results
    volatile int32 voltage_0_m;
    volatile int32 voltage_1_m;
    volatile int32 voltage_2_m;
    volatile int32 current_2_m;
    
    // PI controller states
    int16 pi_current = 0;
    int16 pi_voltage_0 = 0;
    int16 pi_voltage_1 = 0;
    
    // Controller inputs
    
    int MEP_ScaleFactor; // Global variable used by the SFO library
                         // Result can be used for all HRPWM channels
                         // This variable is also copied to HRMSTEP
                         // register by SFO(0) function.
    
    //
    // Array of pointers to EPwm register structures:
    // *ePWM[0] is defined as dummy value not used in the example
    //
    volatile struct EPWM_REGS *ePWM[PWM_CH] =
    {  &EPwm1Regs, &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, &EPwm5Regs,
       &EPwm6Regs, &EPwm7Regs, &EPwm8Regs};
    
    //
    // Function Prototypes
    //
    void Interrupts_Config(void);
    void Interrupts_Init(void);
    void HRPWM_Config(int);
    void ADC_Config(void);
    void SetupADCChannels();
    void CalculateDuty();
    interrupt void adca1_isr(void);
    interrupt void epwm1_isr(void);
    void error(void);
    
    //
    // Main
    //
    void main(void)
    {
    
    //
    // Initialize System Control for Control and Analog Subsystems
    // Enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
    //
        EALLOW; // This is needed to write to EALLOW protected registers
        InitSysCtrl();
        EDIS;
    
    // Disable CPU interrupts
    	DINT;
    
    //
    // Initialize GPIO
    //
    
        // PWM
        InitEPwmGpio();
    
        // Setup LED2
        GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
    	GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
    
    	//
    	// Interrupts
    	//
    	Interrupts_Config();
    	Interrupts_Init();
    
    	//
    	// Initialize system variables, enable HRPWM
    	//
    	UpdateFine = 1;
    	PeriodFine = 0;
    	status = SFO_INCOMPLETE;
    
    	//
    	// Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor.
    	// HRMSTEP must be populated with a scale factor value prior to enabling
    	// high resolution period control.
    	//
        while(status == SFO_INCOMPLETE) // Call until complete
        {
            status = SFO();
            if (status == SFO_ERROR)
            {
                error();    // SFO function returns 2 if an error occurs & # of MEP
            }               // steps/coarse step exceeds maximum of 255.
        }
    
        //
    	// CLA configuration
    	// Configure the CLA memory spaces first followed by
    	// the CLA task vectors
    	//
    	CLA_configClaMemory();
    	CLA_initCpu1Cla1();
    
    	//
    	// ADC configuration
    	//
    	ADC_Config();		// Configure the ADC SOC channels
    	SetupADCChannels();	// Link the SOC channels to ADCIN channels
    
    	// CLA test
    	//CLA_runTest();
    
    	//
    	// ePWM and HRPWM register configuration
    	//
    	HRPWM_Config(PWM_PERIOD);   // ePWMx target
    
    	EINT;  // Enable Global interrupt INTM
    	ERTM;  // Enable Global realtime interrupt DBGM
    
    	//
    	//	Infinite loop
    	//
    
    	Uint16 k = 0; // loop execution count
    
        for(;;)
        {
        	//CLA_runTest();
    
            //
            // Sweep PeriodFine as a Q16 number from 0.2 - 0.999
            //
            //for(PeriodFine = 0x3333; PeriodFine < 0xFFBF; PeriodFine++)
            //{
                //if(UpdateFine)
                //{
                    //
                    // Because auto-conversion is enabled, the desired
                    // fractional period must be written directly to the
                    // TBPRDHR (or TBPRDHRM) register in Q16 format
                    // (lower 8-bits are ignored)
                    //
                    // EPwm1Regs.TBPRDHR = PeriodFine;
                    //
                    // The hardware will automatically scale
                    // the fractional period by the MEP_ScaleFactor
                    // in the HRMSTEP register (which is updated
                    // by the SFO calibration software).
                    //
                    // Hardware conversion:
                    // MEP delay movement = ((TBPRDHR(15:0) >> 8) *  HRMSTEP(7:0) +
                    //                       0x80) >> 8
                    //
                    //for(k=1; k<PWM_CH; k++)
                    //{
                        //(*ePWM[k]).TBPRDHR = PeriodFine; //In Q16 format
                    //}
                //}
                //else
                //{
                    //
                    // No high-resolution movement on TBPRDHR.
                    //
                    //for(k=1; k<PWM_CH; k++)
                    //{
                        //(*ePWM[k]).TBPRDHR = 0;
                    //}
                //}
    
                //
                // Call the scale factor optimizer lib function SFO(0)
                // periodically to track for any change due to temp/voltage.
                // This function generates MEP_ScaleFactor by running the
                // MEP calibration module in the HRPWM logic. This scale
                // factor can be used for all HRPWM channels. HRMSTEP
                // register is automatically updated by the SFO function.
                //
                //status = SFO(); // in background, MEP calibration module
                                // continuously updates MEP_ScaleFactor
    
                //if(status == SFO_ERROR)
                //{
                    //error();   // SFO function returns 2 if an error occurs & # of
                //}              // MEP steps/coarse step exceeds maximum of 255.
    
            //} // end PeriodFine for loop
    
        	k++;
    
        } // end infinite for loop
    }
    
    //
    // Configure interrupts
    //
    void Interrupts_Config()
    {
    	EALLOW;
    
    	//
    	// Initialize PIE control registers to their default state.
    	// The default state is all PIE interrupts disabled and flags
    	// are cleared.
    	//
    
    	//
    	// This function is found in the F2837xD_PieCtrl.c file.
    	//
    	InitPieCtrl();
    
    	//
    	// Disable CPU interrupts and clear all CPU interrupt flags:
    	//
    
    	IER = 0x0000;
    	IFR = 0x0000;
    
    	//
    	// Initialize the PIE vector table with pointers to the shell Interrupt
    	// Service Routines (ISR).
    	// This will populate the entire table, even if the interrupt
    	// is not used in this example.  This is useful for debug purposes.
    	// The shell ISR routines are found in F2837xD_DefaultIsr.c.
    	// This function is found in F2837xD_PieVect.c.
    	//
    	InitPieVectTable();
    
    	// Enable interrupts
    
    	EALLOW;
    	PieVectTable.ADCA1_INT 		= &adca1_isr; //function for ADCA interrupt 1
    	PieVectTable.EPWM1_INT 		= &epwm1_isr; //function for EPWM1 interrupt
    
    	// Enable global Interrupts and higher priority real-time debug events
    	IER |= M_INT1; //Enable group 1 interrupts (ADC interrupts)
    	IER |= M_INT3; //Enable group 3 interrupts (ePwm interrupts)
    	IER |= M_INT11;//Enable group 11 interrupts (CLA interrupts)
    
    	EDIS;
    }
    
    void Interrupts_Init()
    {
    	// Enable PIE interrupt
    	PieCtrlRegs.PIEIER1.bit.INTx1 = 1; 	// enable ADCA1 interrupt (consult technical reference manual p.94)
    	PieCtrlRegs.PIEIER3.bit.INTx1 = 1; 	// enable EPWM1 interrupt
    }
    
    //
    // HRPWM_Config - Configures all ePWM channels and sets up HRPWM
    //                on ePWMxA channels &  ePWMxB channels
    //
    void HRPWM_Config(period)
    {
        Uint16 j;
    
        //
        // ePWM channel register configuration with HRPWM
        // ePWMxA toggle low/high with MEP control on Rising edge
        //
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;   // Disable TBCLK within the EPWM
        EDIS;
    
        for(j=1; j<=PWM_CH; j++)
        {
            (*ePWM[j]).TBCTL.bit.PRDLD = TB_SHADOW;  // set Shadow load
            (*ePWM[j]).TBPRD = period;               // PWM frequency = 1/(2*TBPRD)
            (*ePWM[j]).CMPA.bit.CMPA = period / 2;   // set duty 50% initially
            (*ePWM[j]).CMPA.bit.CMPAHR = (1 << 8);   // initialize HRPWM extension (<< 8 means the shift to the left operator by 8 bits)
            (*ePWM[j]).CMPB.bit.CMPB = period / 2;   // set duty 50% initially
            (*ePWM[j]).CMPB.all |= 1;
            (*ePWM[j]).TBPHS.all = 0;
            (*ePWM[j]).TBCTR = 0;
    
            (*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UP; 	// Select up count mode (ramp up)
                                                            // count mode
            (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN;		// Synchronize ePwm clocks
            (*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
            (*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1;          // TBCLK = SYSCLKOUT
            (*ePWM[j]).TBCTL.bit.FREE_SOFT = 11;
    
            (*ePWM[j]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;  // LOAD CMPA on CTR = 0
            (*ePWM[j]).CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
            (*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;	// A shadow register stores the PWM settings until the next PWM cycle where they will be effectively applied
            (*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    
            (*ePWM[j]).AQCTLA.bit.ZRO = AQ_SET;             // PWM toggle high/low
            (*ePWM[j]).AQCTLA.bit.CAU = AQ_CLEAR;
            (*ePWM[j]).AQCTLB.bit.ZRO = AQ_SET;             // PWM toggle high/low (note: the bit DBCTL.bit.POLSEL further down specifies the complimentarity of the PWM channels signals)
            (*ePWM[j]).AQCTLB.bit.CAU = AQ_CLEAR;
    
            EALLOW;
            (*ePWM[j]).HRCNFG.all = 0x0;
            //(*ePWM[j]).HRCNFG.bit.EDGMODE = HR_BEP;          // MEP control on
                                                             // both edges.
            (*ePWM[j]).HRCNFG.bit.CTLMODE = HR_CMP;          // CMPAHR and TBPRDHR
                                                             // HR control.
            (*ePWM[j]).HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD;  // load on CTR = 0
                                                             // and CTR = TBPRD
            //(*ePWM[j]).HRCNFG.bit.EDGMODEB = HR_BEP;         // MEP control on
                                                             // both edges
            (*ePWM[j]).HRCNFG.bit.CTLMODEB = HR_CMP;         // CMPBHR and TBPRDHR
                                                             // HR control
            (*ePWM[j]).HRCNFG.bit.HRLOADB = HR_CTR_ZERO_PRD; // load on CTR = 0
                                                             // and CTR = TBPRD
            (*ePWM[j]).HRCNFG.bit.AUTOCONV = 1;        // Enable autoconversion for
                                                       // HR period
    
            (*ePWM[j]).HRPCTL.bit.TBPHSHRLOADE = 1;    // Enable TBPHSHR sync
                                                       // (required for updwn
                                                       //  count HR control)
            (*ePWM[j]).HRPCTL.bit.HRPE = 1;            // Turn on high-resolution
                                                       // period control.
    
            CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;      // Enable TBCLK within
                                                       // the EPWM
            (*ePWM[j]).TBCTL.bit.SWFSYNC = 1;          // Synchronize high
                                                       // resolution phase to
                                                       // start HR period
            EDIS;
    
            //
    		// Setup Deadband
    		//
            (*ePWM[j]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
            (*ePWM[j]).DBCTL.bit.POLSEL = DB_ACTV_HIC;	//Active high complimentary
            (*ePWM[j]).DBCTL.bit.IN_MODE = DBA_ALL;
            (*ePWM[j]).DBRED.bit.DBRED = DEADBAND;
            (*ePWM[j]).DBFED.bit.DBFED = DEADBAND;
    
        }
    
        // Enable interrupts on ePwm1 to trigger the ADC
    	EPwm1Regs.ETSEL.bit.SOCASEL	= 1;   		// Select SOC at start of the switching period
    	EPwm1Regs.ETPS.bit.SOCAPRD 	= 3;       	// Generate pulse on 3rd event
    	EPwm1Regs.ETSEL.bit.SOCAEN	= 1;    	// Enable SOC on A group
    
    	//
    	// Interrupt at the start of the switching period
    	//
    	EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;    // Select INT on Zero event
    	EPwm1Regs.ETSEL.bit.INTEN = 1;               // Enable INT
    	EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;          // Generate INT on 1st event
    
    	EALLOW;
    	CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    	EDIS;
    }
    
    //
    // ConfigureADC - Write ADC configurations and power up the ADC for both
    //                ADC A and ADC B
    //
    void ADC_Config(void)
    {
        EALLOW;
    
        //
        //write configurations
        //
        AdcaRegs.ADCCTL2.bit.PRESCALE = 1; //set ADCCLK divider to /2
        AdcbRegs.ADCCTL2.bit.PRESCALE = 1; //set ADCCLK divider to /2
        AdcSetMode(ADC_ADCA, ADC_RESOLUTION_16BIT, ADC_SIGNALMODE_SINGLE);
    	AdcSetMode(ADC_ADCB, ADC_RESOLUTION_16BIT, ADC_SIGNALMODE_SINGLE);
    
        //
        //Set pulse positions to late
        //
        AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
        AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
    
        //
        //power up the ADC
        //
        AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
        AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
    
        //
        //delay for 1ms to allow ADC time to power up
        //
        DELAY_US(1000);
    
        EDIS;
    }
    
    //
    // SetupADCEpwm - Setup ADC EPWM acquisition window
    //
    void SetupADCChannels()
    {
        Uint16 acqps;
    
        //
        //Select the channels to convert and end of conversion flag
        //
        EALLOW;
    
    	// Determine minimum acquisition window (in SYSCLKS) based on resolution
    	if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)
    	{
    		acqps = 1;
    	}
    	else //resolution is 16-bit
    	{
    		acqps = 16;
    	}
    
    	//
        // Channel settings
    	//
    
    	// Current_p
        AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0;  	//SOC0 will convert pin (9)
        AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
        AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
        AdcbRegs.ADCSOC0CTL.bit.CHSEL = 0;  	//SOC0 will convert pin (12)
    	AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	// Current_n
    	AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1;  	//SOC1 will convert pin (11)
    	AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	AdcbRegs.ADCSOC1CTL.bit.CHSEL = 1;  	//SOC1 will convert pin (14)
    	AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	// Current_2
    	AdcaRegs.ADCSOC2CTL.bit.CHSEL = 4;  	//SOC2 will convert pin (21)
    	AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	AdcbRegs.ADCSOC2CTL.bit.CHSEL = 4;  	//SOC2 will convert pin (24)
    	AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	// Voltage_p
    	AdcaRegs.ADCSOC3CTL.bit.CHSEL = 2;  	//SOC3 will convert pin (15)
    	AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	// Voltage_n
    	AdcbRegs.ADCSOC4CTL.bit.CHSEL = 2;  	//SOC4 will convert pin (18)
    	AdcbRegs.ADCSOC4CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcbRegs.ADCSOC4CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
    	// Voltage_2
    	AdcaRegs.ADCSOC5CTL.bit.CHSEL = 3;  	//SOC5 will convert pin A4 (17)
    	AdcaRegs.ADCSOC5CTL.bit.ACQPS = acqps; 	//sample window is 100 SYSCLK cycles
    	AdcaRegs.ADCSOC5CTL.bit.TRIGSEL = 5; 	//trigger on ePWM1 SOCA/C
    
        // Interrupt settings
        AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 1; //end of SOC4 will set INT1 flag
        AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;   //enable INT1 flag
        AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
        EDIS;
    }
    
    //
    // epwm1_isr - EPWM interrupt service request
    //
    interrupt void epwm1_isr(void)
    {
    	//GpioDataRegs.GPACLEAR.bit.GPIO31 = 1;
    	//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    
    	// CLA test
    	//CLA_runTest();
    
    	// Clear INT flag for this timer
    	EPwm1Regs.ETCLR.bit.INT = 1;
    
    	// Acknowledge interrupt
    	PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    
    	// Determine new duty cycle setpoints for next switching cycle
    	//CalculateDuty();
    }
    
    //
    // adca1_isr - Read ADC Buffer in ISR - Process the ADC results
    //
    interrupt void adca1_isr(void)
    {
    	GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    
    	// Buffer results
        Current_p[resultsIndex] = AdcaResultRegs.ADCRESULT0-AdcbResultRegs.ADCRESULT0;
        Current_n[resultsIndex] = AdcaResultRegs.ADCRESULT1-AdcbResultRegs.ADCRESULT1;
        Current_2[resultsIndex] = AdcaResultRegs.ADCRESULT2-AdcbResultRegs.ADCRESULT2;
    
        Voltage_p[resultsIndex] = AdcaResultRegs.ADCRESULT3;
        Voltage_n[resultsIndex] = AdcbResultRegs.ADCRESULT4;
        Voltage_2[resultsIndex] = AdcaResultRegs.ADCRESULT5;
    
        if(RESULTS_BUFFER_SIZE <= resultsIndex)
        {
            resultsIndex = 0;
            bufferFull = 1;
        }
        else
        {
        	resultsIndex++;
    
        }
    
        // Routine to acquire multiple measurements within a single switching cycle
        if (sampleNo < RESULTS_BUFFER_SIZE)
        {
        	// Trigger the ADC to start a new measurement if the buffer is not full
    		//AdcaRegs.ADCSOCFRC1.all = 0xFFFF;
    		//AdcbRegs.ADCSOCFRC1.all = 0xFFFF;
    
    		sampleNo++;
        }
        else
        {
        	// Reset the sampleNo
        	sampleNo=1;
    
        	// Calculate the average of the measurement results and transform to CM/DM variables
    
    		current_2_m = 0;
    		voltage_0_m = 0;
    		voltage_1_m = 0;
    		voltage_2_m = 0;
    
    		//Uint16 i;
    		//for (i=0; i<RESULTS_BUFFER_SIZE; i++)
    		//{
    			//current_2_m += Current_2[i];
    			//voltage_0_m += (Voltage_p[i]+Voltage_n[i]);
    			//voltage_1_m += (Voltage_p[i]-Voltage_n[i]);
    			//voltage_2_m += Voltage_2[i];
    		//}
    
    		//current_2_m = current_2_m >> RESULTS_BUFFER_SHIFT; // RESULTS_BUFFER_SIZE;
    		//voltage_0_m = voltage_0_m >> (RESULTS_BUFFER_SHIFT+1); // RESULTS_BUFFER_SIZE;
    		//voltage_1_m = voltage_1_m >> (RESULTS_BUFFER_SHIFT+1); // RESULTS_BUFFER_SIZE;
    		//voltage_2_m = voltage_2_m >> RESULTS_BUFFER_SHIFT; // RESULTS_BUFFER_SIZE;
        }
    
        AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    
        //GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    }
    
    void CalculateDuty(void)
    {
    	//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    
    	// Variable declarations
    	float q1;
    	float q0;
    	float i_ref;
    
    	//
    	// Control law
    	//
    
    	// Current controller
    	i_ref = 1;
    
    	// Common-mode voltage controller
    	q0 = 0.125;
    
    	// Differential-mode voltage controller
    	q1 = 0.1;
    
    
    	//
    	// Update the duty cycle
    	//
    	if (duty==1)
    	{
    		EPwm1Regs.CMPA.bit.CMPA = PWM_PERIOD * (q0+q1);
    		duty = 0;
    	}
    	else
    	{
    		EPwm1Regs.CMPA.bit.CMPA = PWM_PERIOD * (q0-q1);
    		duty = 1;
    	}
    
    	//
    	// Safety features
    	//
    
    	//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
    }
    
    
    //
    // error - Halt debugger when error occurs
    //
    void error (void)
    {
        ESTOP0;         // Stop here and handle error
    }
    
    // *******************************************************
    // CLA functions
    // *******************************************************
    
    //*****************************************************************************
    // function definitions
    //*****************************************************************************
    void CLA_runTest(void)
    {
    //	float  vector1[] = {1.0,-11.3,6.2,10.8,2.5};
    	length1 = 5;
    	vector1[0] = 1.0;
    	vector1[1] = -11.3;
    	vector1[2] = 6.2;
    	vector1[3] = 10.8;
    	vector1[4] = 2.5;
    
    //	float  vector2[] = {2.0,-11.3,16.2,10.8,2.5,-12.5};
    	length2 = 6;
    	vector2[0] = 2.0;
    	vector2[1] = -11.3;
    	vector2[2] = 16.2;
    	vector2[3] = 10.8;
    	vector2[4] = 2.5;
    	vector2[5] = -12.5;
    
    //	vector3[] = {0.2,2.3,9.6,9.2,6.2,10.8,2.5};
    	length3 = 7;
    	vector3[0] = 0.2;
    	vector3[1] = 2.3;
    	vector3[2] = 9.6;
    	vector3[3] = 9.2;
    	vector3[4] = 6.2;
    	vector3[5] = 10.8;
    	vector3[6] = 2.5;
    
    	Cla1ForceTask1andWait();
    
    	//Cla1ForceTask2andWait();
    
    	//Cla1ForceTask3andWait();
    
    	if(index1 != 1 || min1 != -11.3)
    		fail++;
    	else
    		pass++;
    	if(index2 != 5 || min2 != -12.5)
    		fail++;
    	else
    		pass++;
    	if(index3 != 0 || min3 != 0.2)
    		fail++;
    	else
    		pass++;
    #if 0
    	Cla1ForceTask4andWait();
    
    	Cla1ForceTask5andWait();
    
    	Cla1ForceTask6andWait();
    
    	Cla1ForceTask7andWait();
    
    	Cla1ForceTask8andWait();
    #endif
    }
    
    
    void CLA_configClaMemory()
    {
    	extern uint32_t Cla1funcsRunStart, Cla1funcsLoadStart, Cla1funcsLoadSize;
    
    	EALLOW;
    
    	#ifdef _FLASH
    		// Copy over code from FLASH to RAM
    		memcpy((uint32_t *)&Cla1funcsRunStart, (uint32_t *)&Cla1funcsLoadStart,
    				(uint32_t)&Cla1funcsLoadSize);
    	#endif //_FLASH
    
    	// Initialize and wait for CLA1ToCPUMsgRAM
    	MemCfgRegs.MSGxINIT.bit.INIT_CLA1TOCPU = 1;
    	while(MemCfgRegs.MSGxINITDONE.bit.INITDONE_CLA1TOCPU != 1){};
    
    	// Initialize and wait for CPUToCLA1MsgRAM
    	MemCfgRegs.MSGxINIT.bit.INIT_CPUTOCLA1 = 1;
    	while(MemCfgRegs.MSGxINITDONE.bit.INITDONE_CPUTOCLA1 != 1){};
    
    	// Select LS5RAM to be the programming space for the CLA
    	// First configure the CLA to be the master for LS5 and then
    	// set the space to be a program block
    	//MemCfgRegs.LSxMSEL.bit.MSEL_LS5 = 1;
    	//MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS5 = 1;
    
    	//
    	// Select LS4 and LS5RAM to be the programming space for the CLA
    	// First configure the CLA to be the master for LS4/LS5 and then
    	// set the space to be a program block
    	//
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS4 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS4 = 1;
    
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS5 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS5 = 1;
    
    	//Next configure LS0RAM and LS1RAM as data spaces for the CLA
    	// First configure the CLA to be the master for LS0(1) and then
        // set the spaces to be code blocks
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS0 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS0 = 0;
    
    	MemCfgRegs.LSxMSEL.bit.MSEL_LS1 = 1;
    	MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS1 = 0;
    
    	EDIS;
    
    }
    
    void CLA_initCpu1Cla1()
    {
    
    	EALLOW;
    
    	//  Compute all CLA task vectors
    	// On Type-1 CLAs the MVECT registers accept full 16-bit task addresses as
    	// opposed to offsets used on older Type-0 CLAs
    
    	Cla1Regs.MVECT1 = (uint16_t)(&Cla1Task1);
    	Cla1Regs.MVECT2 = (uint16_t)(&Cla1Task2);
    	Cla1Regs.MVECT3 = (uint16_t)(&Cla1Task3);
    	Cla1Regs.MVECT4 = (uint16_t)(&Cla1Task4);
    	Cla1Regs.MVECT5 = (uint16_t)(&Cla1Task5);
    	Cla1Regs.MVECT6 = (uint16_t)(&Cla1Task6);
    	Cla1Regs.MVECT7 = (uint16_t)(&Cla1Task7);
    	Cla1Regs.MVECT8 = (uint16_t)(&Cla1Task8);
    
    	// Enable the IACK instruction to start a task on CLA in software
    	// for all 8 CLA tasks. Also, globally enable all 8 tasks (or a
    	// subset of tasks) by writing to their respective bits in the
    	// MIER register
        Cla1Regs.MCTL.bit.IACKE = 1;
        Cla1Regs.MIER.all 	= 0x00FF;
    
        // Disable interrupts
        DINT;
    
        // Configure the vectors for the end-of-task interrupt for all
        // 8 tasks
    	PieVectTable.CLA1_1_INT   = &cla1Isr1;
    	PieVectTable.CLA1_2_INT   = &cla1Isr2;
    	PieVectTable.CLA1_3_INT   = &cla1Isr3;
    	PieVectTable.CLA1_4_INT   = &cla1Isr4;
    	PieVectTable.CLA1_5_INT   = &cla1Isr5;
    	PieVectTable.CLA1_6_INT   = &cla1Isr6;
    	PieVectTable.CLA1_7_INT   = &cla1Isr7;
    	PieVectTable.CLA1_8_INT   = &cla1Isr8;
    
    	// Enable CLA interrupts at the group and subgroup levels
    	PieCtrlRegs.PIEIER11.all  = 0xFFFF;
    
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK1 = 0;
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK2 = 0;
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK3 = 0;
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK4 = 0;
    
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK5 = 0;
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK6 = 0;
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK7 = 0;
        //DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK8 = 0;
    
        EDIS;
    }
    
    //*****************************************************************************
    // CLA Interrupt Service Requests
    //*****************************************************************************
    __interrupt void cla1Isr1 ()
    {
    	// Acknowledge the end-of-task interrupt for task 1
    	PieCtrlRegs.PIEACK.all = M_INT11;
    	//asm(" ESTOP0");
    }
    
    __interrupt void cla1Isr2 ()
    {
    	PieCtrlRegs.PIEACK.all = M_INT11;
    }
    
    __interrupt void cla1Isr3 ()
    {
    	PieCtrlRegs.PIEACK.all = M_INT11;
    }
    
    __interrupt void cla1Isr4 ()
    {
    	asm(" ESTOP0");
    }
    
    __interrupt void cla1Isr5 ()
    {
    	asm(" ESTOP0");
    }
    
    __interrupt void cla1Isr6 ()
    {
    	asm(" ESTOP0");
    }
    
    __interrupt void cla1Isr7 ()
    {
    	asm(" ESTOP0");
    }
    
    __interrupt void cla1Isr8 ()
    {
    	// Acknowledge the end-of-task interrupt for task 8
    	PieCtrlRegs.PIEACK.all = M_INT11;
    //	asm(" ESTOP0");
    }
    
    //
    // End of file
    //
    

  • Do you only see the issue when the CLA functionality is enabled?

    I went through your code and the problem isn't jumping out at me. Do you mind sharing your .cmd file and the .map file that is generated for a build that has the issue?

    Whitney

  • Dear Whitney,

    When I disable the lines that configure the CLA memory and the CLA registers, the error disappears.TLC_CONTROL_DELFINO.zip

    Please find both files in attachment. Thanks for your help!

  • I'm a little confused why your map file has a memory region named RAMLS4_LS5, but the linker command file does not. Are you sure those are the correct files?

    Either way, it looks like adca1_isr is being placed in LS4 RAM--which you've said you want to use as CLA program space. The CPU is blocked from accessing memory configured as CLA program memory, so that seems to explain the ILLEGAL_ISR() and why it only pops up when you've configured the memory ownership.

    You need to fix your cmd file so that .text doesn't use any sections that you've assigned to the CLA. Check out the cmd files that are used by our CLA examples if you want an example.

    Whitney
  • Dear Whitney,

    Thank you for pointing that out. I changed the linker cmd file so that the CLA no longer uses the LS4 program space. Maybe I need to reconfigure the linker file in the future to reserve more space for the CLA but up until now, the issue is resolved.

    For others experiencing similar problems, I include the updated linker file.

    // The user must define CLA_C in the project linker settings if using the
    // CLA C compiler
    // Project Properties -> C2000 Linker -> Advanced Options -> Command File
    // Preprocessing -> --define
    #ifdef CLA_C
    // Define a size for the CLA scratchpad area that will be used
    // by the CLA compiler for local symbols and temps
    // Also force references to the special symbols that mark the
    // scratchpad are.
    CLA_SCRATCHPAD_SIZE = 0x100;
    --undef_sym=__cla_scratchpad_end
    --undef_sym=__cla_scratchpad_start
    #endif //CLA_C
    
    MEMORY
    {
    PAGE 0 :
       /* BEGIN is used for the "boot to SARAM" bootloader mode   */
    
       BEGIN           	: origin = 0x000000, length = 0x000002
       RAMM0           	: origin = 0x000122, length = 0x0002DE
       RAMD0           	: origin = 0x00B000, length = 0x000800
       RAMD1            : origin = 0x00B800, length = 0x000800
       RAMLS4      	  	: origin = 0x00A000, length = 0x000800
       RAMLS5           : origin = 0x00A800, length = 0x000800
       //RAMLS4_LS5     	: origin = 0x00A000, length = 0x001000
       RESET           	: origin = 0x3FFFC0, length = 0x000002
    
    PAGE 1 :
    
       BOOT_RSVD        : origin = 0x000002, length = 0x000120     /* Part of M0, BOOT rom will use this for stack */
       RAMM1            : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */
    
       RAMLS0          	: origin = 0x008000, length = 0x000800
       RAMLS1          	: origin = 0x008800, length = 0x000800
       RAMLS2      		: origin = 0x009000, length = 0x000800
       RAMLS3      		: origin = 0x009800, length = 0x000800
    
       RAMGS0           : origin = 0x00C000, length = 0x001000
       RAMGS1           : origin = 0x00D000, length = 0x001000
       RAMGS2           : origin = 0x00E000, length = 0x001000
       RAMGS3           : origin = 0x00F000, length = 0x001000
       RAMGS4           : origin = 0x010000, length = 0x001000
       RAMGS5           : origin = 0x011000, length = 0x001000
       RAMGS6           : origin = 0x012000, length = 0x001000
       RAMGS7           : origin = 0x013000, length = 0x001000
       RAMGS8           : origin = 0x014000, length = 0x001000
       RAMGS9           : origin = 0x015000, length = 0x001000
       RAMGS10          : origin = 0x016000, length = 0x001000
       RAMGS11          : origin = 0x017000, length = 0x001000
       RAMGS12          : origin = 0x018000, length = 0x001000     /* Only Available on F28379D, F28377D, F28375D devices. Remove line on other devices. */
       RAMGS13          : origin = 0x019000, length = 0x001000     /* Only Available on F28379D, F28377D, F28375D devices. Remove line on other devices. */
       RAMGS14          : origin = 0x01A000, length = 0x001000     /* Only Available on F28379D, F28377D, F28375D devices. Remove line on other devices. */
       RAMGS15          : origin = 0x01B000, length = 0x001000     /* Only Available on F28379D, F28377D, F28375D devices. Remove line on other devices. */
    
       CANA_MSG_RAM     : origin = 0x049000, length = 0x000800
       CANB_MSG_RAM     : origin = 0x04B000, length = 0x000800
    
       CLA1_MSGRAMLOW   : origin = 0x001480, length = 0x000080
       CLA1_MSGRAMHIGH  : origin = 0x001500, length = 0x000080
    }
    
    SECTIONS
    {
       codestart        : > BEGIN,     PAGE = 0
       //.text            : >> RAMD0|RAMD1|RAMLS4_LS5,    PAGE = 0
       .text            : >> RAMD0|RAMD1|RAMLS4,    PAGE = 0
       //.text            : >> RAMD0|RAMD1,    PAGE = 0
       .cinit           : > RAMM0,     PAGE = 0
       .pinit           : > RAMM0,     PAGE = 0
       .switch          : > RAMM0,     PAGE = 0
       .reset           : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */
    
       .stack           : > RAMM1,     PAGE = 1
       .ebss            : > RAMLS2,    PAGE = 1
       .econst          : > RAMLS3,    PAGE = 1
       .esysmem         : > RAMLS3,    PAGE = 1
       Filter_RegsFile  : > RAMGS0,	   PAGE = 1
    
        /* CLA specific sections */
       //Cla1Prog         : > RAMLS4_LS5, PAGE=0
       Cla1Prog         : > RAMLS5, PAGE=0
    
       CLADataLS0		: > RAMLS0, PAGE=1
       CLADataLS1		: > RAMLS1, PAGE=1
    
       Cla1ToCpuMsgRAM  : > CLA1_MSGRAMLOW,   PAGE = 1
       CpuToCla1MsgRAM  : > CLA1_MSGRAMHIGH,  PAGE = 1
    
       /* The following section definition are for SDFM examples */
       Filter1_RegsFile : > RAMGS1,	PAGE = 1, fill=0x1111
       Filter2_RegsFile : > RAMGS2,	PAGE = 1, fill=0x2222
       Filter3_RegsFile : > RAMGS3,	PAGE = 1, fill=0x3333
       Filter4_RegsFile : > RAMGS4,	PAGE = 1, fill=0x4444
    
    #ifdef __TI_COMPILER_VERSION__
       #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc : {} > RAMM0,      PAGE = 0
       #else
        ramfuncs    : > RAMM0      PAGE = 0
       #endif
    #endif
    
    #ifdef CLA_C
       /* CLA C compiler sections */
       //
       // Must be allocated to memory the CLA has write access to
       //
       CLAscratch       :
                         { *.obj(CLAscratch)
                         . += CLA_SCRATCHPAD_SIZE;
                         *.obj(CLAscratch_end) } >  RAMLS1,  PAGE = 1
    
       .scratchpad      : > RAMLS1,       PAGE = 1
       .bss_cla		    : > RAMLS1,       PAGE = 1
       .const_cla	    : > RAMLS1,       PAGE = 1
    #endif //CLA_C
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    

  • Great. Thanks for sharing the updated cmd code.

    Whitney