You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/03/06 17:30:09 UTC

[nuttx] branch master updated (b48f9d9b96 -> f97d93903c)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


    from b48f9d9b96 arch/arm: correct ARCH_HAVE_DSP to ARM_HAVE_DSP
     new 88f3d89920 pwm: add configuration option for dead time generators
     new f97d93903c samv7: add support for dead time delay to PWM driver

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/samv7/Kconfig   |   1 +
 arch/arm/src/samv7/sam_pwm.c | 105 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/timers/Kconfig       |  18 ++++++++
 include/nuttx/timers/pwm.h   |   8 ++++
 4 files changed, 131 insertions(+), 1 deletion(-)


[nuttx] 01/02: pwm: add configuration option for dead time generators

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 88f3d89920d311d3092511cada54ce281782c62c
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Mon Mar 6 12:41:11 2023 +0100

    pwm: add configuration option for dead time generators
    
    PWM drivers usually supports dead time generators that automatically
    insert output activation delay for complementary PWM outputs. This
    is usefull for some control purposes as control of H bridge for example.
    
    This commit adds an application to driver interface that can be used
    to set up those delays (if supported by the selected architecture)
    directly from the application. The set up remains the same as for duty
    cycle value.
    
    The whole addition is by default disabled. It can be enabled by config
    option PWM_DEADTIME.
    
    Signed-off-by: Michal Lenc <mi...@seznam.cz>
---
 drivers/timers/Kconfig     | 18 ++++++++++++++++++
 include/nuttx/timers/pwm.h |  8 ++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig
index d64889c2f7..155202cada 100644
--- a/drivers/timers/Kconfig
+++ b/drivers/timers/Kconfig
@@ -13,6 +13,10 @@ config ARCH_HAVE_PWM_OVERWRITE
 	bool
 	default n
 
+config ARCH_HAVE_PWM_DEADTIME
+	bool
+	default n
+
 config ARCH_HAVE_PWM_MULTICHAN
 	bool
 	default n
@@ -46,6 +50,20 @@ config PWM_OVERWRITE
 		controlled from an application level the same way duty cycle or
 		frequency is modified.
 
+config PWM_DEADTIME
+	bool "PWM Deadtime Support"
+	default n
+	depends on ARCH_HAVE_PWM_DEADTIME
+	---help---
+		Some hardware will support deadtime generators that automatically
+		insert output activation delay for complementary PWM outputs. This
+		is usefull for H-bridge motor control for example. The deadtime
+		values are set from application level via the same IOCTL that sets
+		up duty cycle and frequency.
+
+		For detailed description about deadtime functionality please refer
+		to architecture manuals and datasheets.
+
 config PWM_MULTICHAN
 	bool "PWM Multiple Output Channel Support"
 	default n
diff --git a/include/nuttx/timers/pwm.h b/include/nuttx/timers/pwm.h
index c5af6e3c00..e560117b31 100644
--- a/include/nuttx/timers/pwm.h
+++ b/include/nuttx/timers/pwm.h
@@ -123,6 +123,10 @@ struct pwm_chan_s
 #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;
 #endif
   int8_t channel;
 };
@@ -143,6 +147,10 @@ struct pwm_info_s
   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 */


[nuttx] 02/02: samv7: add support for dead time delay to PWM driver

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit f97d93903c6ddd5afc90159b70ba9780c076cbbd
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Mon Mar 6 12:43:38 2023 +0100

    samv7: add support for dead time delay to PWM driver
    
    This commit adds support for dead time delay to SAMv7 PWM driver. The
    dead time can be used to delay an active PWM output at the begining
    of the period. This can be used for H bridge control for example.
    
    The values are to be set from the application level. It is required
    to allow config option PWM_DEADTIME in order to support dead time delay.
    
    Signed-off-by: Michal Lenc <mi...@seznam.cz>
---
 arch/arm/src/samv7/Kconfig   |   1 +
 arch/arm/src/samv7/sam_pwm.c | 105 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig
index 85019d244c..80bc5fae2b 100644
--- a/arch/arm/src/samv7/Kconfig
+++ b/arch/arm/src/samv7/Kconfig
@@ -314,6 +314,7 @@ config SAMV7_PWM
 	default n
 	select ARCH_HAVE_PWM_MULTICHAN
 	select ARCH_HAVE_PWM_OVERWRITE
