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.

TMS320F28375S: CLA Implementation Problem - Interrupt not called

Part Number: TMS320F28375S

I'm trying to add CLA functionality to a project (as an experiment). The project framework works fine without a CLA task being called but as soon as I try and call one (a simple counter increment) I run into problems.

By adding breakpoints, I can see that I step into the CLA task correctly, my counter (DataonlyinCLA) is incremented and I leave the task correctly but it seems that the interrupt associated with the task isn't called. When I continue to run, the program leaves my if statement, ends up resetting (all my watched variables and registers are wiped) and the processor hangs, stopping at 3fe493:   7625      ESTOP0.

I'd be eternally grateful if anyone could help me in working out what's wrong with my code or even give some pointers on how to find out where I'm going wrong. I think I have my linker file correct as the program runs without calling the CLA task and I can run the CLA task once. My CLA setup routine fits with the linker file in terms of assigning memory so I'm not sure where to look now. I'm also unable to find out what is at the memory location 3fe493 and why I might be ending up there. 

Jon

CCSV7.1.0.00016 

Program runs an interrupt at 4Hz to run some comms and a separate interrupt at 20kHz to read some ADC values and filter them.

Code snippets:

Calling CLA1Task1 (in the program section that runs at 20kHz):

if (current_state == TEST_ST&&ControlISRCount >= 200000)     //Wait until 200000 to confirm the program is running correctly before initiating cla task 1.
{
Cla1ForceTask1();

// As far as I understand it, the CLA should trigger "cla1_task1_isr" here, once Cla1Task1 is finished, but this never happens
}

Task1 Code in my .cla file:

__attribute__((interrupt)) void Cla1Task1( void )
{
     DataonlyinCLA=DataonlyinCLA+1;           // I see this calculation being carried out
}

Linker CMD file, based on 2837xS_RAM_CLA_lnk_cpu1.cmd

MEMORY
{

PAGE 0 :			//All memory blocks listed in page 0 are defined as program space

   /* 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
   RAMLS3      		: origin = 0x009800, length = 0x000800
   RAMLS4      	    : origin = 0x00A000, length = 0x000800
   RAMLS5           : origin = 0x00A800, length = 0x000800
   RESET           	: origin = 0x3FFFC0, length = 0x000002

   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

   FLASHC  			: origin = 0x084000, length = 0x002000  	/* on-chip Flash, reserved for CLA*/

PAGE 1 :			//All memory blocks listed in page 1 are defined as data space

   BOOT_RSVD        : origin = 0x000002, length = 0x000120		/* Part of M0, BOOT rom will use this for stack */
   RAMM1            : origin = 0x000400, length = 0x000400

   RAMLS0          	: origin = 0x008000, length = 0x000800
   RAMLS1          	: origin = 0x008800, length = 0x000800
   RAMLS2      		: origin = 0x009000, length = 0x000800


   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 , F28377S, F28375S devices. Remove line on other devices. */
   RAMGS13          : origin = 0x019000, length = 0x001000     /* Only Available on , F28377S, F28375S devices. Remove line on other devices. */
   RAMGS14          : origin = 0x01A000, length = 0x001000     /* Only Available on , F28377S, F28375S devices. Remove line on other devices. */
   RAMGS15          : origin = 0x01B000, length = 0x001000     /* Only Available on , F28377S, F28375S 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
{
	//Program memory
	// > MEMLOC1|MEMLOC2 means try memory location 1, if it does not fit in there, use memory location 2 instead
	// >> MEMLOC1|MEMLOC2 means split across memory location 1 and memory location 2

	codestart        : > BEGIN,		PAGE = 0
	ramfuncs    		: > RAMM0,		PAGE = 0
	.text            : >> RAMGS0|RAMGS1|RAMGS2|RAMGS3|RAMGS4,    PAGE = 0
	.cinit           : > RAMM0,		PAGE = 0
	.pinit           : > RAMM0,		PAGE = 0
	.switch          : > RAMM0,		PAGE = 0
	.reset           : > RESET,		PAGE = 0, TYPE = DSECT /* not used, */

	//Data memory

	.stack           : > RAMM1,		PAGE = 1
	.ebss            : > RAMLS0,	PAGE = 1
	.econst          : > RAMLS0,	PAGE = 1
	.esysmem         : > RAMLS1,	PAGE = 1
	.sysmem			 : > RAMLS1,	PAGE = 1

	Filter_RegsFile  : > RAMGS5,	   PAGE = 1

	ramfuncs    	 : > RAMM0      PAGE = 0

	/* CLA specific sections */
	// Program memory
	Cla1Prog         : >> RAMLS3|RAMLS4|RAMLS5, PAGE=0

	// Data memory
	CLADataLS0		: > RAMLS0, PAGE=1
	CLADataLS1		: > RAMLS1, PAGE=1

	// Message memory
	Cla1ToCpuMsgRAM  : > CLA1_MSGRAMLOW,   PAGE = 1
	CpuToCla1MsgRAM  : > CLA1_MSGRAMHIGH,  PAGE = 1

	//Not sure what this entry does
	TrigRegsFile		: > RAMM0,	PAGE = 0


   /* CLA C compiler sections */
   //
   // Must be allocated to memory the CLA has write access to
   //

   .scratchpad      : > RAMLS1,       PAGE = 1
   .bss_cla		    : > RAMLS1,       PAGE = 1
   .const_cla	    : > RAMLS1,       PAGE = 1
}

