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.

TMS320F28377D: ePWM OSHTSYNC clarification

Part Number: TMS320F28377D


Hello all,

I'm working on a scheme in which I want epwm1 to be synchronized to an external pulse via EXTSYNCIN1. The source of EXTSYNCIN1 is actually frequency-locked to SYSCLK, and I know what it's period will be, so I just need a single SYNC event in order to align the timebase of epwm1. From then on things will stay locked via dead-reckoning.

My plan was to set up epwm1 such that it is free running, but EXTSYNCIN1 is initially tied to an unbonded GPIO (via INPUTXBAR5) to prevent SYNCI from occurring. Then when I want to synchronize, I do the following

// clear SYNCI, in case it was set
EPwm1Regs.TBSTS.bit.SYNCI=1; 
// connect EXTSYNCIN1 to the correct GPIO
XBAR_setInputPin(XBAR_INPUT5, GPIO_Sync); 
// wait until SYNCI is detected
while(EPwm1Regs.TBSTS.bit.SYNCI==0); 
// connect EXTSYNCIN1 to unbonded GPIO again, preventing further SYNCI events
XBAR_setInputPin(XBAR_INPUT5, GPIO_DUMMYXBAR); 

But while reading the TRM I noticed the OSHTSYNC and OSHTSYNCMODE bits in TBCTL2. The TBCTL2 table seems to be the only place these bits are mentioned, but they sound like a better way to implement what I want (no need for a loop polling TBSTS.SYNCI).

I could only find a couple other questions on E2E regarding these bits. This thread suggested that "The oneshot sync put is going to send out immediately. IF it is enabled." which isn't what I want. But this doesn't really make sense to me either... how is that different from SWFSYNC in TBCTL?

This other thread seems to suggest that OSHTSYNC does what I want it to. But this thread is regarding the F28002x devices. The TRM for the F28002x has much more description of this function, and there are many other differences, including entire registers that aren't mentioned in the F2837x TRM. Table 3-30 in The C2000 Real-Time Control MCU Peripherals reference guide states that both these devices have type 4 ePWMs, but also states there are some differences between them....

Any help would be appreciated.

Regards,

