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.

28035 ePWM Action Qualifier output assert

Hello,

I'm trying to initialize the ePWM7 on a 28035 to output a high signal on EPWM7A.  To do so I'm trying to use the Action Qualifier register "AQCSFRC" to assert the output high continuously.  See the code snippet below for what I'm doing.

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    SysCtrlRegs.PCLKCR1.bit.EPWM7ENCLK = 1;
    EDIS;

    //Time Base Period Register
    EPwm7Regs.TBPRD = 1; // Period = 1201 TBCLK counts
 
    //Time Base Control Register

    //Time Base Phase Register
    EPwm7Regs.TBPHS.half.TBPHS     = 0; // Set Phase register to zero

    //Counter Compare Registers
    
    //Action Qualifier Registers
    //Clear the whole register to disable action based on the compare register
    EPwm7Regs.AQCTLA.bit.CBD = 0; 
    EPwm7Regs.AQCTLA.bit.CBU = 0; 
    EPwm7Regs.AQCTLA.bit.CAD = 0; 
    EPwm7Regs.AQCTLA.bit.CBU = 0; 
    EPwm7Regs.AQCTLA.bit.PRD = 0; 
    EPwm7Regs.AQCTLA.bit.ZRO = 0; 

    //Action Qualifier Software Force Register
    EPwm7Regs.AQSFRC.bit.RLDCSF    = 0x03;//Load immediately
    EPwm7Regs.AQSFRC.bit.ACTSFA    = 0x03;//On one-time software forced event, toggle the output

    //Not using the deadband submodule

    //PWM-Chopper Control Register
    EPwm7Regs.PCCTL.bit.CHPEN = 0; //Disable chopping module

    //Trip zone submodule registers
    EPwm7Regs.TZCTL.bit.DCBEVT2 = 0x03;  //Disable trip action
    EPwm7Regs.TZCTL.bit.DCBEVT1 = 0x03;
    EPwm7Regs.TZCTL.bit.DCAEVT2 = 0x03;
    EPwm7Regs.TZCTL.bit.DCAEVT1 = 0x03;
    EPwm7Regs.TZCTL.bit.TZB     = 0x03;
    EPwm7Regs.TZCTL.bit.TZA     = 0x03;

    Gpio_SetMux(40, 1); /* Set GPIO40 to EPWM7A */
    EPwm7Regs.AQCSFRC.bit.CSFA = 0x02; //Force a continuous high on output A   
    EPwm7Regs.AQCSFRC.bit.CSFB = 0x02; //Force a continuous high on output B
 

Up to this point I've tried following the application note examples, (I.E. Controlling Multiple Buck Converters With Independent Frequencies from spruge9e) with no success.  

I was able to toggle the output high when I had it configured as a GPIO, but for my application I need to use the PWM peripheral. 

Clearly I've missed something, can someone correct me?

