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.

F28069M CLA Controls ePWM Issues

1. I have ported my motor control current PI loop from F28069M C28 to CLA, somehow the PWM signals are not changed by CLA writing different values into CMPx registers.

//set compare registers

EPwm1Regs.CMPA.half.CMPA = compValue[0]; // PWM 1A - PhaseA

EPwm2Regs.CMPA.half.CMPA = compValue[1]; // PWM 2A - PhaseB

EPwm3Regs.CMPA.half.CMPA = compValue[2]; // PWM 3A - PhaseC

 

I noticed that there was a posting on this forum about the following setting. I tried both 0 and 1 to the CONFIG bit, there was no effect.

EALLOW;

SysCtrlRegs.EPWMCFG.bit.CONFIG = 1; //ePWM DMA/CLA Configuration Register

EDIS;

2. Another question on CPUtoCLA1 variables issue. I had a variable Bool btn1Closed declared in a C28 file,

#pragma DATA_SECTION(btn1Closed, "CpuToCla1MsgRAM")

volatile Bool btn1Closed; //button 1 status

In CLA1, I used it in a condition checking as below

if ((engageCmd == MTR_DISENGAGE) || (btn1Closed == True))

{

     //shut down motor upon either disengage command or button1 closed event

    DisengageMotor();

}

else

{

     //link to PWM module of DSP

    pwmRatio = GetSvPwm();

    SetPwmCmpRegs(pwmRatio);

}

However, regardless what value of the variable btn1Closed is, the execution logic always jumps to the "else" branch.

I'm stuck at this point, please advise ASAP. Thank you very much!

