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.

TM4C129XNCZAD: One-shot PWM for timers doesn't work for large ILR

Part Number: TM4C129XNCZAD

I'm trying to get a sequence of for PWM pulses generated by daisy chaining both A and B timers of timers 1 and 2 using one-shot PWM mode. If I set PHASE_PERIOD to any value that fits in 16 bits the code below works. If I set PHASE_PERIOD to more than 16 bits, it looks like the timer counts down until the first time the 16 least significant bits of Timer 1A hit zero, Timer 1A enable is cleared and then everything stops. Even if I try re-enabling timer 1A, the enable appears to be cleared immediately and the timer stops right away.

The documentation doesn't talk about using one-shot PWM mode and it isn't supported natively by the TI libraries. I had to define my own configuration for it. Is it a valid operating mode?

#define PHASE_PERIOD                                                            (65536U)

#define TIMER_CFG_A_ONE_SHOT_PWM                               (0x009)

#define TIMER_CFG_B_ONE_SHOT_PWM                               (0x900)

uint32_t load;

TimerConfigure( TIMER1_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_ONE_SHOT_PWM | TIMER_CFG_B_ONE_SHOT_PWM );

/* Phase C PWM */
GPIOPinConfigure( GPIO_PS0_T2CCP0 );
GPIOPinTypeTimer( GPIO_PORTS_BASE, GPIO_PIN_0 );

/* Phase D PWM */
GPIOPinConfigure( GPIO_PS1_T2CCP1 );
GPIOPinTypeTimer( GPIO_PORTS_BASE, GPIO_PIN_1 );

TimerConfigure( TIMER2_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_ONE_SHOT_PWM | TIMER_CFG_B_ONE_SHOT_PWM );

load = PHASE_PERIOD;
// Phase A and B PWM control.
TimerLoadSet( TIMER1_BASE, TIMER_BOTH, load & 0xffff );
TimerPrescaleSet( TIMER1_BASE, TIMER_BOTH, load >> 16 );

// Phase C and D PWM control.
TimerLoadSet( TIMER2_BASE, TIMER_BOTH, load & 0xffff );
TimerPrescaleSet( TIMER2_BASE, TIMER_BOTH, load >> 16 );

/// Phase B-D wait for the previous timer to timeout before starting.
TimerControlWaitOnTrigger( TIMER1_BASE, TIMER_B, true );
TimerControlWaitOnTrigger( TIMER2_BASE, TIMER_BOTH, true );

load /= 2;

TimerMatchSet( TIMER1_BASE, TIMER_BOTH, load & 0xffff );

TimerPrescaleMatchSet( TIMER1_BASE, TIMER_BOTH, load >> 16 );

TimerMatchSet( TIMER2_BASE, TIMER_BOTH, load & 0xffff );

TimerPrescaleMatchSet( TIMER2_BASE, TIMER_BOTH, load >> 16 );

while ( true )

{

if ( (HWREG( TIMER2_BASE + TIMER_O_CTL ) & TIMER_CTL_TBEN) == 0 )

{

// TODO: Set the warmer phase duty cycle

// Enable 2 first since it won't start until timer 1 has completed.

TimerEnable( TIMER2_BASE, TIMER_BOTH );

TimerEnable( TIMER1_BASE, TIMER_BOTH );

}

}

}

