• Vladimir Zapolskiy's avatar
    pwm: lpc32xx: fix and simplify duty cycle and period calculations · 5a9fc9c6
    Vladimir Zapolskiy authored
    The change fixes a problem, if duty_ns is too small in comparison
    to period_ns (as a valid corner case duty_ns is 0 ns), then due to
    PWM_DUTY() macro applied on a value the result is overflowed over 8
    bits, and instead of the highest bitfield duty cycle value 0xff the
    invalid duty cycle bitfield value 0x00 is written.
    
    For reference the LPC32xx spec defines PWMx_DUTY bitfield description
    is this way and it seems to be correct:
    
     [Low]/[High] = [PWM_DUTY]/[256-PWM_DUTY], where 0 < PWM_DUTY <= 255.
    
    In addition according to my oscilloscope measurements LPC32xx PWM is
    "tristate" in sense that it produces a wave with floating min/max
    voltage levels for different duty cycle values, for corner cases:
    
      PWM_DUTY == 0x01 => signal is in range from -1.05v to 0v
      ....
      PWM_DUTY == 0x80 => signal is in range from -0.75v to +0.75v
      ....
      PWM_DUTY == 0xff => signal is in range from 0v to +1.05v
    
      PWM_DUTY == 0x00 => signal is around 0v, PWM is off
    
    Due to this peculiarity on very long period ranges (less than 1KHz)
    and odd pre-divider values PWM generated wave does not remind a
    clock shape signal, but rather a heartbit shape signal with positive
    and negative peaks, so I would recommend to use high-speed HCLK clock
    as a PWM parent clock and avoid using RTC clock as a parent.
    
    The change corrects PWM output in corner cases and prevents any
    possible overflows in calculation of values for PWM_DUTY and
    PWM_RELOADV bitfields, thus helper macro definitions may be removed.
    Signed-off-by: default avatarVladimir Zapolskiy <vz@mleia.com>
    Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
    5a9fc9c6
pwm-lpc32xx.c 4.11 KB