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: Staring with CLA

Part Number: TMS320F28379D
Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE

Tool/software: Code Composer Studio

Hello

Using the examples provided under Controlsuite-> device support -> F28379D and the technical reference manual I managed to understand how the PWM and ADC work.
Now I would like to include the CLA into my program to calculate the control law.

In the technical reference manual, they say that you should do the following six steps:

1)Copy CLA code into the CLA program RAM
2)Initialize CLA data RAM if necessary
3)Configure the CLA registers
4)Initialize the PIE vector table and registers
5)Enable CLA tasks/interrupts
6)Initialize other peripherals

I tried to retrieve these steps in the examples that are provided but I have a lot of difficulties with this CLA. Is it possible to provide an example where all these steps are shown? Are there some functions that are provided to be readily used for this purpose?

I would like to use the CLA for the PI control loops in a power electronics converter.

Kind regards

Simon

  • There are CLA examples in controlSUITE and C2000Ware software packages. The CLA examples demonstrate this.

    sal
  • Hello Sal

    Sorry for my late reply. I first had to arrange some other things before I could go on with the CLA

    So to continue my question, I tried to look at these examples but I don't really see how it works.

    Below I pasted the code of the cla_vminfloat example for the F28379D.

    Could you indicate me where the first two steps

    1)Copy CLA code into the CLA program RAM
    2)Initialize CLA data RAM if necessary

    take place because I don't see how it happens. (Sorry, but I don't have a programming background)

    Kind regards and thanks for your help

    Simon

    //###########################################################################
    // FILE:   cla_vminfloat_cpu01.c
    // TITLE:  Vector Minimum Example for F2837xD.
    //
    //! \addtogroup cpu01_example_list
    //! <h1>CLA Vector Minimum (cla_vminfloat_cpu01)</h1>
    //!
    //! Task 1 calculates the vector min moving backward through the array. \n
    //! Task 2 calculates the vector min moving forward through the array. \n
    //! Task 3 calculates the vector min using the ternary operator. \n
    //!
    //! \b Memory \b Allocation \n
    //!  - CLA1 to CPU Message RAM
    //!    - min1 - Minimum value in vector 1
    //!    - index1 - Index of the minimum value in vector 1
    //!    - min2 - Minimum value in vector 2
    //!    - index2 - Index of the minimum value in vector 2
    //!    - min3 - Minimum value in vector 3
    //!    - index3 - Index of the minimum value in vector 3
    //!  - CPU to CLA1 Message RAM
    //!    - vector1 - Input vector to task 1
    //!    - vector2 - Input vector to task 2
    //!    - vector3 - Input vector to task 3
    //!    - length1 - Length of vector 1
    //!    - length2 - Length of vector 2
    //!    - length3 - Length of vector 3
    //!
    //! \b Watch \b Variables \n
    //! - vector1 - Input vector to task 1
    //! - vector2 - Input vector to task 2
    //! - vector3 - Input vector to task 3
    //! - min - Minimum value in vector 1
    //! - index1 - Index of the minimum value in vector 1
    //! - min2 - Minimum value in vector 2
    //! - index2 - Index of the minimum value in vector 2
    //! - min3 - Minimum value in vector 3
    //! - index3 - Index of the minimum value in vector 3
    //!
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v190 $
    // $Release Date: Mon Feb  1 16:51:57 CST 2016 $
    // $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    #include "F28x_Project.h"     // Device Headerfile and Examples Include File
    #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();

    //*****************************************************************************
    // Start of main
    //*****************************************************************************
    void main(void)
    {
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xD_SysCtrl.c file.
        InitSysCtrl();

    // Step 2. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
        DINT;

    // Initialize the 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();

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

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

    // Step 5. Run the test
        CLA_runTest();
    }

    //*****************************************************************************
    // 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(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;

        //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(void)
    {
        //  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
        EALLOW;
        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;

        // 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;
        IER |= (M_INT11 );
    }

    //*****************************************************************************
    // ISR
    //*****************************************************************************
    __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

  • Hi Simon,
    The actual CLA program is the vminfloat.cla.

    // Step 3. Configure the CLA memory spaces first followed by
    // the CLA task vectors
    CLA_configClaMemory(); // copies the code from FLASH to CLA RAM
    CLA_initCpu1Cla1();

    There are specific methods the CPU and CLA pass data between themselves.

    The CLA runs tasks.

    Some allocations of CLA data RAM

    //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

    You may try to step though the code with the debugger.
    The trick in doing more advanced stuff is figuring out how to have the CPU do something very useful while the CLA is busy doing calculations in parallel with the CPU IMO

  • Ok I think that I am starting to understand:

    Correct me if I'm wrong but this is how I see it now:

    -The tasks that the CLA needs to perform are written in a separate file - *.cla - So in my case, I will place the code of the PI controller here

    -For the tasks to work, the CLA needs some communication with the main CPU.
    So in the beginning of the regular program, you give the names of the variables that it will use as an input from the CPU and you also give the names of what you expect to get back from the CLA (CLA output data)

    -In the beginning of your program you also declare some CLA waitstep - no idea what the purpose is here?

    -Then you need to define some functions to set up the CLA:
    void CLA_runTest(void);
    void CLA_configClaMemory(void);
    void CLA_initCpu1Cla1(void);
    Can I just copy these lines and use the same in my program as I suppose that this setting up/ initializing will proably be the same in every case?

    -In the vminfloat example they also provide this:
    __interrupt void cla1Isr1();
    which seems to be just some checkpoint to see if the CLA really ran the code:

    __interrupt void cla1Isr1 ()
    {
        // Acknowledge the end-of-task interrupt for task 1
        PieCtrlRegs.PIEACK.all = M_INT11;
    //    asm(" ESTOP0");
    }

    However I don't see when this function is called or used in the program. Is it really necessary?

    Thanks already a lot for your help. I'm getting a much better understanding about this already.

    Simon

  • Hi Simon,
    It really is not my program, it is just sections from what you cut and pasted in your post.

    Wait steps? Do you mean this?
    Cla1ForceTask1andWait();

    This is the way they executed the routine, which is silly in the real world. It tells the CLA to run the task and have the CPU wait until it is done. If that was acceptable, why not have the CPU do the CLA computations.

    I do 't remember the exact sequence for the ISR, but if I had to guess a typical sequence, and ADC conversion trips the execution of the CLA task, then the at the end of the task, the isr executes to clean up, ...
    // Acknowledge the end-of-task interrupt for task 1
    PieCtrlRegs.PIEACK.all = M_INT11;

    You might want to look through the CLA documentation.

    training.ti.com/c2000-cla-c-compiler-4-part-series