+	select ARCH_HAVE_PWM_DEADTIME
 
 config SAMV7_HAVE_SDRAMC
 	bool
diff --git a/arch/arm/src/samv7/sam_pwm.c b/arch/arm/src/samv7/sam_pwm.c
index b59b545e76..cd08629fe9 100644
--- a/arch/arm/src/samv7/sam_pwm.c
+++ b/arch/arm/src/samv7/sam_pwm.c
@@ -326,6 +326,11 @@ static void pwm_set_output(struct pwm_lowerhalf_s *dev, uint8_t channel,
 static void pwm_set_freq(struct pwm_lowerhalf_s *dev, uint8_t channel,
                          uint32_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);
+#endif
 
 /****************************************************************************
  * Private Functions
@@ -530,6 +535,90 @@ static void pwm_set_comparison(struct pwm_lowerhalf_s *dev)
     }
 }
 
+/****************************************************************************
+ * Name: pwm_set_deadtime
+ *
+ * Description:
+ *   Set deadtime generator values.
+ *
+ * Input Parameters:
+ *   dev         - A reference to the lower half PWM driver state structure
+ *   channel     - Channel to by updated
+ *   dead_time_a - dead time value for output A
+ *   dead_time_b - dead time value for output B
+ *   duty        - channel duty cycle
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#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)
+{
+  struct sam_pwm_s *priv = (struct sam_pwm_s *)dev;
+  uint16_t period;
+  uint16_t width_1;
+  uint16_t width_2;
+  uint16_t regval;
+
+  /* Get the period value */
+
+  period = pwm_getreg(priv, SAMV7_PWM_CPRDX + (channel * CHANNEL_OFFSET));
+
+  /* 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.
+   *
+   * 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);
+
+  /* It is required width_1 < (CORD - CDTY) and
+   * width_2 < CDTY
+   */
+
+  if (width_1 > (period - regval))
+    {
+      pwmerr("ERROR: Dead Time value DTH has to be < period - duty! " \
+             "Setting DTH to 0\n");
+      width_1 = 0;
+    }
+
+  if (width_2 > regval)
+    {
+      pwmerr("ERROR: Dead Time value DTL has to be < duty! " \
+             "Setting DTL to 0\n");
+      width_2 = 0;
+    }
+
+  /* Update dead time value */
+
+  if (pwm_getreg(priv, SAMV7_PWM_SR) & CHID_SEL(1 << channel))
+    {
+      pwm_putreg(priv, SAMV7_PWM_DTUPDX + (channel * CHANNEL_OFFSET),
+                 DTUPD_DTHUPD_SEL(width_1) | DTUPD_DTLUPD_SEL(width_2));
+    }
+  else
+    {
+      pwm_putreg(priv, SAMV7_PWM_DTX + (channel * CHANNEL_OFFSET),
+                 DT_DTH_SEL(width_1) | DT_DTL_SEL(width_2));
+    }
+}
+#endif
+
 /****************************************************************************
  * Name: pwm_setup
  *
@@ -581,7 +670,11 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
 
       channel = priv->channels[i].channel;
 
-      regval = CMR_CPOL | CMR_DPOLI;
+      regval = CMR_DPOLI;
+#ifdef CONFIG_PWM_DEADTIME
+      regval |= CMR_DTE;
+#endif
+
       pwm_putreg(priv, SAMV7_PWM_CMRX + (channel * CHANNEL_OFFSET), regval);
 
       /* Reset duty cycle register */
@@ -713,6 +806,12 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
 
               pwm_set_freq(dev, priv->channels[index - 1].channel,
                            info->frequency);
+#ifdef CONFIG_PWM_DEADTIME
+              pwm_set_deadtime(dev, priv->channels[index - 1].channel,
+                               info->channels[i].dead_time_a,
+                               info->channels[i].dead_time_b,
+                               info->channels[i].duty);
+#endif
               pwm_set_output(dev, priv->channels[index - 1].channel,
                              info->channels[i].duty);
 #ifdef CONFIG_PWM_OVERWRITE
@@ -740,6 +839,10 @@ static int pwm_start(struct pwm_lowerhalf_s *dev,
       /* 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[index - 1].channel,
+                       info->dead_time_a, info->dead_time_b);
+#endif
       pwm_set_output(dev, priv->channels[0].channel, info->duty);
 #endif