I'm trying to use the PWM peripheral to generate pulse streams of varying period and a duty cycle of approx 50%. I have code which works most of the time, but sometimes when I change the period, I get an over-length pulse at the point of change - a pulse which is longer than the correct pulse for either the previous or the new period.
A specific example:
- going from 25.05us to 50.01us period (from 12.5 to 25 us pulse length), I sometimes get a high pulse of 49.5us (see scope trace below)
- going from 50.01us to 25.05us period (from 25 to 12.5 us pulse length), I sometimes get a high pulse of 37.4us.
In one run of 1000 changes of period, I saw the over-length pulse 14 times.
I'm using a PWM clock divisor of 64 (PWM_CC = 0x105), and the changes to the LOAD and CMP registers of the PWM are made in "Globally Synchronized" mode ("Updates to the register are delayed until the next time the counter is 0 after a synchronous update has been requested through the PWMCTL register"). As I understand it, this mode should mean that the LOAD and CMP registers both get updated at the same time, but even if they did not I can't see why I should sometimes get a period of over 62us when changing between 25 and 50us.
The code which is updating the PWM timings is:
HWREG(PWM0_BASE + pwm_gen_id + PWM_O_X_LOAD) = period - 1; // set PWM period
HWREG(PWM0_BASE + pwm_gen_id + PWM_O_X_CMPA) = period >> 1; // set PWM duty cycle to 50%
HWREG(PWM0_BASE + pwm_gen_id + PWM_O_X_GENA) = 0x8c; // drive pwm output high on load and low on CMPAdn
HWREG(PWM0_BASE + PWM_O_CTL) = pwm_gen_bit; // Synchronize pending PWM register changes the next time the counter becomes zero
and the state of the relevant PWM registers when running is
PWMCTL=0
PWMSYNC=0
PWMENABLE=0x55
PWMENUPD=0x2222
PWM0CTL=0xfd
PWM0CMPB=0
PWM0GENA=0x8c
and either
PWM0LOAD=0x5d, PWM0CMPA=0x2f
or
PWM0LOAD=0x2e, PWM0CMPA=0x17
The is on a TM4C1294NCPDT with silicon revision 3, so the only documented PWM bug is PWM#04, which is not relevant as I am not using any PWM interrupts.
I'm starting to feel arrogant enough to suspect a bug in the PWM peripheral, so will someone please tell me how I'm being dumb here and it's my fault for not using it properly?
Thanks,
Michael
(I also saw wrong-length first pulses when starting the pulse stream running, either by writing to PWMENABLE or by changing PWM0GENA from 0x80 to 0x8c - this may be related to the above issue. But let's start with the period-change issue as it is simpler to understand.)