Mike

  • Hi Mike,

    You are correct that OSHTSYNC would be a better way to implement your sync scheme here. You could set OSHTSYNCMODE to 1 to enable One Shot sync mode. Then, any time OSHTSYNC is set to 1, it would allow a single sync pulse to take effect based on the timing of your external sync source.

    SWFSYNC differs in that a software force sends out the sync pulse immediately when a 1 is written to SWFSYNC. Contrastingly, the OSHTSYNC sync functionality enables a one shot sync pulse driven by another source (rather than immediately taking effect as is the case in SWFSYNC). This means that you could be sending many external sync signals into your PWM module (using EXTSYNCIN1 as is in your case, for example), but the single one shot sync signal will occur only if the OSHTSYNC bit is set to 1 before your external sync pulse occurs. I understand that the first thread you mentioned is a bit misleading in its wording, so hopefully this helps clear that up. The following diagram is also going to be added to the device TRM soon, in case you find it helpful:

    Please let me know if you have further questions on this.

    Regards,

    Allison

  • Hi Allison, thanks for your clarification.

    One more question about your diagram: It appears that one short sync mode for a module will take effect on that module's sync output (EPWMxSYNCO), and not its sync input (EPWMxSYNCI). If that's the case, for ePWM1, it will not prevent multiple EXTSYNCIN1 events from affecting the timebase of ePWM1. But it can make it so that only one of those EXTSYNCIN1 events will propagate further to ePWM2 and so on. Is that correct?

  • Hi Mike,

    Yes, your understanding here is correct. So in your case what you could do- if you are trying to gate SYNCI for your PWM- is adjust so you are using PWM2. PWM1 would be essentially a dummy PWM that gates sync signal propagation to PWM2. This would still save you software overhead of the 'for' loop polling SYNCI (though the polling 'for' loop is still a functional way of gating). Let me know if you need any more clarification here.

    Regards,

    Allison

  • Hi Allison,

    Ok, sounds good. I was already planning on reserving ePWM1 as a "dummy" which would only pass sync events to the other ePWM.

    Thanks!

  • Hi Allison, I think I spoke too soon. Once I set up ePWM1 for one shot sync mode, it will propagate one SYNCO on the next EXTSYNCIN1 event as expected (I'm using GPIO6 to directly observe SYNCO). But after that, even if I set OSHTSYNC again, no further SYNCO will occur. Even resetting the peripheral via SOFTPRES2 does not get it out of this state. Only way I can produce further SYNCO events from ePWM1 is to either disable one shot sync mode (OSHTSYNCMODE=0), or do a device reset.

    Are you sure one shot sync mode is actually functional for the F2837xD?

  • Hi Mike,

    The OSHTSYNC bit automatically clears to ‘0’ after a single sync pulse is allowed through. After it clears, you should be able to write a ‘1’ again to OSHTSYNC to reset/reopen the gate and allow a subsequent one shot sync pulse through (and this cycle can be repeated). This should be functional for the device, so let's try to figure out the issue. When are you 'setting' your OSHTSYNC after it is first used and what count mode are you using? To clarify, are you trying to perform several one shot sync events on ePWM? And is it that ePWM1 recognizes the sync-in signal, but does not propagate the sync-out to the next ePWM? Or does ePWM1 not recognize the external sync-in at all?

    Regards,

    Allison

  • Hi Allison.

    When I observe OSHTSYNC via the debugger, it always reads zero. The TRM also describes it as R-0/W1S. Doesn't look like there's any way to confirm the state of the one-shot latch from the peripheral registers.

    Here's the snip of code which handles this. Prior to this, the ePWMs peripherals are reset and reconfigured, and are free-running. GPIO6 is already set up to show the SYNCO pulse from ePWM1. This routine generates its own EXTSYNCIN1 by connecting two GPIOs together (GPIO31 is extsyncin1, and I drive it with GPIO23):

    // EXTSYNCIN1 is connected to GPIO31 via XBAR_INPUT5
    // GPIO31 is inverted the gpio control register
    // GPIO23 is connected to GPIO31
    // use GPIO23 to generate EXTSYNCIN1 automatically
    void syncToSequenceSync_E2E(uint16_t sync_option) {
        uint32_t sync_timeout=0;    // for timeout
    
        // set EXTSYNCIN1 in idle state (high, because GPIO31 is inverted)
        GpioDataRegs.GPASET.bit.GPIO23=1;
    
        // clear 1ms timer overflow
        CpuTimer0.TCR.bit.TIF=1;
        // EXTSYNCIN1 should already be configured to connect to GPIO31 via XBAR_INPUT5
        // so wait until SYNCI bit in TBSTS is detected
        // first clear SYNCI bit in TBSTS by writing it 1
        EPwm1Regs_master.TBSTS.bit.SYNCI=1;
        // enable one-shot sync mode for master PWM, so it only propagates a single SYNCO to ePWM2 and so on
        EPwm1Regs_master.TBCTL2.bit.OSHTSYNCMODE=1;
        EPwm1Regs_master.TBCTL2.bit.OSHTSYNC=1;
    
        //wait for GPIO31 to be high (input inversion enabled, so look for GPxDAT=0)
        while(sync_timeout<SYNC_TIMEOUT_MAX_MS) {
            if(GpioDataRegs.GPADAT.bit.GPIO31==0) break;
            // increment sync_timout if 1ms timer has lapsed
            if(CpuTimer0.TCR.bit.TIF) {
                // clear CPU timer interrupt flag
                CpuTimer0.TCR.bit.TIF=1;
                sync_timeout++;
            }
        }
        // enable EXTSYNCIN1 via XBAR_INPUT5 to GPIO31
        XBAR_setInputPin(XBAR_INPUT5, 31);
        // wait for SYNCI flag to set, or for timeout
        while(sync_timeout<SYNC_TIMEOUT_MAX_MS) {
            if(EPwm1Regs_master.TBSTS.bit.SYNCI==1) break;
            // increment sync_timout if 1ms timer has lapsed
            if(CpuTimer0.TCR.bit.TIF) {
                // clear CPU timer interrupt flag
                CpuTimer0.TCR.bit.TIF=1;
                sync_timeout++;
                // generate manual sequence_sync edge after timeout
                if(sync_timeout == SEQUENCESYNC_TEST_DELAY_MS) {
                    DBG2_CLR();
                }
            }
        }
        // immediately disable EXTSYNCIN1 so no further syncs occur
        XBAR_setInputPin(XBAR_INPUT5, 100);
        // return
    }

    The first time I run this after a device reset, it works as expected and I see the SYNCO pulse, and I see the timebase reset (by looking at other signals synchronized to epwm1). But on subsequent attempts it seems like EXTSYNCIN1 is being ignored. If I set a breakpoint at line 19 and manually clear OSHTSYNCMODE via the debugger, then EXTSYNCIN1 is detected again.

  • Hi Mike,

    Thanks so much for sharing this information and your configurations. I will be sure to look into the cause of this behavior on Monday and provide an update for you by the end of day. Feel free to send any further updates in the mean time.

    Best,

    Allison

  • Hi Mike,

    I will need some more time to continue looking into this. Please allow until tomorrow for an update.

    Best,

    Allison

  • Hi Mike,

    Thanks for your patience. Yes, the OSHTSYNC will always read a 0 since it auto clears, so the SYNCI bit is the latch that would indicate that an external synchronization event has occurred. Have you tried adding back in the "while(EPwm1Regs.TBSTS.bit.SYNCI==0);" after the comment "//so wait until SYNCI bit in TBSTS is detected" in your code snippet from above? (Just for verification purposes to see if the SYNCI is still being detected). Also, would there a way for you to be able to provide scope shots of the sync input signal and PWM signal to further verify the SYNCIN pulse is functional?

    What is the period/freq is of your external sync signal? Is this staying constant when you are trying to reset/reuse the OSHTSYNC after the first time you sync (as in, are you trying to sync these signals when they are already aligned after the first sync?)? Another thing that could be helpful to try is if you update/change the TBPHS value of the PWM within your program in between the first time you sync and the next time you try to sync.

    Can I ask why you are enabling EXTSYNCIN1 and then disabling it in your function listed above (and both are after you use OSHTCYNC)? The OSHTSYNC mode should gate your sync signal from propagating without you needing to enable/disable your sync signal. Are you reenabling the external sync before calling this function again? Apologies for all the questions- just wanting to get more context here to work through.

    Regards,

    Allison

  • Hi Allison

    The while(EPwm1Regs.TBSTS.bit.SYNCI==0) line actually was a typo when I was copying the code into the message, it should have been waiting for SYNCI==1, not SYNCI==0.

    At that point in the code (before I've connected EXTSYNCIN1 via INPUTXBAR5), TBSTS.bit.SYNCI is always clear.

    Currently the external sync signal is just a single shot pulse generated by GPIO23 (with the macros DBG2_SET() and DBG2_CLR()).

    The code enabling/disabling EXTSYNC1 is probably redundant, especially since I'm manually pulsing EXTSYNCIN1 just once per repetition. I've just kept it around until the issues with OSHTSYNC mode are resolved.

    I took some scope captures of what I'm seeing. The important channels are:

    D2: This is the signal driving EXTSYNCIN1 (GPIO23 driving GPIO31)

    D7: This is SYNCO (GPIO6)

    D6: This is a 50% duty cycle waveform produced by ePWM2, which is synced to ePWM1. It's set up so that rising edges of D6 should happen immediately when the sync occurs (with a few cycles of delay here and there).

    First three images are without setting OSHTSYNCMODE or OSHTSYNC. First it a very zoomed-in look at the moment where EXTSYNCIN1 assert (D2 falling). SYNCO is visible as a short pulse on channel D7. And the ePWM output edge (D6) is immediately after, as expected:

    Here's a more zoomed-out look at the same setup again. From here we can see the synchronization of the phase of D6 to EXTSYNCIN1.

    If I do several more repetitions with infinite persist, it looks like this. I'm triggering on the falling edge of D2 (which causes EXTSYNCIN1), and everything after that point is very well synchronized, even though the prior phase was all over the place.

    Next I uncommented the lines setting OSHTSYNCMODE and OSHTSYNC, then reloaded the code. The very first time I try the experiment, it seems to work, exactly the same as before:

    But on subsequent tries, I EXTSYNCIN1 seems to be ignored. The SYNCO pulse does not appear, and the phase of the ePWM output is not affected:

    If I do multiple repetitions with infinite persist, it's clear that nothing is synchronized:

    Again I want to reiterate that in between each repetition of my experiment, I'm actually resetting the ePWM peripherals, and reconfiguring them from scratch. But even so, when OSHTSYNCMODE is used, something about it is apparently persisting even through the peripheral reset.

  • Thanks so much for the info and scope shots, Mike, I see the issue you're having. When you say that you are "resetting the ePWM peripherals and reconfiguring them", what exactly is occurring when you do this? Are you completely reloading the program or doing a CPU reset? I'm trying to recreate the issue myself as well, but would you also be able to send me your code and configurations so that I am able to help debug it with your setup?

    Regards,

    Allison

  • Hi Allison,

    By resetting the peripherals I mean just the peripheral via SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_EPWM1), which uses the SOFTPRES2 register bits. I'm not resetting the CPU or reloading code (except when I mentioned changing code to use the OSHTSYNCMODE).

    After getting into that state with the sixth figure above (where OSHTSYNCMODE is set and one EXTSYNCIN1 has already occurred), no further SYNCI or SYNCO seem to occur until I either clear OSHTSYNCMODE via the debugger, or do a warm or cold reset of the MCU.

    I'm testing this on a custom board, and the code that handles the epwm initialization is a relatively small piece of a very long initialization routine, so I can't easily reduce it to a minimal test case. Here is a more complete chunk of code which resets ePWM1, configures it, starts it running, then attempts to generate EXTSYNCIN1 by toggling GPIO23. This doesn't include any GPIO or sysctl configuration though.

    #define EPwm1Regs_master EPwm1Regs
    // reset and reconfigure ePWM1
    void my_EPwm1_init(void) {
        // Reset ePWM1 peripheral
        SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_EPWM1);
        
        // Initialization of ePWM1
    
        // Change clock divider to /1
        // (PWM clock will be 100MHz)
        EPwm1Regs_master.TBCTL.bit.HSPCLKDIV = 0;
        // enable PHSEN so that timebase can be synchronized
        EPwm1Regs_master.TBCTL.bit.PHSEN = 1;
    
        // Disable TBCLKSYNC
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        EPwm1Regs_master.AQSFRC.bit.RLDCSF=3;                     //immediate reload
        EPwm1Regs_master.AQCSFRC.bit.CSFB=AQ_NO_ACTION;           //why do I set these to no action here??
        EPwm1Regs_master.AQCSFRC.bit.CSFA=AQ_NO_ACTION;
    
        //Write to TBPRD and TBPHS registers.
        EPwm1Regs_master.TBCTL.bit.PRDLD = TB_IMMEDIATE;          // set to immediate
        EPwm1Regs_master.TBPRD = 999;                      // write immediate TBPRD
        EPwm1Regs_master.TBCTL.bit.PRDLD = TB_SHADOW;             // set Shadow load
        EPwm1Regs_master.TBPRD = 999;                      // write shadow TBPRD
        // I'm writing TBPRD twice because of this: https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/573404
    
        // set TBPHS and PHSDIR
        EPwm1Regs_master.TBPHS.bit.TBPHS = 0;
        EPwm1Regs_master.TBCTL.bit.PHSDIR = 0;
    
        //Configure modes, clock dividers and action qualifier
        EPwm1Regs_master.TBCTR = 0;
        EPwm1Regs_master.TBSTS.bit.CTRDIR = 1;                        //start counting up
        EPwm1Regs_master.TBCTL.bit.CTRMODE = TB_FREEZE;               // freeze for now
        EPwm1Regs_master.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;           // pass SYNCI to next ePWM module
        EPwm1Regs_master.TBCTL.bit.HSPCLKDIV = TB_DIV1;
        EPwm1Regs_master.TBCTL.bit.CLKDIV = TB_DIV1;             // TBCLK = SYSCLKOUT
        EPwm1Regs_master.TBCTL.bit.FREE_SOFT = 00;
    
        EPwm1Regs_master.AQCTLA.bit.CAU = AQ_CLEAR;
        EPwm1Regs_master.AQCTLA.bit.ZRO = AQ_CLEAR;
        EPwm1Regs_master.AQCTLB.bit.CBU = AQ_CLEAR;
        EPwm1Regs_master.AQCTLB.bit.ZRO = AQ_CLEAR;
    
        // Other init functions happen....
        
        // Set epwm1 to count up, once timebase is enabled
        EPwm1Regs_master.TBCTL.bit.CTRMODE = TB_COUNT_UP;
        
        // Other init function happen....
        
        // Start the ePWM peripherals with TBCLKSYNC
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        __asm (" nop");
        __asm (" nop");
        __asm (" nop");
        __asm (" nop");
        __asm (" nop");
        //Perform a software sync
        EPwm1Regs_master.TBCTL.bit.SWFSYNC = 1; // force TBPHS sync. This will propagate through all ePWM channels via SYNCO/SYNCI
        __asm (" nop");
        __asm (" nop");
        __asm (" nop");
        __asm (" nop");
        __asm (" nop");
        EDIS;
    
        // attempt to synchronize using EXTSYNCIN1, which comes from toggling GPIO23
        testExtSyncIn1();
    }
    
    // define SEQUENCESYNC_TEST_DELAY_MS to enable generation of EXTSYNCIN1 via GPIO23
    #define SEQUENCESYNC_TEST_DELAY_MS   10
    // define SEQUENCESYNC_USE_OSHTSYNCMODE to make use of OSHTSYNCMODE
    #define SEQUENCESYNC_USE_OSHTSYNCMODE
    
    // XBAR_INPUT5 is connected to dummy GPIO, so GPIO31 does not drive EXTSYNCIN1
    // GPIO31 is inverted the gpio control register
    // GPIO23 is connected to GPIO31
    // use GPIO23 to generate EXTSYNCIN1 automatically
    void testExtSyncIn1(void) {
        uint32_t sync_timeout=0;    // for timeout
    
        // set EXTSYNCIN1 in idle state (high, because GPIO31 is inverted)
        GpioDataRegs.GPASET.bit.GPIO23=1;
    
        // clear 1ms timer overflow
        CpuTimer0Regs.TCR.bit.TIF=1;
        // EXTSYNCIN1 should already be configured to connect to GPIO31 via XBAR_INPUT5
        // first clear SYNCI bit in TBSTS by writing it 1
        EPwm1Regs_master.TBSTS.bit.SYNCI=1;
        // enable one-shot sync mode for master PWM, so it only propagates a single SYNCO to ePWM2 and so on
        EPwm1Regs_master.TBCTL2.bit.OSHTSYNCMODE=1;
        EPwm1Regs_master.TBCTL2.bit.OSHTSYNC=1;
    
        //wait for GPIO31 to be high (input inversion enabled, so look for GPxDAT=0)
        while(sync_timeout<SYNC_TIMEOUT_MAX_MS) {
            if(GpioDataRegs.GPADAT.bit.GPIO31==0) break;
            // increment sync_timout if 1ms timer has lapsed
            if(CpuTimer0Regs.TCR.bit.TIF) {
                // clear CPU timer interrupt flag
                CpuTimer0Regs.TCR.bit.TIF=1;
                sync_timeout++;
            }
        }
        // connect EXTSYNCIN1 via XBAR_INPUT5 to GPIO31
        XBAR_setInputPin(XBAR_INPUT5, 31);
        // wait for SYNCI flag to set, or for timeout
        while(sync_timeout<SYNC_TIMEOUT_MAX_MS) {
            if(EPwm1Regs_master.TBSTS.bit.SYNCI==1) break;
            // increment sync_timout if 1ms timer has lapsed
            if(CpuTimer0Regs.TCR.bit.TIF) {
                // clear CPU timer interrupt flag
                CpuTimer0Regs.TCR.bit.TIF=1;
                sync_timeout++;
                // generate manual sequence_sync edge after timeout
                if(sync_timeout == SEQUENCESYNC_TEST_DELAY_MS) {
                    GpioDataRegs.GPACLEAR.bit.GPIO23=1;
                }
            }
        }
        // immediately disable EXTSYNCIN1 so no further syncs occur
        XBAR_setInputPin(XBAR_INPsUT5, 100);
    }

    It looks like I'm issuing a SWFSYNC immediately after starting the ePWM timebase by setting CpuSysRegs.PCLKCR0.bit.TBCLKSYNC. That's a holdover from a much older version of the initialization code. It's pointless now, but I don't see how it could be related to my issue.

  • Hi Mike,

    Thanks for sharing more of your program. I do not think that SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_EPWM1) should affect the performance of OSHTSYNC as long as the OSHTSYNC is set and you are writing a '1' to that bit before you try to sync even though you can only read 0 from it (that way by writing a '1' you still set it to allow the single sync pulse to propagate through). I will develop a test case based on the rest of your program and try to find the where the issue is occurring. Please expect a response back from me by Tuesday at the very latest. In the mean time, if you could try to omit any other unnecessary parts of your program such as the SWFSYNC or enabling/disabling the EXTSYNCIN path to see if these are somehow interfering with the OSHTSYNC set that might be helpful. Feel free to update here if you find out any further information.

    Regards,

    Allison

  • Hi Mike,

    Just wanted to update you: I was able to run a stripped down test case and it seems that the OSHTSYNC functions as expected, but when I tried to issue a SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_EPWM1) it disrupted EPWM1 functionality in the test, so I still need to do some more digging into what exactly is affected configuration-wise when doing the peripheral reset and will consult others on it as well.

    A few more follow-up questions: you had mentioned that you are resetting the peripheral in between repetitions, but I wanted to clarify are you calling the EPWM init repeatedly then? I also wanted to ask if you have specific reasoning why you are implementing the peripheral reset in your program? Is it only for testing purposes or is it part of your development flow? Also, did you also try removing the enabling/disabling GPIO and SWFSYNC?

    Regards,

    Allison

  • Hi Allison, thanks for sticking with this.

    Fair question about why I'm resetting the peripheral. See this older thread for background. https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/980873/tms320f28379d-initializing-epwms-while-tbclksync-0

    In my application the entire real-time power control function (which uses the ePWM, ADC, CLA, etc) needs to be able to start, stop, and restart multiple times between MCU resets.

    Originally I wasn't doing a peripheral reset, but observed that after running the ePWM, stopping it, then restarting it, I would sometimes see spurious behavior because certain state machines inside the ePWM hadn't been "flushed" properly. For example, the AQ state, event counters, active and shadow registers... there are a lot of states which cannot be determined by reading any registers, so you can only notice them after their adverse affects are felt. Manually resetting each of those bits/registers made the initializer code grow tremendously, and even then it didn't work 100%. The peripheral reset seemed like the reasonable approach. I'm doing the same for the ADC (which also had some internal states which are difficult to reset otherwise).

    It would be unfortunate if the peripheral reset has blind spots as well. Now my paranoia is coming back...

    Also, did you also try removing the enabling/disabling GPIO and SWFSYNC?

    I can definitely try removing the SWFSYNC and check if that affects anything. What do you mean by the GPIO though? In my setup, if I don't use GPIO23 to control EXTSYNCIN1, then I won't see any SYNC events no matter what.

  • Hi Mike,

    The peripheral reset should clear all the register settings as expected. Are you perhaps able to provide more context to your program? i.e. under what conditions are you calling the epwm init function (which has the peripheral reset) and what other settings/functions are occurring in between each repetition of calling the init to reset the epwm peripheral? Could you provide more of your code for the pwm and gpio configurations as well as your main loop that calls the epwm init? I'm wondering if there is something else that is interfering with the OSHTSYNC or something else I'm missing. Just wanting to understand the full flow of program since there are often other things that are connected together in some subtle way.

    And I was mainly referring to when you were connecting/disconnecting the GPIO23 and GPIO31 together in your code since the OSHTSYNC should be gating the external sync from propagating through to other epwm modules. Let me know if you've seen any different behavior with this.

    Also, are you able to capture all the epwm register settings from the first repetition that works and then the next repetition that doesn't? If you can, it could be really helpful to compare the registers directly from one iteration to the next to make sure 100% that the settings match, though I don't see why they wouldn't if you are configuring the epwm the same after the reset. 

    Regards,

    Allison

  • Hi Mike,

    Attached is the code for the stripped down example I made which executes a peripheral reset + one-shot sync pulse repeatedly for EPWM1 to sync EPWM1, EPWM2, and EPWM3. A GPIO is toggled using a CPUTIMER ISR so the GPIO can be used as the external sync source for EPWM1. EPWM1 is synced repeatedly by the GPIO toggling high, but uses one-shot sync mode to gate all but the first sync pulse to EPWM2 and EPWM3. The CPUTIMER interrupt also then calls the EPWM1 initialization again (which has the peripheral reset and then reconfigures EPWM1) and enables one-shot sync mode and sets the OSHTSYNC bit to propagate a single sync pulse again. I also did check the registers before and after the peripheral reset was executed and made sure they cleared back to reset values after peripheral reset.

    //#############################################################################
    //
    // EPWM OSHT SYNCHRONIZATION
    //
    // (Using OSHTSYNC repeatedly with EPWM peripheral resets)
    //
    //
    // This configures ePWM1, ePWM2, and ePWM3 as follows:
    //  - ePWM1 without phase shift as master
    //  - ePWM2 with phase shift of 0 TBCLKs
    //  - ePWM3 with phase shift of 0 TBCLKs
    //
    // External Connections
    // - GPIO0 EPWM1A
    // - GPIO1 EPWM1B
    // - GPIO2 EPWM2A
    // - GPIO3 EPWM2B
    // - GPIO4 EPWM3A
    // - GPIO5 EPWM3B
    //
    //#############################################################################
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    #define EPWM_TIMER_TBPRD    2000
    
    int count = 0; //count to keep track of CPUTIMER ISR
    
    //
    // Function Prototypes
    //
    void initEPWM(uint32_t base, SysCtl_PeripheralSOFTPRES val);
    
    //
    // Main
    //
    void main(void)
    {
    
        Device_init(); // Initialize device clock and peripherals
        Device_initGPIO(); // Disable pin locks and enable internal pull ups.
        Interrupt_initModule(); // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        Interrupt_initVectorTable(); // Initialize the PIE vector table with pointers to the shell ISR
        Board_init(); // Configure GPIO0/1 , GPIO2/3 and GPIO4/5 as ePWM1A/1B, ePWM2A/2B, ePWM3A/3B pins respectively
    
        // Disable sync(Freeze clock to PWM as well).
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // Initialize EPWM1 without phase shift as master EPWM:
        initEPWM(myEPWM1_BASE, SYSCTL_PERIPH_RES_EPWM1);
        EPWM_setPhaseShift(myEPWM1_BASE, 0);
        EPWM_setTimeBaseCounter(myEPWM1_BASE, 0);
    
        // Initialize EPWM2 with phase shift of 300 TBCLKs
        initEPWM(myEPWM2_BASE, SYSCTL_PERIPH_RES_EPWM2);
        EPWM_setPhaseShift(myEPWM2_BASE, 0);
        EPWM_setTimeBaseCounter(myEPWM2_BASE, 0);
    
        // Initialize EPWM3 with phase shift of 600 TBCLKs
        initEPWM(myEPWM3_BASE, SYSCTL_PERIPH_RES_EPWM3);
        EPWM_setPhaseShift(myEPWM3_BASE, 0);
        EPWM_setTimeBaseCounter(myEPWM3_BASE, 0);
    
        // EPWM1 SYNCO is generated on SYNCIN from GPIO22 being pulled high in CPUTIMER ISR.
        EPWM_setSyncOutPulseMode(myEPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
        EPWM_enableOneShotSync(myEPWM1_BASE); // Enable on-shot sync mode on EPWM1 to gate sync pulses to EPWM2/3 after resetting in the init.
        EPWM_startOneShotSync(myEPWM1_BASE); // Set the OSHTSYNC bit to allow a single sync pulse to propagate after resetting in the init.
    
        // EPWM2 uses the ePWM 1 SYNCO as its SYNCIN.
        EPWM_setSyncOutPulseMode(myEPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
    
        // EPWM3 uses the ePWM 1 SYNCO as its SYNCIN.
        EPWM_setSyncOutPulseMode(myEPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
    
        // Enable sync and clock to EPWM
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
    
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        EINT;
        ERTM;
    
        // IDLE loop. Just sit and loop forever:
        for(;;)
        {
    
        }
    }
    
    void initEPWM(uint32_t base, SysCtl_PeripheralSOFTPRES val) // General EPWM initialization
    {
        SysCtl_resetPeripheral(val); //Start by resetting EPWM peripheral (clears the EPWM's registers back to reset values)
    
        // Set-up TBCLK
        EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD);
        EPWM_setPhaseShift(base, 0U);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_enablePhaseShiftLoad(base);
    
        // Set Compare values
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, EPWM_TIMER_TBPRD/2);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_B, EPWM_TIMER_TBPRD/4);
    
        // Set up counter mode
        EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP);
        EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_8, EPWM_HSCLOCK_DIVIDER_1);
    
        // Set up shadowing
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        // Set actions
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    
    }
    
    __interrupt void INT_myCPUTIMER0_ISR(void)
    {
        if(count==10)
        {
            initEPWM(myEPWM1_BASE, SYSCTL_PERIPH_RES_EPWM1); // Reset EPWM1 and reinitialize EPWM1
            EPWM_setPhaseShift(myEPWM1_BASE, 0); // Set EPWM1 to sync back to the GPIO pulling high
            EPWM_enableOneShotSync(myEPWM1_BASE); // Enable on-shot sync mode on EPWM1 to gate sync pulses to EPWM2/3 after resetting using the init.
            EPWM_startOneShotSync(myEPWM1_BASE); // Set the OSHTSYNC bit to allow a single sync pulse to propagate after resetting using the init.
            count = 0; // Reset count
        }
    
        GPIO_togglePin(myGPIO22); //toggle GPIO22 to be external sync source EXTSYNCIN for EPWM1
    
        count++; // Increment counter
    
        Interrupt_clearACKGroup(INT_myCPUTIMER0_INTERRUPT_ACK_GROUP); //Acknowledge CPUTIMER interrupt
    
    }
    

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/epwm_5F00_oshtsync.syscfg

    Below are some scope shots of the program to help show its functionality:

    • Channel 1 = EPWM1
    • Channel 2 = EPWM2
    • Channel 3 = EPWM3
    • Channel 4 = SyncOut pulse from EPWM1 (gated by OSHTSYNC; SyncOut pulse used as scope trigger)
      • SyncOut routed out through OUTPUTXBAR

    1. The first sync pulse after starting the program is allowed to propagate through all three EPWMs:

    2. Other sync pulses to EPWM1 occur, but are gated from EPWM2 and EPWM3 causing a slight visible offset:

    3. EPWM1 goes low for a short time as it is reset when EPWM1 init is called again. Once reset/reconfiguration is complete and OSHTSYNC is set again, the next sync pulse is allowed to propagate through all EPWMs to sync them:

    This cycle repeats since the GPIO is continually toggling and I also looped the calling of the EPWM 1 init (EPWM1 reset).

    Let me know if any of this helps with debugging! In general, though, I think this confirms that the peripheral reset functions as we thought. As long as you reconfigure your EPWM1 and re-enable and set one-shot sync mode bits after resetting, the OSHTSYNC should work without issues.

    Regards,

    Allison

  • Hi Allison,

    The code for initializing/halting these peripherals is a couple thousand lines long, and I doubt it's it would help to see that much detail.

    I can give some more details though. The handling of the EXTSYNCIN1 event as described above is basically the very last step in my initialization routine. After that code, I do not access the ePWM registers at all in the main loop. I'm only using the ePWMs to control timing of other events, and those timings are totally fixed (so I'm no writing to CMPA or CMPB to adjust duty cycle, etc). I'm not using the tripzone, so there should be anything affecting the ePWMs after initialization. When I need to stop and restart the peripherals (in order to synchronize them to a new EXTSYNCIN1 event), I first issue resets to the ePWM modules. I don't stop their timebases or do anything else (I don't see anything wrong with this in my case). I do the same to some other peripherals (the CLA, ADC, Pie, etc) but I doubt other peripherals can really affect the OSHTSYNCMODE operation.

    I did try your suggestion of removing the SWFSYNC, but did not notice any effect.

    But there was another experiment I did with a positive result. I removed the last line of my testExtSyncIn1() function in which I disconnect EXTSYNCIN1 from GPIO31 by changing the INPUTXBAR5 to a dummy GPIO. If I do this, then I do see SYNCO events occurring, even when  OSHTSYNCMODE is set. I also see the phase of ePWM2A synchronizing, as desired. I don't have any explanation for why this change to INPUTXBAR5 would have this interaction with OSHTSYNCMODE though. Maybe you can make some sense out of this clue....

  • Hi Mike,

    Thanks so much for the response. If you see SYNCO pulses from EPWM1 from every EXTSYNCIN even when EPWM1 is supposed to be in OSHTSYNC mode, then that to me sounds like there is an issue with setting up OSHTSYNC mode properly to allow only a single pulse through instead of all sync pulses (is this what you are saying is happening? Or is it that it is only allowing one sync pulse through per 'repetition' as is desired?).

    I see you had been disconnecting the GPIO from INPUTXBAR in that last line - were these being reconnected at the beginning/before each repetition (assuming 1 repetition = EPWM peripheral reset and then issuing of external GPIO pulse as the EPWM1 sync source) as well? I assume yes, but if not, that would explain why you weren't seeing the SYNCO pulses before- because there was perhaps no SYNCI actually routing through INPUTXBAR into EPWM1.

    Have you had a chance to look at the code and scope shots from my last response? Let me know your thoughts- hope that it helps provide some certainty in terms of your worries about the peripheral reset paranoia you mentioned.

    Regards,

    Allison