Thanks.

  • Hi,

    Jason Riordan said:
    I'm trying to initialize the ePWM7 on a 28035 to output a high signal on EPWM7A.

    The simplest way to achieve this is to configure ePWM in a up count mode and then keep the duty at max ie CMPA value = TBPRD. You'll get logic 1 signal.

    Regards,

    Gautam

  • Gautam,

    I've tried to implement your suggestion to achieve a logic high but to no avail.

    EALLOW;
    SysCtrlRegs.PCLKCR1.bit.EPWM7ENCLK = 1;
    EDIS;
    
    Gpio_SetMux(40, 1); //Macro to set the mode on the I/O to ePWM
    
    EPwm7Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE;
    EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
    
    EPwm7Regs.TBPRD = 1;
    EPwm7Regs.CMPA.half.CMPA = 1;

    I commented out the initialization of the other registers to try to simplify things as you said, but I'm still only ever seeing a low signal.  I've JTAG'd to the device and I can see the registers changing and I can see the peripheral being enabled as ePWM, but I still don't see a change on the output.

    Jay

  • This is still unresolved.  If anyone else has had experiences with this problem, sharing them would be greatly appreciated. 

  • Did you

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
    after init?
    Roger
  • Roger44834 said:

    Did you

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
    after init?
    Roger

    I was not.  However, I did add it at the end of the init routine, but still no change.  

  • Did you init more than shown ore just what you posted?

    What I see:

    • TBPRD = 1, unusual for me, not sure if a bigger value would resolve your problems, try 500
    • TBCTL.bit.HSPCLKDIV and CLKDIV not set but should be ok if 0
    • TZSEL not set to 0
    • CMPCTL not set
    • TBCTR not set to 0
    • DBCTL not set to 0

    If you debug, do you see TBCTR change?

  • I'm only initializing what I'm showing.  

    For this application, some of the features of the PWM are not important. I'm not using the PWM as you would expect.  Because of register availability in the CLA of this device, I'm looking to control the output of the PWM in software rather than output a wave form.  The code snippets I've posted and experimenting up to this point have been outside the CLA to avoid needless complexity while establishing that the methodology works. 

    As I expressed in the OP, I'm looking to drive the output high and low in software.  I.E. 100% duty or 0% duty. Therefore, I'm not overly concerned with the deadband settings or the clock division etc.

    I will verify that I am seeing TBCTR change.

  • Hi Jason,

    Sorry for the delayed response.

    The AQCSFRC register is EALLOW protected. You will need to execute EALLOW instruction in your code before writing to this register. After you are done writing to this register, you can execute EDIS instruction.

    Let me know if this doesn't work.

    Hrishi

  • Jason,

    It looks like this register is not EALLOW protected. My suggestion above will not help. Sorry for the confusion.

    Please enable (Set) TBCLKSYNC before writing to the AQCSFRC register. Also, did you try any other values for the period register other than 1? Try a higher value (say) 100. Because of the way this peripheral is being used, the period register value should not matter.

    Let me know how this goes.

    Hrishi

  • Any updates on this?  I am having the same issue.


    I am trying to use the PWM to profile my CLA code.  I can use the AQCSFRC.CSFA bit to set and clear the PWM output in my main loop (on the c28), but it does not work in my CLA task code.  I have tried all of the above suggestions, but no luck. 


    Any thoughts?  I don't mean to steal the thread, this just seemed very close to my problem. 

    Thanks.

  • I did resolve the issue, so hopefully I can help you out.

    The following is done executed in the CPU as part of init:
    [code]
    void Init(void)
    {
    Gpio_SetMux(44, 0);
    Gpio_SetDirection(44, GPIO_DIRECTION_INPUT);

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    SysCtrlRegs.PCLKCR1.bit.EPWM7ENCLK = 1;
    EDIS;

    /*
    Time Base Period Register
    Period doesn't matter for this application
    */
    EPwm7Regs.TBPRD = 500;

    //Time Base Control Register
    EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
    EPwm7Regs.TBCTL.bit.PHSEN = TB_DISABLE;
    EPwm7Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE;
    EPwm7Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
    EPwm7Regs.TBCTL.bit.FREE_SOFT = 0x03; //Free run mode
    EPwm7Regs.TBCTL.bit.PHSDIR = 0; //Don't care for this application
    EPwm7Regs.TBCTL.bit.CLKDIV = 0; //Don't care for this application
    EPwm7Regs.TBCTL.bit.HSPCLKDIV = 0; //Don't care for this application
    EPwm7Regs.TBCTL.bit.SWFSYNC = 0; //Don't care for this application
    EPwm7Regs.TBCTR = 0;

    //Counter Compare Registers
    EPwm7Regs.CMPCTL.bit.SHDWAMODE = 1;//immediate mode
    EPwm7Regs.CMPCTL.bit.LOADAMODE = 0x00; // load on CTR=Zero

    //Not using the deadband submodule

    //PWM-Chopper Control Register

    //Trip zone submodule registers
    EPwm7Regs.TZCTL.bit.DCBEVT2 = 0x03; //Disable trip action
    EPwm7Regs.TZCTL.bit.DCBEVT1 = 0x03;
    EPwm7Regs.TZCTL.bit.DCAEVT2 = 0x03;
    EPwm7Regs.TZCTL.bit.DCAEVT1 = 0x03;
    EPwm7Regs.TZCTL.bit.TZB = 0x03;
    EPwm7Regs.TZCTL.bit.TZA = 0x03;

    EALLOW;
    EPwm7Regs.TZCLR.bit.OST = 1; //Clear the one-shots
    EPwm7Regs.TZCLR.bit.INT = 1; //clear the interrupt flag
    EPwm7Regs.TZEINT.bit.OST = 1;
    EDIS;

    Gpio_SetMux(40, 1); /* Set GPIO40 to EPWM7A */
    Gpio_SetMux(41, 1); /* Set GPIO41 to EPWM7B */

    //Enable the clock to make the peripheral clock
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;

    //Set to a known value.
    EPwm7Regs.AQCSFRC.bit.CSFA = 0x02; //Force a continuous high on output A
    EPwm7Regs.AQCSFRC.bit.CSFB = 0x02; //Force a continuous high on output B

    return;
    }
    [/code]

    After the ePWM peripheral is setup, I'm init'ing the CLA peripheral. From this routine I fire off a CLA task which clears the CLA-> CPU memory. Note: You can't use memset inside the CLA, so you have to get creative with clearing the memory you care about!

    [code]
    void Init_CLA(void)
    {
    //Clear the control structure in our side of the message RAM
    Flush_Cpu_CLA_Msg_Space();

    //Flush the space we're going to copy the CLA's program into
    memset(&Cla1Prog_Start, 0, (uint32_t)& Cla1FuncsLoadSize);

    //Copy CLA code from CPU memory space to CLA RAM
    memcpy(&Cla1FuncsRunStart, &Cla1FuncsLoadStart, (uint32_t) &Cla1FuncsLoadSize);
    EALLOW;

    //Enable the clock to the cla1 peripheral
    CLA_CLOCK_ENABLE();

    //What offset from the start of CLA runspace can we find the start of each task?
    Cla1Regs.MVECT1 = ((uint16_t) Cla1Task1 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT2 = ((uint16_t) Cla1Task2 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT3 = ((uint16_t) Cla1Task3 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT4 = ((uint16_t) Cla1Task4 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT5 = ((uint16_t) Cla1Task5 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT6 = ((uint16_t) Cla1Task6 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT7 = ((uint16_t) Cla1Task7 - (uint16_t) &Cla1Prog_Start);
    Cla1Regs.MVECT8 = ((uint16_t) Cla1Task8 - (uint16_t) &Cla1Prog_Start);

    //What interrupt sources can trigger tasks?
    Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_ADCINT1;
    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 = CLA_INTERRUPT_ENABLE_MASK;//what interrupts can trigger tasks?

    //Configure the CLA registers
    MAP_PROGE_MEM_CLA();//Map SRAM section L3 to CLA program memory.

    Cla1Regs.MCTL.bit.IACKE = CLA_IACK_ENABLE; //Enable calling CLA tasks from SW

    EDIS;

    Cla1ForceTask2(); //The init routine on the CLA side of the cpu

    return;
    }
    [/code]

    To control the ePWM signals from within the CLA I use macros:

    [code]
    #define ASSERT_SELECT() (EPwm7Regs.AQCSFRC.bit.CSFA = 0x02)
    #define DEASSERT_SELECT() (EPwm7Regs.AQCSFRC.bit.CSFA = 0x01)

    #define ASSERT_ENABLE() (EPwm7Regs.AQCSFRC.bit.CSFB = 0x02)
    #define DEASSERT_ENABLE() (EPwm7Regs.AQCSFRC.bit.CSFB = 0x01)
    [/code]
  • Jason,

    Thanks for your response, but I'm still very confused.  I don't really understand how "flushing" the memory helps (also, I'm not really sure how to do that or what that means... the functions you mentioned are not TI standard ones that I could view). 


    I found that I am even able to successfully change the DAC value of the comparator from the CLA.  Also, I can write ONE change to EPwm1Regs.AQCSFRC.bit.CSFA in the CLA (ie. I can either set or clear it, but not both).  So it seems that the memory link is there for the peripheral registers, but with restrictions. 

    Any thoughts?


    Thanks again.

  • Mike,

    What I posted is part of my initialization, I'm flushing, or clearing memory, to put it into a known state. For me, I clear the bits in memory to 0, so that I know what I'm starting with. This isn't something to help with using the peripherals from the CLA, but good programming practice to start from a known state. There are a few functions calls I posted that I don't provide code for because I thought their intent was clear.

    For example:
    [code]
    Gpio_SetMux(40, 1); /* Set GPIO40 to EPWM7A */
    [/code]

    This function is setting the CPU internally muxed I/O and configuring it to be used for EPWM7A - the 40 comes right from the datasheet for the device and the 1 comes directly from the datasheet as well for I/O muxing. The API I put here is just convenience.

    Because I'm allowing the CLA tasks to be called from software and not just from peripheral interrupts:
    [code]
    Cla1ForceTask2(); //The init routine on the CLA side of the cpu
    [/code]
    Is another convenience function that twiddles the CLA peripheral bits to start executing CLA task2 without cluttering up my code.

    If you read through the documentation for the CLA on the 28x series parts, you can see that you have [u]very[/u] limited peripheral access from the CLA. For example, you can only read the ADC result registers, you cannot touch any of the other ADC registers from the CLA. There is no GPIO access from the CLA, however, if you're clever, you can manipulate the ePWM into behaving similarly to a GPIO.

    The solution to my original post was to reactive the connection between the system clock and the EPWM peripheral.