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.

LAUNCHXL-F28379D: Dual Core PWM Trip

Part Number: LAUNCHXL-F28379D

Hello,

My goal is to be able to force the output of all of the PWMs to a low state from either core.  For one core, that involves using a GPIO pin connected to the PWM through XBAR Input 1 to the one shot trip zone of the PWMs.  This works well, and it can be found in the trip zone example code.  However, I'm not sure of a way to be able to trigger the PWMs from either core.

The currently unsuccessful method I'm using is to initialize the XBAR and PWM trigger on CPU1.  CPU2 is given control of a GPIO pin.  If CPU2 needs to trip the PWMs, it would directly control the XBAR connected GPIO.  If CPU1 needs to trip the PWMs, it is configured to raise an IPC flag that causes CPU2 to interrupt and directly control the XBAR connected GPIO.

Here's the main() code for CPU1 to initialize the PWMs, XBAR, and trigger:

    EALLOW;

    GPIO_setPadConfig(32, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(32, GPIO_DIR_MODE_OUT);
    GPIO_setMasterCore(32, GPIO_CORE_CPU2);

    InputXbarRegs.INPUT1SELECT = 32;

    EPwm1Regs.TZSEL.bit.OSHT1 = 1;          
    EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO;  
    EPwm2Regs.TZSEL.bit.OSHT1 = 1;          
    EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO;  
    EPwm3Regs.TZSEL.bit.OSHT1 = 1;          
    EPwm3Regs.TZCTL.bit.TZA = TZ_FORCE_LO;  

    EDIS;

    CpuSysRegs.PCLKCR2.bit.EPWM1 = 1;
    CpuSysRegs.PCLKCR2.bit.EPWM2 = 1;
    CpuSysRegs.PCLKCR2.bit.EPWM3 = 1;
    InitEPwmGpio();

    EALLOW;                             
    EPwm1Regs.TZCLR.bit.OST = 1;        
    EPwm1Regs.TZCLR.bit.INT = 1;        
    EPwm2Regs.TZCLR.bit.OST = 1;        
    EPwm2Regs.TZCLR.bit.INT = 1;        
    EPwm3Regs.TZCLR.bit.OST = 1;        
    EPwm3Regs.TZCLR.bit.INT = 1;   
    EDIS;

This code is in an 8kHz timer interrupt on CPU1 used to request a trigger from CPU2 after 4 seconds:

    static int debugCount = 0;
    debugCount++;
    if (debugCount >= 32000)
    {
        HWREG(IPC_BASE + IPC_O_SET) = 1UL << IPC_TRIGGER_FAULT;
    }

The following is in main() on CPU2 to initialize the IPC interrupt:

    EALLOW;
    PieVectTable.IPC0_INT = &FaultTrigger;
    EDIS;    

    // Enable CPU INT1 which is connected to Upper PIE IPC INT0-3:
    IER |= M_INT1;

    // Enable CPU01 to CPU02 INTn in the PIE: Group 11 interrupts
    PieCtrlRegs.PIEIER1.bit.INTx13 = 1;   // CPU1 to CPU2 INT0

Finally, this is the IPC ISR:

__interrupt void FaultTrigger(void)
{
    EALLOW;
    GpioDataRegs.GPBCLEAR.bit.GPIO32 = 1; // Used to trip the trigger
    GpioDataRegs.GPBSET.bit.GPIO32 = 1;
    EDIS;

    // Clear the IPC flag
    HWREG(IPC_BASE + IPC_O_CLR) = 1UL << IPC_TRIGGER_FAULT;

    // Acknowledge IPC INT0 Flag and PIE to receive more interrupts
    IpcRegs.IPCACK.bit.IPC0 = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

Is there a simpler approach to this that allows both cores to directly cause the PWM, which is set up on CPU1, to force all of the outputs low?

Thanks!

  • Hi,

    Will you be able to use 2 different IOs/XBAR inputs controlled by CPU1 and CPU2 separately?
    Both can be configured as sources of trip in all PWMs - that way either CPU can trip all PWMs by controlling the IO owned by corresponding CPU.
    You can also avoid IPC and interrupt latency.
  • Yes, this is a possible option!  However, I'm having difficulty initializing the TZ submodule.  When I set up the TZ, it seems like the OSHT flag gets set, and I cannot seem to clear it.  What could be causing the registers not to clear? 

    Here's my updated initialization:

        EALLOW;
        (*ePWM[index]).TZSEL.bit.OSHT1 = 1;
        (*ePWM[index]).TZCTL.bit.TZA = TZ_FORCE_LO;
        (*ePWM[index]).TZCTL.bit.TZB = TZ_FORCE_LO;
        (*ePWM[index]).TZEINT.bit.OST = 1;
        (*ePWM[index]).TZSEL.bit.OSHT2 = 1;
        (*ePWM[index]).TZCLR.bit.OST = 1;
        (*ePWM[index]).TZOSTCLR.bit.OST1 = 1;     // This should clear the OST1 flag
        (*ePWM[index]).TZOSTCLR.bit.OST2 = 1;     // This should clear the OST2 flag
        (*ePWM[index]).TZCLR.bit.INT = 1;         // This should clear the TZ interrupt

    Immediately after this code is run, the ePWM registers contain the following:

    This is an overview of all of the TZ registers:

  • I've gotten your solution to work! Thank you!  My first issues was that when I passed control of a GPIO to CPU2, the data register for that pin would be cleared, even if I set the pin before passing control to CPU2.  This was fixed by using an IPC flag to let CPU2 know when the GPIO pin needed to be set.  After both GPIO are set, the trip zone submodule could be initialized without tripping.  I also made sure to enable the TZ interrupt after making any configurations.  Also the pin must be low for 3*TBCLK to be sufficient for a trip.

    TL;DR:  Made sure both pins were set before configuring the trip zone module and the the pins went low for long enough to trigger a trip.

    Thanks again!

  • That's great!

    Yes - trip input has to be at least 3*TBCLK wide.
    Also, I agree with your observation on the data register being cleared, even if it was set before passing control to CPU2. 
    One thing I can think of to also write a 1 to GPDAT register from CPU2 before passing the control of the IO.
    This would keep the state of the IO high during switching of CPU ownership.

    You can do this as part of initialization code from CPU2 and avoid IPC.