Some timer fixes for PWM mode.
authorNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 1 Oct 2015 19:56:28 +0000 (21:56 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 16:03:04 +0000 (17:03 +0100)
drivers/timers.c
include/core/lpc_regs_12xx.h
include/drivers/timers.h

index 26c3e56..6a6dbdd 100644 (file)
@@ -206,12 +206,12 @@ int timer_setup(uint32_t timer_num, const struct timer_config* conf)
                        }
                        break;
                case LPC_TIMER_MODE_PWM:
+                       /* Make sure we have a PWM cycle length */
                        if (conf->match[ conf->config[1] ] == 0) {
-                               return -EINVAL; /* Force use of Channel 3 for PWM cycle length */
+                               return -EINVAL;
                        }
-                       /* Activate selected PWM channels 0 to 2 */
-                       timer->regs->pwm_ctrl = (conf->config[0] & 0x07);
-                       /* Use Channel 3 for PWM cycle length as recommended in the manual */
+                       /* Activate selected PWM channels 0 to 3 */
+                       timer->regs->pwm_ctrl = (conf->config[0] & 0x0F);
                        timer->regs->match_ctrl &= ~(LPC_TIMER_MATCH_ERASE(conf->config[1]));
                        timer->regs->match_ctrl |= (LPC_TIMER_RESET_ON_MATCH << LPC_TIMER_MATCH_SHIFT(conf->config[1]));
                        for (i = 0; i < NUM_CHANS; i++) {
index e8b80c6..570f563 100644 (file)
@@ -710,14 +710,14 @@ struct lpc_timer
 #define LPC_TIMER_INTERRUPT_ON_MATCH   0x01
 #define LPC_TIMER_RESET_ON_MATCH       0x02
 #define LPC_TIMER_STOP_ON_MATCH        0x04
-#define LPC_TIMER_MATCH_ERASE(x)       (0x07 << ((x) * 3))
-#define LPC_TIMER_MATCH_SHIFT(x)       ((x) * 3)
+#define LPC_TIMER_MATCH_ERASE(x)       (0x07 << (((x) & 0x03) * 3))
+#define LPC_TIMER_MATCH_SHIFT(x)       (((x) & 0x03) * 3)
 /* Capture internal configuration */
 #define LPC_TIMER_CAP_ON_RISING_EDGE   0x01
 #define LPC_TIMER_CAP_ON_FALLING_EDGE  0x02
 #define LPC_TIMER_INTERRUPT_ON_CAPTURE 0x04
-#define LPC_TIMER_CAPTURE_ERASE(x)     (0x07 << ((x) * 3))
-#define LPC_TIMER_CAPTURE_SHIFT(x)     ((x) * 3)
+#define LPC_TIMER_CAPTURE_ERASE(x)     (0x07 << (((x) & 0x03) * 3))
+#define LPC_TIMER_CAPTURE_SHIFT(x)     (((x) & 0x03) * 3)
 /* Match external configuration */
 #define LPC_TIMER_NOTHING_ON_MATCH     0x00
 #define LPC_TIMER_CLEAR_ON_MATCH       0x01
@@ -745,7 +745,7 @@ struct lpc_timer
 #define LPC_COUNTER_CLEAR_ON_CHAN3_RISE   0x06
 #define LPC_COUNTER_CLEAR_ON_CHAN3_FALL   0x07
 /* PWM */
-#define LPC_PWM_CHANNEL_ENABLE(x)    (0x01 << (x))
+#define LPC_PWM_CHANNEL_ENABLE(x)    (0x01 << ((x) & 0x03))
 
 
 
index acac774..8c244ff 100644 (file)
@@ -56,6 +56,7 @@ enum lpc_timer_mode {
 /* Notes:
  * In counter or PWM mode, the config is done using config[0] for enabled channels and config[1] holds
  *   the channel number used to control PWM cycle.
+ *   Note that the manual recommends Channel 3 be used for PWM cycle length.
  * The field "reset_on_capture" must be set to LPC_COUNTER_CLEAR_ON_EVENT_EN ored with one
  *   of the LPC_COUNTER_CLEAR_ON_CHAN*_* to activate the clear timer on event functionality
  */