diff --git a/arch/arm/src/samv7/sam_pwm.c b/arch/arm/src/samv7/sam_pwm.c index 71eab51dfc2b1..5f0650adc6b79 100644 --- a/arch/arm/src/samv7/sam_pwm.c +++ b/arch/arm/src/samv7/sam_pwm.c @@ -52,12 +52,6 @@ #ifdef CONFIG_SAMV7_PWM -#ifdef CONFIG_PWM_NCHANNELS -# define PWM_NCHANNELS CONFIG_PWM_NCHANNELS -#else -# define PWM_NCHANNELS 1 -#endif - #define CHANNEL_OFFSET 0x20 #define COMP_OFFSET 0x10 #define FAULT_SEL_OFFSET 0x8 @@ -436,14 +430,14 @@ static uint32_t pwm_getreg(struct sam_pwm_s *priv, uint32_t offset); /* Helper functions */ static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel, - ub16_t duty); + pwm_duty_t duty); static void pwm_set_freq(struct pwm_lowerhalf_s *dev, uint8_t channel, - uint32_t frequency); + pwm_freq_t frequency); static void pwm_set_comparison(struct pwm_lowerhalf_s *dev); #ifdef CONFIG_PWM_DEADTIME static void pwm_set_deadtime(struct pwm_lowerhalf_s *dev, uint8_t channel, - ub16_t dead_time_a, ub16_t dead_time_b, - ub16_t duty); + pwm_duty_t dead_time_a, pwm_duty_t dead_time_b, + pwm_duty_t duty); #endif static void pwm_set_polarity(struct pwm_lowerhalf_s *dev, uint8_t channel, uint8_t cpol, uint8_t dcpol); @@ -481,7 +475,7 @@ static uint32_t pwm_getreg(struct sam_pwm_s *priv, uint32_t offset) ****************************************************************************/ static void pwm_set_freq(struct pwm_lowerhalf_s *dev, uint8_t channel, - uint32_t frequency) + pwm_freq_t frequency) { struct sam_pwm_s *priv = (struct sam_pwm_s *)dev; uint32_t regval; @@ -542,7 +536,7 @@ static void pwm_set_freq(struct pwm_lowerhalf_s *dev, uint8_t channel, ****************************************************************************/ static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel, - ub16_t duty) + pwm_duty_t duty) { struct sam_pwm_s *priv = (struct sam_pwm_s *)dev; uint16_t period; @@ -555,7 +549,7 @@ static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel, /* Compute PWM width (count value to set PWM low) */ - width = b16toi(duty * period + b16HALF); + width = b16toi(b16divi(ftob16(duty), 100) * period + b16HALF); /* Update duty cycle */ @@ -675,8 +669,8 @@ static void pwm_set_comparison(struct pwm_lowerhalf_s *dev) #ifdef CONFIG_PWM_DEADTIME static void pwm_set_deadtime(struct pwm_lowerhalf_s *dev, uint8_t channel, - ub16_t dead_time_a, ub16_t dead_time_b, - ub16_t duty) + pwm_duty_t dead_time_a, pwm_duty_t dead_time_b, + pwm_duty_t duty) { struct sam_pwm_s *priv = (struct sam_pwm_s *)dev; uint16_t period; @@ -691,20 +685,14 @@ static void pwm_set_deadtime(struct pwm_lowerhalf_s *dev, uint8_t channel, /* Compute channel's duty cycle value. Dead time counter has only 12 bits * and not 16 as duty cycle or period counter. Therefore a 12 bits recount * is necessary to set the dead time value corresponding to selected - * frequency. This expects the dead time value selected in the application - * is moved left by 12 and devided by 100. For example: - * dead_time_a = (selected_dead_time_duty << 12) / 100 - * This aproach is the same as with duty cycle setup in the application - * but with 12 bits. + * frequency. * * Also note that it might not be possible to get correct delay on lower * frequencies since dead time register has only 12 bits. */ - width_1 = (dead_time_a * period) >> 12; - width_2 = (dead_time_b * period) >> 12; - - regval = b16toi(duty * period + b16HALF); + width_1 = (((b16_t)(dead_time_a * 4096.0f) / 100) * period) >> 12; + width_2 = (((b16_t)(dead_time_b * 4096.0f) / 100) * period) >> 12; /* It is required width_1 < (CORD - CDTY) and * width_2 < CDTY @@ -957,7 +945,6 @@ static int pwm_start(struct pwm_lowerhalf_s *dev, const struct pwm_info_s *info) { struct sam_pwm_s *priv = (struct sam_pwm_s *)dev; -#ifdef CONFIG_PWM_MULTICHAN uint32_t regval; for (int i = 0; i < PWM_NCHANNELS; i++) @@ -978,7 +965,7 @@ static int pwm_start(struct pwm_lowerhalf_s *dev, /* Set the frequency and enable PWM output for each channel */ pwm_set_freq(dev, priv->channels[index - 1].channel, - info->frequency); + info->channels[i].frequency); #ifdef CONFIG_PWM_DEADTIME pwm_set_deadtime(dev, priv->channels[index - 1].channel, info->channels[i].dead_time_a, @@ -1030,18 +1017,6 @@ static int pwm_start(struct pwm_lowerhalf_s *dev, pwm_putreg(priv, SAMV7_PWM_ENA, CHID_SEL(1)); pwm_putreg(priv, SAMV7_PWM_SCUC, regval); } -#else - /* Set the frequency and enable PWM output just for first channel */ - - pwm_set_freq(dev, priv->channels[0].channel, info->frequency); -#ifdef CONFIG_PWM_DEADTIME - pwm_set_deadtime(dev, priv->channels[0].channel, - info->dead_time_a, info->dead_time_b); -#endif - pwm_set_polarity(dev, priv->channels[0].channel, - info->cpol, info->dcpol); - pwm_set_output(dev, priv->channels[0].channel, info->duty); -#endif pwm_set_comparison(dev); @@ -1072,7 +1047,6 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev) struct sam_pwm_s *priv = (struct sam_pwm_s *)dev; uint32_t regval; -#ifdef CONFIG_PWM_MULTICHAN for (int i = 0; i < priv->channels_num; i++) { regval = CHID_SEL(1 << priv->channels[i].channel); @@ -1085,10 +1059,6 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev) regval &= ~(CHID_SEL(1 << 0) | CHID_SEL(1 << 1) | CHID_SEL(1 << 2) | CHID_SEL(1 << 3)); pwm_putreg(priv, SAMV7_PWM_SCM, regval); -#else - regval = CHID_SEL(1 << priv->channels[0].channel); - pwm_putreg(priv, SAMV7_PWM_DIS, regval); -#endif /* CONFIG_PWM_MULTICHAN */ return OK; } diff --git a/drivers/timers/pwm.c b/drivers/timers/pwm.c index 9e627fdcde28f..ee3028a0f04de 100644 --- a/drivers/timers/pwm.c +++ b/drivers/timers/pwm.c @@ -114,21 +114,14 @@ static const struct file_operations g_pwmops = static void pwm_dump(FAR const char *msg, FAR const struct pwm_info_s *info, bool started) { -#ifdef CONFIG_PWM_MULTICHAN int i; -#endif - - pwminfo("%s: frequency: %" PRId32 "\n", msg, info->frequency); -#ifdef CONFIG_PWM_MULTICHAN - for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + for (i = 0; i < PWM_NCHANNELS; i++) { - pwminfo(" channel: %d duty: %08" PRIx32 "\n", - info->channels[i].channel, info->channels[i].duty); + pwminfo(" channel: %d frequency: %" PWM_FREQ_PRI " duty:" + " %" PWM_FREQ_PRI "\n", info->channels[i].channel, + info->channels[i].frequency, info->channels[i].duty); } -#else - pwminfo(" duty: %08" PRIx32 "\n", info->duty); -#endif #ifdef CONFIG_PWM_PULSECOUNT pwminfo(" count: %" PRIx32 "\n", info->count); diff --git a/include/nuttx/timers/pwm.h b/include/nuttx/timers/pwm.h index 3e7a7c9812c23..3fa32bffee30f 100644 --- a/include/nuttx/timers/pwm.h +++ b/include/nuttx/timers/pwm.h @@ -138,61 +138,57 @@ #define PWM_DCPOL_LOW 1 /* Logical zero */ #define PWM_DCPOL_HIGH 2 /* Logical one */ +/* PWM number of configured channels ****************************************/ + +#ifdef CONFIG_PWM_MULTICHAN +#define PWM_NCHANNELS CONFIG_PWM_NCHANNELS +#else +#define PWM_NCHANNELS 1 +#endif + +/* PWM frequency and duty types *********************************************/ + +#ifdef CONFIG_HAVE_FLOAT +typedef float pwm_freq_t; +typedef float pwm_duty_t; +#define PWM_FREQ_PRI "f" +#define PWM_DUTY_PRI "f" +#else +typedef uint32_t pwm_freq_t; +typedef uint8_t pwm_duty_t; +#define PWM_FREQ_PRI PRIx32 +#define PWM_DUTY_PRI PRIx8 +#endif + /**************************************************************************** * Public Types ****************************************************************************/ -/* If the PWM peripheral supports multiple output channels, then this - * structure describes the output state on one channel. - */ +/* This structure describes the characteristics of one channel */ -#ifdef CONFIG_PWM_MULTICHAN struct pwm_chan_s { - ub16_t duty; + pwm_freq_t frequency; + pwm_duty_t duty; #ifdef CONFIG_PWM_OVERWRITE bool ch_outp_ovrwr; bool ch_outp_ovrwr_val; #endif #ifdef CONFIG_PWM_DEADTIME - ub16_t dead_time_a; - ub16_t dead_time_b; + pwm_duty_t dead_time_a; + pwm_duty_t dead_time_b; #endif uint8_t cpol; uint8_t dcpol; int8_t channel; }; -#endif -/* This structure describes the characteristics of the pulsed output */ +/* This structure describes the PWM device */ struct pwm_info_s { - uint32_t frequency; /* Frequency of the pulse train */ - -#ifdef CONFIG_PWM_MULTICHAN - /* Per-channel output state */ - - struct pwm_chan_s channels[CONFIG_PWM_NCHANNELS]; - -#else - ub16_t duty; /* Duty of the pulse train, "1"-to-"0" duration. - * Maximum: 65535/65536 (0x0000ffff) - * Minimum: 1/65536 (0x00000001) */ -#ifdef CONFIG_PWM_DEADTIME - ub16_t dead_time_a; /* Dead time value for main output */ - ub16_t dead_time_b; /* Dead time value for complementary output */ -#endif -# ifdef CONFIG_PWM_PULSECOUNT - uint32_t count; /* The number of pulse to generate. 0 means to - * generate an indefinite number of pulses */ -# endif - uint8_t cpol; /* Channel polarity */ - uint8_t dcpol; /* Disabled channel polarity */ -#endif /* CONFIG_PWM_MULTICHAN */ - - FAR void *arg; /* User provided argument to be used in the - * lower half */ + struct pwm_chan_s channels[PWM_NCHANNELS]; + FAR void *arg; }; /* This structure is a set a callback functions used to call from the upper-