Thanks for your help.

  • Keith Clifford said:
    PWM pulses generated by daisy chaining both A and B timers of timers 1 and 2 using one-shot PWM mode

    I'm in general agreement w/your objective - but  am unable to confirm that such Timer-Generated, "One-Shot PWM Mode"  - formally (and properly)  exists.     You DO ask if yours is a "Valid Operating Mode" - from the chart description (below) and my years of experience (here & w/multiple other ARM MCUs) - I would vote,  NO!

    Follows justification (directly from my current 4C129 MCU Manual.)    Note that "One-Shot & PWM" Modes are separate - I am unsure if they can be (properly blended/combined!)

    Now the fact that you report (some) success w/16 bits (or fewer) suggests that you (may) have created a "Successful Hybrid Mode" - of which myself - and perhaps others (to include vendor) were unaware!     Do note that in (both) cases "One-Shot" or "PWM" the "counter size" IS limited to 16 bits - yet the Prescaler may extend the range (of each) to 24 bits.         

    While the MCU Manual and API evidence "stacks against you" - it may be possible to  "Tease Out" such capability - provided sufficient "time, energy & proper + sustained focus" - are unleashed.

    Perhaps if you describe your "end objective" - myself  or others here - may "Share such need" - and produce (some) contribution...

  • It is not clear what you are trying to do, by chaining two timers.

    With that said, read the data sheet about the timers high 16 bits in the pwm mode. You will find it helpful.
  • As to, "Timer's high 16 bits in PWM Mode" - my belief is that  "No such high 16 bits (productively) exist" (w/in Register GPTMTnILR) - when the Timer is in 16 bit, PWM mode.

    Eight additional "high bits" (instead) - may be achieved - via the Prescaler (Register GPTMTnPR) - as the chart I presented reveals.

    The MCU Manual notes,  "In a 16-bit mode, the upper 16 bits of this register (GPTMTAILR) read as 0s and have no effect on the state of GPTMTBILR."

  • Thanks for your help. I have it working using ALTCLK (16 instead of 120 MHz)to drive the timers. I don't quite have the range that I want and since ALTCLK is derived from PIOSC it isn't synched to the system clock but I'm going to go with it and see how it works out. I had another look at the documentation and there is the following note for TxMR:TAAMS

    Note: To enable PWM mode, you must also clear the TACMR
    bit and configure the TAMR field to 0x1 or 0x2.

    0x01 is for one-shot and 0x02 is for periodic so according to that the mode is supported. As a test I changed the timer configuration to periodic and it didn't have the same issue but I need it to be one-shot.

    The application needs to drive 4 phases of a heating element in sequence. If all else fails I can drive the phases explicitly.

  • Glad to note your success - good job.   (yet w/few "reservations.")

    Might you prepare (even) a crude "pen/pencil" sketch - showing the timing relationship - between your (believed) 4 channels.     Firm/I do much "Multi-Phase" design work  (via Cortex M7) - and have employed methods (outside) - of that you've presented.    (and not necessarily demanding the power of superior MCU)

    As to the "Syncing of Timers" - do note that there "was" (very) delicate (and demanding) "errata" attached to such "Timer Sync."      Quick scan of the most current MCU errata may "save you" - down the line.

    The reduction of System Clock - from 120 to 16MHz (non-integer) BTW - IS concerning - and (may) signal (pardon) "inefficiency" w/in your unique, Timer-Sync'ed implementation.     

    In addition - are not "All other" aspects of your MCU operation - throttled back?     Is that acceptable?

  • Thanks for mentioning the errata. I scanned it and don't see anything that applies in my circumstances.

    I didn't change the system clock. I set the clock source for the timers I'm using in the daisy chain to ALTCLK setting GPTMCC for the two timer modules to 1 and made sure the ALTCLKCFG is set to use PIOSC.

    I've attached a scope capture. I have the PWM set to close to 100% and I have to explicitly restart the sequence by enabling the first timer in the chain.

  • There's no doubt that you've achieved your "Four Phase" Output.     Tomorrow - when staff arrives - I'll see if they can "Search/Find" the (rather severe) usage requirement - forced upon (past) Timer Sync.   (this may have been resolved - most of my work now resolves around "R-52 and M7" (Autonomous Auto) so I'm unaware if a "fix here"  arrived/succeeded.)

    One caution - our multi-phase designs (demand) that a, "dead-band" be inserted between the "High & Low Side" Power FETs - driven by each of our phases.       Such "dead-band" is not (directly) achievable via the Timer Implementation - yet is "fully/effectively available" - via your MCU's (far more advanced) PWM Generators.     (which can easily produce, "Complementary PWM signals" - with programmable dead-band - adjustable at (both) leading & trailing signal edge.)

    Of note to you - those PWM Generators DO accommodate up to 4 channels - "just satisfying" your needs.     (yet not ours - which extend to 6-8 phases - to meet client (demanding) specs.)    All 8 - PWM Generator Signal Outputs - may be "instantly" halted - via a "Single, PWM Fault pin!"     That "fault pin" can - easily & efficiently - provide, "Over-Current Protection" and/or (many other) PWM Signal over-rides...

  • for something like that, you don't need to get too fancy. one timer would do it easily, and to generate as many pulses as you want.

    this may help get you started: 

    it uses avr/pic to generate arbitrary and fully independent pulses to drive servos but the same concept applies here.