CLA Setup:

void InitCLA(void)
{
    extern uint32_t Cla1ProgRunStart, Cla1ProgLoadStart, Cla1ProgLoadSize;
    extern uint32_t Cla1funcsRunStart, Cla1funcsLoadStart, Cla1funcsLoadSize;
    //  extern uint32_t CLA1mathTablesRunStart, CLA1mathTablesLoadStart, CLA1mathTablesLoadSize;

    EALLOW;

    DevCfgRegs.DC1.bit.CPU1_CLA1 = 1;

    // 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){};

    //Local Shared RAM Master Selector
    MemCfgRegs.LSxMSEL.bit.MSEL_LS0 = 1;         //1 = Shared between CPU and CLA1, 0 = CPU only
    MemCfgRegs.LSxMSEL.bit.MSEL_LS1 = 1;         //1 = Shared between CPU and CLA1, 0 = CPU only
    MemCfgRegs.LSxMSEL.bit.MSEL_LS2 = 1;         //1 = Shared between CPU and CLA1, 0 = CPU only
    MemCfgRegs.LSxMSEL.bit.MSEL_LS3 = 1;         //1 = Shared between CPU and CLA1, 0 = CPU only
    MemCfgRegs.LSxMSEL.bit.MSEL_LS4 = 1;         //1 = Shared between CPU and CLA1, 0 = CPU only
    MemCfgRegs.LSxMSEL.bit.MSEL_LS5 = 1;         //1 = Shared between CPU and CLA1, 0 = CPU only

    //Memory Configuration - CLA Data Memory and CLA Program Memory Select
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS0 = 0;     //1 = CLA Program Memory, 0 = CLA Data Memory
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS1 = 0;     //1 = CLA Program Memory, 0 = CLA Data Memory
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS2 = 0;     //1 = CLA Program Memory, 0 = CLA Data Memory
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS3 = 1;     //1 = CLA Program Memory, 0 = CLA Data Memory
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS4 = 1;     //1 = CLA Program Memory, 0 = CLA Data Memory
    MemCfgRegs.LSxCLAPGM.bit.CLAPGM_LS5 = 1;     //1 = CLA Program Memory, 0 = CLA Data Memory

    //Memory write and fetch protection
    MemCfgRegs.LSxACCPROT0.bit.CPUWRPROT_LS0 = 0;     //0 = CPU writes allowed, 1 = CPU writes blocked
    MemCfgRegs.LSxACCPROT0.bit.FETCHPROT_LS0 = 0;     //0 = CPU fetch allowed, 1 = CPU fetch blocked
    MemCfgRegs.LSxACCPROT0.bit.CPUWRPROT_LS1 = 0;     //0 = CPU writes allowed, 1 = CPU writes blocked
    MemCfgRegs.LSxACCPROT0.bit.FETCHPROT_LS1 = 0;     //0 = CPU fetch allowed, 1 = CPU fetch blocked
    MemCfgRegs.LSxACCPROT0.bit.CPUWRPROT_LS2 = 0;     //0 = CPU writes allowed, 1 = CPU writes blocked
    MemCfgRegs.LSxACCPROT0.bit.FETCHPROT_LS2 = 0;     //0 = CPU fetch allowed, 1 = CPU fetch blocked
    MemCfgRegs.LSxACCPROT0.bit.CPUWRPROT_LS3 = 0;     //0 = CPU writes allowed, 1 = CPU writes blocked
    MemCfgRegs.LSxACCPROT0.bit.FETCHPROT_LS3 = 0;     //0 = CPU fetch allowed, 1 = CPU fetch blocked
    MemCfgRegs.LSxACCPROT1.bit.CPUWRPROT_LS4 = 0;     //0 = CPU writes allowed, 1 = CPU writes blocked
    MemCfgRegs.LSxACCPROT1.bit.FETCHPROT_LS4 = 0;     //0 = CPU fetch allowed, 1 = CPU fetch blocked
    MemCfgRegs.LSxACCPROT1.bit.CPUWRPROT_LS5 = 0;     //0 = CPU writes allowed, 1 = CPU writes blocked
    MemCfgRegs.LSxACCPROT1.bit.FETCHPROT_LS5 = 0;     //0 = CPU fetch allowed, 1 = CPU fetch blocked

    //Assign address vectors for all CLA tasks
    Cla1Regs.MVECT1 = (uint16_t)(&Cla1Task1);               // Calculate and assign address vector for Task1
    Cla1Regs.MVECT2 = (uint16_t)(&Cla1Task2);               // Calculate and assign address vector for Task2
    Cla1Regs.MVECT3 = (uint16_t)(&Cla1Task3);               // Calculate and assign address vector for Task3
    Cla1Regs.MVECT4 = (uint16_t)(&Cla1Task4);               // Calculate and assign address vector for Task4
    Cla1Regs.MVECT5 = (uint16_t)(&Cla1Task5);               // Calculate and assign address vector for Task5
    Cla1Regs.MVECT6 = (uint16_t)(&Cla1Task6);               // Calculate and assign address vector for Task6
    Cla1Regs.MVECT7 = (uint16_t)(&Cla1Task7);               // Calculate and assign address vector for Task7
    Cla1Regs.MVECT8 = (uint16_t)(&Cla1Task8);               // Calculate and assign address vector for Task8

    //--- Select Task interrupt source                     /******** TRIGGER SOURCE FOR EACH TASK (unlisted numbers are reserved) ********/
    DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK1 = 0;    // 0=none       8=ADCBINT3  16=ADCDINT1  32=XINT4     42=EPWM7INT   70=TINT2     78=ECAP4INT   95=SD1INT     114=SPIRXINTC
    DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK2 = 0;    // 1=ADCAINT1   9=ADCBINT4  17=ADCDINT2  33=XINT5     43=EPWM8INT   71=MXEVTA    79=ECAP5INT   96=SD2INT
    DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK3 = 0;    // 2=ADCAINT2  10=ADCBEVT   18=ADCDINT3  36=EPWM1INT  44=EPWM9INT   72=MREVTA    80=ECAP6INT  107=UPP1INT
    DmaClaSrcSelRegs.CLA1TASKSRCSEL1.bit.TASK4 = 0;    // 3=ADCAINT3  11=ADCCINT1  19=ADCDINT4  37=EPWM2INT  45=EPWM10INT  73=MXEVTB    83=EQEP1INT  109=SPITXINTA
    DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK5 = 0;    // 4=ADCAINT4  12=ADCCINT2  20=ADCDEVT   38=EPWM3INT  46=EPWM11INT  74=MREVTB    84=EQEP2INT  110=SPIRXINTA
    DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK6 = 0;    // 5=ADCAEVT   13=ADCCINT3  29=XINT1     39=EPWM4INT  47=EPWM12INT  75=ECAP1INT  85=EQEP3INT  111=SPITXINTB
    DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK7 = 0;    // 6=ADCBINT1  14=ADCCINT4  30=XINT2     40=EPWM5INT  48=TINT0      76=ECAP2INT  87=HRCAP1INT 112=SPIRXINTB
    DmaClaSrcSelRegs.CLA1TASKSRCSEL2.bit.TASK8 = 0;    // 7=ADCBINT2  15=ADCCEVT   31=XINT3     41=EPWM6INT  69=TINT1      77=ECAP3INT  88=HRCAP2INT 113=SPITXINTC

    //--- CLA1TASKSRCSELx register lock control
    DmaClaSrcSelRegs.CLA1TASKSRCSELLOCK.bit.CLA1TASKSRCSEL1 = 0;     // Write a 1 to lock (cannot be cleared once set)
    DmaClaSrcSelRegs.CLA1TASKSRCSELLOCK.bit.CLA1TASKSRCSEL2 = 0;     // Write a 1 to lock (cannot be cleared once set)

    Cla1Regs.MCTL.bit.IACKE = 1;                            // Allow software forced triggering of CLA Tasks (could be in addition to interrupt source set above)

    Cla1Regs.MIER.all                           = 0x00FF;   //Enable interrupts for all 8 tasks

    PieCtrlRegs.PIEIER11.all                    = 0xFFFF;   // Enable CLA interrupt group in the PIE
    IER |= M_INT11;                                         // Allow CLA interrupt group to proceed through to CPU

    PieCtrlRegs.PIEACK.all = 0xFFFF;                        // Acknowledge all PIE bits to start from fresh

    EDIS;

    PieVectTable.CLA1_1_INT        = &cla1_task1_isr;       // Pointer to function for Cla Task1 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_2_INT        = &cla1_task2_isr;       // Pointer to function for Cla Task2 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_3_INT        = &cla1_task3_isr;       // Pointer to function for Cla Task3 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_4_INT        = &cla1_task4_isr;       // Pointer to function for Cla Task4 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_5_INT        = &cla1_task5_isr;       // Pointer to function for Cla Task5 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_6_INT        = &cla1_task6_isr;       // Pointer to function for Cla Task6 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_7_INT        = &cla1_task7_isr;       // Pointer to function for Cla Task7 interrupt (interrupt sent back when task is complete)
    PieVectTable.CLA1_8_INT        = &cla1_task8_isr;       // Pointer to function for Cla Task8 interrupt (interrupt sent back when task is complete)
}

  • Hi Jon,

    I dont have the entirety of your code but is there is a possibility that you disabled all interrupts at the global level (with the DINT macro) but did not reenable it after peripheral setup (EINT)?
  • You are a lifesaver! 

    It wasn't the DINT/EINT statements but by double checking those I noticed that my DIS statement was before I set the PieVectTable.CLA...values. They are EALLOW protected so weren't getting set.

    I shifted the EDIS statement to after the PieVectTable statements and now it runs like a dream (well, a dream in which a highly capable processor counts up 1 number at a time - but it's a start).

    Jon