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) }