Bug: PwmOut broken on LPC11UXX

28 Apr 2014

A while ago I wrote some code for a booster circuit that drives PIO0_8 at 500kHz with a varying duty cycle. The code I used (simplified for clarity) is as follows:

#include "mbed.h"

PwmOut sw(P0_8);

int main()
{
    //Set the switch period to 2µs (500kHz)
    sw.period_us(2);

    //Set the initial duty cycle to 90%
    sw = 0.9;

    //Don't exit main!
    while(1);
}

Today I received a nasty surprise when I tried to revisit this code using the latest mbed library revision. For some reason, I was no longer getting the voltage I was expecting. On closer inspection with an oscilloscope, I found that PIO0_8 is no longer running at 500kHz, but around 33kHz. At this point I haven't checked the past library versions to find out where it broke, but it is definitely broken. Attached is a picture of the waveform I get when I run the attached code with mbed library revision 83:

/media/uploads/neilt6/pwmout_bug.jpg

28 Apr 2014

Just did a little digging, and it turns out pwmout_api.c was updated 4 months ago in order to "fix 16bit timer pwm output". Surprise surprise, PIO0_8 is connected to CT16B0...

28 Apr 2014

To be fair, 16-bit timer output was always broken on the LPC11uXX devices, it was running at Fclk. You can do the math: for your application it was probably fine, but anyone trying to control a servo with it failed, and that is a more normal use case ;).

Still I thought it wasn't changed that this shouldn't be possible anymore, something to have a look at, I don't directly see what is wrong with the code there.

I was going to write that your code should have been impossible anyway on mbed, since PWM uses 1 microsecond accuracy, but I see the duty cycle code isn't limitted by that, and it runs at full speed on the LPC11u24, while on Fclk/4 on the LPC1768. If you do want to use the latest mbed, it should in the meantime work with: https://mbed.org/users/Sissors/code/FastPWM/.

28 Apr 2014

Erik - wrote:

To be fair, 16-bit timer output was always broken on the LPC11uXX devices, it was running at Fclk. You can do the math: for your application it was probably fine, but anyone trying to control a servo with it failed, and that is a more normal use case ;).

Surely there's a way to handle both scenarios, the 16-bit timers are definitely capable of producing 500kHz or even 1MHz PWM waveforms. I should know, my original booster code (which I wrote using LPCXpresso) ran at 1MHz. To break one use case in favor of another simply isn't fair. I myself have never used PWM on a microcontroller to drive servos.

28 Apr 2014

You are right that update shouldn't have broken it for you either, and looking at it I don't see why it would break it for you. You have no other PwmOut objects at the same time? If not I can later look at it more in depth, not now though :).

Btw it is possible to handle both scenarios, using a dynamic prescaler. And that is exactly what that update added. And also what FastPWM uses for 16-bit timers (on 32-bit timers it is a waste of cpu cycles to calculate prescalers: the NXP 32-bit timers can make periods up to something like 10,000 years on the LPC11u24, longer on the LPC1768). From all use cases with PWM at high speeds, yours is the one which profits least from FastPWM (all other supported devices have increased resolution), still it might be useful since it allows you to change your period with clock cycle accuracy, instead of microsecond accuracy.

Of course that doesn't fix the library, which also should be done, when figured out what the actual issue is :P.

29 Apr 2014

Erik - wrote:

Btw it is possible to handle both scenarios, using a dynamic prescaler. And that is exactly what that update added. And also what FastPWM uses for 16-bit timers (on 32-bit timers it is a waste of cpu cycles to calculate prescalers: the NXP 32-bit timers can make periods up to something like 10,000 years on the LPC11u24, longer on the LPC1768). From all use cases with PWM at high speeds, yours is the one which profits least from FastPWM (all other supported devices have increased resolution), still it might be useful since it allows you to change your period with clock cycle accuracy, instead of microsecond accuracy.

Of course that doesn't fix the library, which also should be done, when figured out what the actual issue is :P.

Ah, makes sense. Actually, the person who originally patched the file has some modified code on GitHub for me to test tomorrow. Hopefully it'll be that simple!

29 Apr 2014

Good news everyone, the modified code works! The bug will be fixed as soon as the library is updated.

/media/uploads/neilt6/pwmout_fixed.jpg

29 Apr 2014

Ah of course, it makes so much sense now. I actually did wonder if that if statement was correct (yes I really did :P), it was imo a bit weird, but I didn't thought it was wrong. But it actually is quite logical now :). Good it is fixed.