-Louis

 

  • Are your EPwm AQCTL registers set up to do anything?
    What is Bool defined as? And which compiler version are you using? CLA does not support booleans correctly until 15.9.0 or later.
  • Yes, everything works well in c28, I just ported the current control loop to CLA.

    My CCS version is 6.1.3.00034, I bet the CLA compiler is the latest as well.

    The definition of Bool is basically an enum, 0 for False, 1 for True.

    I tried hard code the value of the variable but still unsuccessful.

    Thanks for your support.

  • I would try adding this before the if statement:

    while (btn1Closed != True);
    if ((engageCmd == MTR_DISENGAGE) || (btn1Closed == True)) {
    // ...

    that way, you know for sure, if it gets past the while loop, then btn1Closed is == True and it should not go to the else part of the if statement.

    I would also try changing the type of btn1Closed to Uint16 and explicitly setting to 0 or 1 and checking if == to 0 or 1.  This would ensure that it's not a typedef problem with the CLA.

  • I took your suggestion to change the type of btn1Closed to Uint16, but it still jumps incorrectly.

    From the screenshot, you can see that the variable btn1Closed was 1 when the CLA task is halted. Supposedly, the execution should branch to line 178, but it went to line 183.

    Any advice on this issue and the PWM issue would be much appreciated!

  • Please step through several lines before the actual value of btn1Closed is updated.  You may want to move your __mdebugstop() to somewhere after the if statement.
    Refer to this document:
    processors.wiki.ti.com/.../Control_Law_Accelerator_(C2000_CLA)_Debug_on_CCS_FAQ

    Specifically, the question "If I halt before an instruction, I have to step the CLA multiple times before I see the result of the instruction. Why is this?"

    It may be that btn1Closed is actually 0, even though it shows as 1 in the watch window, and will not update until you step through a few more lines.

  • I stepped into multiple lines, the value of btn1Closed is 1. In fact, that variable was declared in a C28 file, and placed in CPU-to-CLA message RAM, C28 sets its value, CLA just reads its value.
    Thanks for your help.
    I appreciate support from TI or anyone else. Just want to get it going.
  • Somehow that if statement is evaluating to false, there has to be a logical explanation for this.

    Can you post your CLA configuration code and EPWM configuration code and GPIO configuration code? That way everyone can check to make sure your PWMs are configured correctly (for the issue of PWMs not updating) and the CLA is configured correctly (especially the memory configuration MMEMCFG).
  • My code project worked in C28 architecture, the only changes are porting the current control loop to CLA. The hardware is TI's TMDSHVMTRPFCKIT. 

    Below are the configurations of CLA, ePWM, GPIO.

    //CLA configuration

    void InitCLA1(void)

    {

    EALLOW;

    // Compute all CLA task vectors

    Cla1Regs.MVECT1 = (Uint16)((Uint32)&Cla1Task1 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT2 = (Uint16)((Uint32)&Cla1Task2 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT3 = (Uint16)((Uint32)&Cla1Task3 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT4 = (Uint16)((Uint32)&Cla1Task4 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT5 = (Uint16)((Uint32)&Cla1Task5 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT6 = (Uint16)((Uint32)&Cla1Task6 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT7 = (Uint16)((Uint32)&Cla1Task7 - (Uint32)&Cla1Prog_Start);

    Cla1Regs.MVECT8 = (Uint16)((Uint32)&Cla1Task8 - (Uint32)&Cla1Prog_Start);

    // All tasks are enabled and will be started by SW trigger

    Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT2SEL = CLA_INT2_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT3SEL = CLA_INT3_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT4SEL = CLA_INT4_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT5SEL = CLA_INT5_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT6SEL = CLA_INT6_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT7SEL = CLA_INT7_NONE;

    Cla1Regs.MPISRCSEL1.bit.PERINT8SEL = CLA_INT8_NONE;

    Cla1Regs.MIER.all = (M_INT2 | M_INT1); //enable CLA1 Task 1 and Task 2 only

    // Switch the CLA program space to the CLA and enable software forcing

    Cla1Regs.MMEMCFG.all = CLA_PROG_ENABLE|CLARAM0_ENABLE|CLARAM1_ENABLE|CLARAM2_ENABLE|CLA_RAM1CPUE;

    Cla1Regs.MCTL.bit.IACKE = 1;       //enable IACK feature

    EDIS;

    }

    //ePWM configuration

    #define EPWM1_AQCTLA_INIT 0x0060        //CAU = 10, CAD = 01

    void InitEPwm1(void)

    {

    EPwm1Regs.TBCTL.bit.CTRMODE = TB_FREEZE; // Disable the timer

    EPwm1Regs.TBCTL.all = EPWM1_TBCTL_INIT; // Configure timer control register

    EPwm1Regs.TBCTR = 0x0000; // Clear timer counter

    EPwm1Regs.TBPRD = PWM_HALF_PERIOD; // Set timer period

    EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Set timer phase

    EPwm1Regs.CMPCTL.all = EPWM1_CMPCTL_INIT; // Compare control register

    EPwm1Regs.AQCTLA.all = EPWM1_AQCTLA_INIT; // Action-qualifier control register A

    EPwm1Regs.AQSFRC.all = EPWM1_AQSFRC_INIT; // Action-qualifier s/w force register

    EPwm1Regs.AQCSFRC.all = EPWM1_AQCSFRC_INIT; // Action-qualifier continuous s/w force register

    EPwm1Regs.DBCTL.bit.OUT_MODE = DBA_DBB_EN; // Deadband is fully enabled

    EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary

    EPwm1Regs.PCCTL.bit.CHPEN = CHP_DISABLE; // PWM chopper unit disabled

    // Set up ADC SOC Trigger by EPWM1 period event

    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOCA

    EPwm1Regs.ETSEL.bit.SOCASEL = SOC_TBCTR_ZERO; // Enable CNT_ZERO event for SOCA

    EPwm1Regs.ETPS.bit.SOCAPRD = EPWM_INT_2ND_EVENT;// Generate SOCA on the 2nd event

    EPwm1Regs.ETCLR.bit.SOCA = 1; // Clear SOCA flag

    }

    //GPIO configuration

    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = GPIO0_MUX_EPWM1A; // 0=GPIO, 1=EPWM1A, 2=Resv, 3=Resv

    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = GPIO1_MUX_EPWM1B; // 0=GPIO, 1=EPWM1B, 2=Resv, 3=COMP1OUT

    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = GPIO2_MUX_EPWM2A; // 0=GPIO, 1=EPWM2A, 2=Resv, 3=Resv

    GpioCtrlRegs.GPAMUX1.bit.GPIO3 = GPIO3_MUX_EPWM2B; // 0=GPIO, 1=EPWM2B, 2=SPISOMI-A, 3=COMP2OUT

    GpioCtrlRegs.GPAMUX1.bit.GPIO4 = GPIO4_MUX_EPWM3A; // 0=GPIO, 1=EPWM3A, 2=Resv, 3=Resv

    GpioCtrlRegs.GPAMUX1.bit.GPIO5 = GPIO5_MUX_EPWM3B; // 0=GPIO, 1=EPWM3B, 2=SPISIMO-A, 3=ECAP1

     

    Thank you for your continuing support!

     

  • How about your cmd file? Where is CpuToCla1MsgRAM mapped to? Is CpuToCla1MsgRAM defined in DMA memory?
  • MEMORY
    {
    ...
    PAGE 1:
    CLA1_To_CPU_RAM : origin = 0x001480, length = 0x000080 /* CLA1_to_CPU message RAM */
    CPU_To_CLA1_RAM : origin = 0x001500, length = 0x000080 /* CPU_to_CLA1 message RAM */
    }

    SECTIONS
    {
    ...
    Cla1ToCpuMsgRAM : > CLA1_To_CPU_RAM, PAGE = 1
    CpuToCla1MsgRAM : > CPU_To_CLA1_RAM, PAGE = 1
    }

    I suspected something to do with data type mismatch between C28 and CLA. I removed my data type definitions and added
    #include "F2806x_Cla_typedefs.h"
    then, execution flow got worse. I'm still struggling.
  • In your .cla file, make sure F2806x_Cla_typedefs.h is included before your device or project header file. Your .cla file should be the only one including that CLA typedefs header file.

    For example, I only have

    #include "F2806x_Cla_typedefs.h"        /* F2806x CLA type definitions                                                */
    #include "F2806x_Device.h"              /* F2806x header file peripheral address definitions                          */
    #include "CLAmath.h"                    /* CLA math header file                                                       */
    #include "CPUCLACommon.h"               /* Header file for common CPU/CLA definitions                                 */
    

    in my .cla file, and it doesn't include the project header file

    and all other .c files simply have

    #include "Project.h"                             /* Main include file                                                  */

    where Project.h has

    #include "F2806x_Device.h"              /* F2806x header file peripheral address definitions                          */
    #include "F2806x_DefaultIsr.h"          /* ISR definitions                                                            */
    #include "IQmathLib.h"                  /* IQ math header file                                                        */
    #include "C28x_FPU_FastRTS.h"           /* Fast RTS header file                                                       */
    #include "CPUCLACommon.h"               /* Header file for common CPU/CLA definitions                                 */

  • Fulano, thank you for your support that inspired me to look for where the issues were. I got it working now, the root cause was due to the data type mismatch between C28 and CLA. Some data that were declared of Int16 type in C28 then ported to CLA did not work. After changing them to 32-bit type, my code works.

    Thank you again!