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

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


The following commit(s) were added to refs/heads/master by this push:
     new 095c32b0eb Add a stepper generic upperhalf driver Add a stepper A4988 
lowerhalf driver
095c32b0eb is described below

commit 095c32b0eb98c592f7dbdeb5fa82ddf2cb98d2b9
Author: Philippe Leduc <philippe.le...@mailfence.com>
AuthorDate: Wed Oct 11 09:46:50 2023 +0200

    Add a stepper generic upperhalf driver
    Add a stepper A4988 lowerhalf driver
---
 Kconfig                             |  33 ++++
 drivers/motor/CMakeLists.txt        |   8 +
 drivers/motor/Kconfig               |  20 +++
 drivers/motor/Make.defs             |  11 ++
 drivers/motor/a4988.c               | 310 +++++++++++++++++++++++++++++++++
 drivers/motor/stepper.c             | 337 ++++++++++++++++++++++++++++++++++++
 include/debug.h                     |  18 ++
 include/nuttx/fs/ioctl.h            |   6 +
 include/nuttx/motor/a4988.h         | 101 +++++++++++
 include/nuttx/motor/stepper.h       | 212 +++++++++++++++++++++++
 include/nuttx/motor/stepper_ioctl.h |  40 +++++
 11 files changed, 1096 insertions(+)

diff --git a/Kconfig b/Kconfig
index 6b7d2a47ad..c563b830bd 100644
--- a/Kconfig
+++ b/Kconfig
@@ -2034,6 +2034,39 @@ config DEBUG_MOTOR_INFO
 
 endif # DEBUG_MOTOR
 
+config DEBUG_STEPPER
+       bool "Stepper Motor Debug Features"
+       default n
+       depends on STEPPER
+       ---help---
+               Enable motor debug features.
+
+if DEBUG_STEPPER
+
+config DEBUG_STEPPER_ERROR
+       bool "Stepper Motor Error Output"
+       default n
+       depends on DEBUG_ERROR
+       ---help---
+               Enable motor error output to SYSLOG.
+
+config DEBUG_STEPPER_WARN
+       bool "Stepper Motor Warnings Output"
+       default n
+       depends on DEBUG_WARN
+       ---help---
+               Enable motor warning output to SYSLOG.
+
+config DEBUG_STEPPER_INFO
+       bool "Stepper Motor Informational Output"
+       default n
+       depends on DEBUG_INFO
+       ---help---
+               Enable motor informational output to SYSLOG.
+
+endif # DEBUG_STEPPER
+
+
 config DEBUG_VIDEO
        bool "Video Debug Features"
        default n
diff --git a/drivers/motor/CMakeLists.txt b/drivers/motor/CMakeLists.txt
index affaad616e..b3f58bdbc9 100644
--- a/drivers/motor/CMakeLists.txt
+++ b/drivers/motor/CMakeLists.txt
@@ -24,3 +24,11 @@ endif()
 if(CONFIG_MOTOR_UPPER)
   target_sources(drivers PRIVATE motor.c)
 endif()
+
+if(CONFIG_STEPPER_UPPER)
+  target_sources(drivers PRIVATE stepper.c)
+endif()
+
+if(CONFIG_STEPPER_A4988)
+  target_sources(drivers PRIVATE a4988.c)
+endif()
diff --git a/drivers/motor/Kconfig b/drivers/motor/Kconfig
index 7c220916b4..8cfe8171ea 100644
--- a/drivers/motor/Kconfig
+++ b/drivers/motor/Kconfig
@@ -62,3 +62,23 @@ endif
 source "drivers/motor/foc/Kconfig"
 
 endif # MOTOR
+
+menuconfig STEPPER
+       bool "Stepper control drivers"
+       default n
+
+if STEPPER
+
+config STEPPER_UPPER
+       bool "Stepper Motor Generic upper-half driver"
+       default n
+       ---help---
+               Enables building of a stepper generic upper half driver.
+
+config STEPPER_A4988
+       bool "A4988 Stepper Motor Driver"
+       default n
+       ---help---
+               Enables A4988 stepper driver.
+
+endif # STEPPER
diff --git a/drivers/motor/Make.defs b/drivers/motor/Make.defs
index f109531592..b415e79295 100644
--- a/drivers/motor/Make.defs
+++ b/drivers/motor/Make.defs
@@ -30,6 +30,17 @@ ifeq ($(CONFIG_MOTOR_UPPER),y)
 CSRCS += motor.c
 endif
 
+# Stepper upper half and lower halfs
+
+ifeq ($(CONFIG_STEPPER_UPPER),y)
+CSRCS += stepper.c
+endif
+
+ifeq ($(CONFIG_STEPPER_A4988),y)
+CSRCS += a4988.c
+endif
+
+
 # Include motor drivers in the build
 
 MOTOR_DEPPATH := --dep-path motor
diff --git a/drivers/motor/a4988.c b/drivers/motor/a4988.c
new file mode 100644
index 0000000000..b5a3bbe390
--- /dev/null
+++ b/drivers/motor/a4988.c
@@ -0,0 +1,310 @@
+/****************************************************************************
+ * drivers/motor/a4988.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/motor/a4988.h>
+
+#include <errno.h>
+#include <debug.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct a4988_dev_s
+{
+  FAR struct a4988_ops_s *ops;   /* A4988 ops */
+  int32_t  position;
+  uint8_t  auto_idle;            /* If true, go in idle mode between movement 
*/
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int a4988_setup(FAR struct stepper_lowerhalf_s *dev);
+static int a4988_shutdown(FAR struct stepper_lowerhalf_s *dev);
+static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
+                      FAR struct stepper_job_s const *param);
+static int a4988_state(FAR struct stepper_lowerhalf_s *dev,
+                       FAR struct stepper_state_s *state);
+static int a4988_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault);
+static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle);
+static int a4988_microstepping(FAR struct stepper_lowerhalf_s *dev,
+                               uint16_t resolution);
+static int a4988_ioctl(FAR struct stepper_lowerhalf_s *dev, int cmd,
+                       unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct stepper_ops_s g_a4988_ops =
+{
+  a4988_setup,          /* setup */
+  a4988_shutdown,       /* shutdown */
+  a4988_work,           /* work */
+  a4988_state,          /* state */
+  a4988_clear,          /* clear */
+  a4988_idle,           /* idle */
+  a4988_microstepping,  /* microstepping */
+  a4988_ioctl           /* ioctl */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int a4988_setup(FAR struct stepper_lowerhalf_s *dev)
+{
+  FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
+  priv->ops->idle(false);
+  priv->ops->enable(true);
+
+  return 0;
+}
+
+static int a4988_shutdown(FAR struct stepper_lowerhalf_s *dev)
+{
+  FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
+  priv->ops->idle(true);
+  priv->ops->enable(false);
+
+  return 0;
+}
+
+static int a4988_work(FAR struct stepper_lowerhalf_s *dev,
+                      FAR struct stepper_job_s const *job)
+{
+  FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
+  int delay;
+  int count;
+
+  if (job->steps == 0)
+    {
+      /* Nothing to do */
+
+      return 0;
+    }
+
+  /* Compute delay between pulse */
+
+  delay = USEC_PER_MSEC / job->speed;
+  if (delay < 1)
+    {
+      delay = 1;
+    }
+
+  /* Set direction */
+
+  if (job->steps > 0)
+    {
+      priv->ops->direction(true);
+      count = job->steps;
+    }
+  else
+    {
+      priv->ops->direction(false);
+      count = -job->steps;
+    }
+
+  if (priv->auto_idle)
+    {
+      priv->ops->idle(false);
+      usleep(USEC_PER_MSEC);
+    }
+
+  for (int32_t i = 0; i < count; ++i)
+    {
+      priv->ops->step(true);
+      up_udelay(1);
+      priv->ops->step(false);
+      up_udelay(delay);
+    }
+
+  if (priv->auto_idle)
+    {
+      priv->ops->idle(true);
+    }
+
+  /* Update position */
+
+  priv->position += job->steps;
+
+  return 0;
+}
+
+static int a4988_state(FAR struct stepper_lowerhalf_s *dev,
+                       FAR struct stepper_state_s *state)
+{
+  FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
+  state->position = priv->position;
+
+  return 0;
+}
+
+static int a4988_clear(FAR struct stepper_lowerhalf_s *dev, uint8_t fault)
+{
+  return -ENOSYS;
+}
+
+static int a4988_idle(FAR struct stepper_lowerhalf_s *dev, uint8_t idle)
+{
+  FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
+
+  if (idle == STEPPER_AUTO_IDLE)
+    {
+      priv->auto_idle = true;
+      return 0;
+    }
+
+  priv->auto_idle = false;
+
+  if (idle == STEPPER_ENABLE_IDLE)
+    {
+      priv->ops->idle(true);
+    }
+  else
+    {
+      priv->ops->idle(false);
+      usleep(USEC_PER_MSEC);
+    }
+
+  return 0;
+}
+
+static int a4988_microstepping(FAR struct stepper_lowerhalf_s *dev,
+                               uint16_t resolution)
+{
+  FAR struct a4988_dev_s *priv = (FAR struct a4988_dev_s *)dev->priv;
+
+  switch (resolution)
+    {
+      case 1:
+        {
+          priv->ops->microstepping(false, false, false);
+        }
+        break;
+
+      case 2:
+        {
+          priv->ops->microstepping(true, false, false);
+        }
+        break;
+
+      case 4:
+        {
+          priv->ops->microstepping(false, true, false);
+        }
+        break;
+
+      case 8:
+        {
+          priv->ops->microstepping(true, true, false);
+        }
+        break;
+
+      case 16:
+        {
+          priv->ops->microstepping(true, true, true);
+        }
+        break;
+
+      default:
+        {
+          return -EINVAL;
+        }
+    }
+
+  return 0;
+}
+
+static int a4988_ioctl(FAR struct stepper_lowerhalf_s *dev, int cmd,
+                       unsigned long arg)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int a4988_register(FAR const char *devpath, FAR struct a4988_ops_s *ops)
+{
+  FAR struct a4988_dev_s *priv;
+  FAR struct stepper_lowerhalf_s *lower;
+  int ret = 0;
+
+  /* Sanity check */
+
+  DEBUGASSERT(ops != NULL);
+
+  /* Initialize the a4988 dev structure */
+
+  priv = kmm_malloc(sizeof(struct a4988_dev_s));
+  if (priv == NULL)
+    {
+      stperr("Failed to allocate instance\n");
+      return -ENOMEM;
+    }
+
+  priv->ops = ops;
+  priv->position = 0;
+
+  lower = kmm_malloc(sizeof(struct stepper_lowerhalf_s));
+  if (priv == NULL)
+    {
+      stperr("Failed to allocate instance\n");
+      kmm_free(priv);
+      return -ENOMEM;
+    }
+
+  lower->priv = priv;
+  lower->state.fault = STEPPER_FAULT_CLEAR;
+  lower->state.state = STEPPER_STATE_INIT;
+  lower->state.position = 0;
+  lower->ops = &g_a4988_ops;
+
+  /* Initialize lower layer (only once) */
+
+  priv->ops->initialize();
+
+  /* Register the character driver */
+
+  ret = stepper_register(devpath, lower);
+  if (ret < 0)
+    {
+      stperr("Failed to register driver: %d\n", ret);
+      kmm_free(priv);
+      kmm_free(lower);
+      return ret;
+    }
+
+  stpinfo("a4988 registered at %s\n", devpath);
+  return ret;
+}
diff --git a/drivers/motor/stepper.c b/drivers/motor/stepper.c
new file mode 100644
index 0000000000..f1e64978a7
--- /dev/null
+++ b/drivers/motor/stepper.c
@@ -0,0 +1,337 @@
+/****************************************************************************
+ * drivers/motor/stepper.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* Upper-half, character driver for stepper control */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/motor/stepper.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure describes the state of the upper half driver */
+
+struct stepper_upperhalf_s
+{
+  FAR struct stepper_lowerhalf_s *lower; /* lower half driver */
+  int refs;                              /* Reference count */
+  mutex_t lock;                          /* Only one thread can access at a 
time */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int     stepper_open(FAR struct file *filep);
+static int     stepper_close(FAR struct file *filep);
+static ssize_t stepper_read(FAR struct file *filep, FAR char *buffer,
+                            size_t buflen);
+static ssize_t stepper_write(FAR struct file *filep, FAR const char *buffer,
+                             size_t buflen);
+static int     stepper_ioctl(FAR struct file *filep, int cmd,
+                             unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_stepper_fops =
+{
+  stepper_open,   /* open */
+  stepper_close,  /* close */
+  stepper_read,   /* read */
+  stepper_write,  /* write */
+  NULL,           /* seek */
+  stepper_ioctl,  /* ioctl */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stepper_open
+ *
+ * Description:
+ *   This function is called whenever the stepper device is opened.
+ *
+ ****************************************************************************/
+
+static int stepper_open(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct stepper_upperhalf_s *stepper = inode->i_private;
+  FAR struct stepper_lowerhalf_s *lower = stepper->lower;
+  int ret;
+
+  ret = nxmutex_lock(&stepper->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Increment the count of references to the device.  If this the first
+   * time that the driver has been opened for this device, then
+   * initialize the device.
+   */
+
+  stepper->refs++;
+  if (stepper->refs == 1)
+    {
+      ret = lower->ops->setup(lower);
+      if (ret < 0)
+        {
+          stepper->refs--;  /* Something bad happened: open failure */
+        }
+    }
+
+  nxmutex_unlock(&stepper->lock);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: stepper_close
+ *
+ * Description:
+ *   This routine is called when the stepper device is closed.
+ *
+ ****************************************************************************/
+
+static int stepper_close(FAR struct file *filep)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct stepper_upperhalf_s *stepper = inode->i_private;
+  FAR struct stepper_lowerhalf_s *lower = stepper->lower;
+  int ret;
+
+  ret = nxmutex_lock(&stepper->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Decrement the references to the driver.  If the reference count will
+   * decrement to 0, then uninitialize the driver.
+   */
+
+  stepper->refs--;
+  if (stepper->refs == 0)
+    {
+      ret = lower->ops->shutdown(lower); /* Disable the stepper */
+    }
+
+  nxmutex_unlock(&stepper->lock);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: stepper_read
+ ****************************************************************************/
+
+static ssize_t stepper_read(FAR struct file *filep, FAR char *buffer,
+                            size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct stepper_upperhalf_s *stepper = inode->i_private;
+  FAR struct stepper_lowerhalf_s *lower = stepper->lower;
+  FAR struct stepper_state_s *state;
+  int ret;
+
+  if (buflen != sizeof(struct stepper_state_s))
+    {
+      return -EINVAL;
+    }
+
+  state = (FAR struct stepper_state_s *)buffer;
+  ret = lower->ops->state(lower, state);
+  if (ret < 0)
+    {
+      stperr("Get stepper state failed: %d\n", ret);
+      return ret;
+    }
+
+  return sizeof(struct stepper_state_s);
+}
+
+/****************************************************************************
+ * Name: stepper_write
+ ****************************************************************************/
+
+static ssize_t stepper_write(FAR struct file *filep, FAR const char *buffer,
+                             size_t buflen)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct stepper_upperhalf_s *stepper = inode->i_private;
+  FAR struct stepper_lowerhalf_s *lower = stepper->lower;
+  FAR struct stepper_job_s const *job;
+  int ret;
+
+  if (buflen != sizeof(struct stepper_job_s))
+    {
+      return -EINVAL;
+    }
+
+  job = (FAR struct stepper_job_s const *)buffer;
+  ret = lower->ops->work(lower, job);
+  if (ret < 0)
+    {
+      stperr("Stepper work failed: %d\n", ret);
+      return ret;
+    }
+
+  return sizeof(struct stepper_job_s);
+}
+
+/****************************************************************************
+ * Name: stepper_ioctl
+ ****************************************************************************/
+
+static int stepper_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct stepper_upperhalf_s *stepper = inode->i_private;
+  FAR struct stepper_lowerhalf_s *lower = stepper->lower;
+  int ret = 0;
+
+  switch (cmd)
+    {
+      case STEPIOC_IDLE:
+        {
+          uint8_t idle = (uint8_t)arg;
+
+          ret = lower->ops->idle(lower, idle);
+          if (ret < 0)
+            {
+              stperr("STEPIOC_IDLE failed: %d\n", ret);
+            }
+        }
+        break;
+
+      case STEPIOC_CLEAR_FAULT:
+        {
+          uint8_t fault = (uint8_t)arg;
+
+          ret = lower->ops->clear(lower, fault);
+          if (ret < 0)
+            {
+              stperr("STEPIOC_CLEAR_FAULT failed: %d\n", ret);
+            }
+        }
+        break;
+
+      case STEPIOC_MICROSTEPPING:
+        {
+          uint16_t resolution = (uint16_t)arg;
+
+          ret = lower->ops->microstepping(lower, resolution);
+        }
+        break;
+
+      default:
+        {
+          ret = lower->ops->ioctl(lower, cmd, arg);
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stepper_register
+ *
+ * Description:
+ *   This function binds an instance of a "lower half" stepper driver with
+ *   the "upper half" stepper device and registers that device so that can
+ *   be used by application code.
+ *
+ *   We will register the character device with specified path.
+ *
+ * Input Parameters:
+ *   path  - The user specifies path name.
+ *   lower - A pointer to an instance of lower half stepper driver. This
+ *           instance is bound to the stepper driver and must persists
+ *           as long as the driver persists.
+ *
+ * Returned Value:
+ *   OK if the driver was successfully register; A negated errno value is
+ *   returned on any failure.
+ *
+ ****************************************************************************/
+
+int stepper_register(FAR const char *path,
+                     FAR struct stepper_lowerhalf_s *lower)
+{
+  FAR struct stepper_upperhalf_s *stepper;
+  int ret = 0;
+
+  /* Sanity check */
+
+  DEBUGASSERT(lower != NULL);
+
+  /* Initialize the upper-half data structure */
+
+  stepper = kmm_zalloc(sizeof(struct stepper_upperhalf_s));
+  if (stepper == NULL)
+    {
+      stperr("ERROR: Failed to allocate instance\n");
+      return -ENOMEM;
+    }
+
+  /* Initialize mutex */
+
+  nxmutex_init(&stepper->lock);
+
+  /* Connect stepper driver with lower level interface */
+
+  stepper->lower = lower;
+  stepper->refs = 0;
+
+  /* Register the stepper character driver */
+
+  ret = register_driver(path, &g_stepper_fops, 0666, stepper);
+  if (ret < 0)
+    {
+      nxmutex_destroy(&stepper->lock);
+      kmm_free(stepper);
+    }
+
+  return ret;
+}
diff --git a/include/debug.h b/include/debug.h
index 5b5cf4ddef..e6b9163cd7 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -830,6 +830,24 @@
 #  define mtrinfo     _none
 #endif
 
+#ifdef CONFIG_DEBUG_STEPPER_ERROR
+#  define stperr      _err
+#else
+#  define stperr      _none
+#endif
+
+#ifdef CONFIG_DEBUG_STEPPER_WARN
+#  define stpwarn     _warn
+#else
+#  define stpwarn     _none
+#endif
+
+#ifdef CONFIG_DEBUG_STEPPER_INFO
+#  define stpinfo     _info
+#else
+#  define stpinfo     _none
+#endif
+
 #ifdef CONFIG_DEBUG_VIDEO_ERROR
 #  define verr        _err
 #else
diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h
index 210f56e2a2..b4aaca0b26 100644
--- a/include/nuttx/fs/ioctl.h
+++ b/include/nuttx/fs/ioctl.h
@@ -98,6 +98,7 @@
 #define _MIPIDSIBASE    (0x3900) /* Mipidsi device ioctl commands */
 #define _SEIOCBASE      (0x3a00) /* Secure element ioctl commands */
 #define _SYSLOGBASE     (0x3c00) /* Syslog device ioctl commands */
+#define _STEPIOBASE     (0x3d00) /* Stepper device ioctl commands */
 #define _WLIOCBASE      (0x8b00) /* Wireless modules ioctl network commands */
 
 /* boardctl() commands share the same number space */
@@ -612,6 +613,11 @@
 #define _MTRIOCVALID(c)     (_IOC_TYPE(c) == _MTRIOBASE)
 #define _MTRIOC(nr)         _IOC(_MTRIOBASE, nr)
 
+/* Stepper drivers **********************************************************/
+
+#define _STEPIOCVALID(c)    (_IOC_TYPE(c) == _STEPIOBASE)
+#define _STEPIOC(nr)        _IOC(_STEPIOBASE, nr)
+
 /* MATH drivers *************************************************************/
 
 #define _MATHIOCVALID(c)    (_IOC_TYPE(c) == _MATHIOBASE)
diff --git a/include/nuttx/motor/a4988.h b/include/nuttx/motor/a4988.h
new file mode 100644
index 0000000000..aee48c6bcc
--- /dev/null
+++ b/include/nuttx/motor/a4988.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ * include/nuttx/motor/a4988.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_MOTOR_A4988_H
+#define __INCLUDE_NUTTX_MOTOR_A4988_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/motor/stepper.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_STEPPER_A4988)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct a4988_ops_s
+{
+  /* Initialize the control, called at register step */
+
+  CODE void (*initialize)(void);
+
+  /* Control step output */
+
+  CODE void (*step)(int level);
+
+  /* Direction */
+
+  CODE void (*direction)(int level);
+
+  /* Configure microstepping */
+
+  CODE void (*microstepping)(int ms1, int ms2, int ms3);
+
+  /* Enable control */
+
+  CODE void (*enable)(int level);
+
+  /* Idle control */
+
+  CODE void (*idle)(int level);
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: a4988_register
+ *
+ * Description:
+ *  Register the a4988 character device as 'devpath'
+ *
+ * Input Parameters:
+ *  devpath - The full path to the driver to register. E.g., "/dev/pwrmntr0"
+ * Returned Value:
+ *  ops - operations on the concrete hardware
+ *  Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int a4988_register(FAR const char *devpath, FAR struct a4988_ops_s *ops);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_STEPPER_A4988 */
+#endif /* __INCLUDE_NUTTX_DRIVERS_MOTOR_A4988_H */
diff --git a/include/nuttx/motor/stepper.h b/include/nuttx/motor/stepper.h
new file mode 100644
index 0000000000..1577c33e01
--- /dev/null
+++ b/include/nuttx/motor/stepper.h
@@ -0,0 +1,212 @@
+/*****************************************************************************
+ * include/nuttx/motor/stepper.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ *****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_MOTOR_STEPPER_H
+#define __INCLUDE_NUTTX_MOTOR_STEPPER_H
+
+/* The motor driver is split into two parts:
+ *
+ * 1) An "upper half", generic driver that provides the common motor
+ *    interface to application level code, and
+ * 2) A "lower half", platform-specific driver that implements the low-level
+ *    functionality eg.:
+ *      - timer controls to implement the PWM signals,
+ *      - analog peripherals configuration such as ADC, DAC and comparators,
+ *      - control algorithm for motor driver (eg. FOC control for BLDC)
+ *
+ * This 'upper-half' driver has been designed with flexibility in mind
+ * to support all kinds of electric motors and their applications.
+ */
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+#include <stdint.h>
+
+#include <nuttx/motor/stepper_ioctl.h>
+
+#ifdef CONFIG_STEPPER_UPPER
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Types
+ *****************************************************************************/
+
+/* Stepper driver state */
+
+enum stepper_state_e
+{
+  STEPPER_STATE_INIT     = 0,     /* Initial state */
+  STEPPER_STATE_IDLE     = 1,     /* IDLE state */
+  STEPPER_STATE_RUN      = 2,     /* Run state */
+  STEPPER_STATE_FAULT    = 3      /* Fault state */
+};
+
+/* Stepper driver fault type */
+
+enum stepper_fault_e
+{
+  STEPPER_FAULT_CLEAR        = 0,         /* No fault */
+  STEPPER_FAULT_OVERCURRENT  = (1 << 0),  /* Over-current Fault */
+  STEPPER_FAULT_OVERVOLTAGE  = (1 << 1),  /* Over-voltage Fault */
+  STEPPER_FAULT_OVERPOWER    = (1 << 2),  /* Over-power Fault (electrical) */
+  STEPPER_FAULT_OVERTEMP     = (1 << 3),  /* Over-temperature Fault */
+  STEPPER_FAULT_OVERLOAD     = (1 << 4),  /* Stepper overload Fault 
(mechanical) */
+  STEPPER_FAULT_LOCKED       = (1 << 5),  /* Stepper locked Fault */
+  STEPPER_FAULT_INVAL_PARAM  = (1 << 6),  /* Invalid parameter Fault */
+  STEPPER_FAULT_OTHER        = (1 << 7)   /* Other Fault */
+};
+
+/* Stepper IDLE control */
+
+enum stepper_idle_e
+{
+  STEPPER_ENABLE_IDLE  = 0,  /* Enable IDLE mode */
+  STEPPER_DISABLE_IDLE = 1,  /* Disable IDLE mode */
+  STEPPER_AUTO_IDLE    = 2,  /* Set automaticaly IDLE when stepper not in 
movement */
+};
+
+/* Stepper driver state */
+
+struct stepper_state_s
+{
+  uint8_t state;      /* Stepper driver state  */
+  uint8_t fault;      /* Stepper driver faults */
+  int32_t position;   /* Feedback from motor - absolute position */
+};
+
+/* Stepper parameters. */
+
+struct stepper_job_s
+{
+  int32_t   steps;     /* Steps to do. Position: CW, Negative: CCW */
+  uint16_t  speed;     /* Stepper speed in step/ms */
+};
+
+/* Stepper operations used to call from the upper-half, generic stepper driver
+ * into lower-half, platform-specific logic.
+ */
+
+struct stepper_lowerhalf_s;
+struct stepper_ops_s
+{
+  /* Setup stepper for operational mode */
+
+  CODE int (*setup)(FAR struct stepper_lowerhalf_s *dev);
+
+  /* Disable stepper */
+
+  CODE int (*shutdown)(FAR struct stepper_lowerhalf_s *dev);
+
+  /* work */
+
+  CODE int (*work)(FAR struct stepper_lowerhalf_s *dev,
+                   FAR struct stepper_job_s const *param);
+
+  /* Get motor state  */
+
+  CODE int (*state)(FAR struct stepper_lowerhalf_s *dev,
+                    FAR struct stepper_state_s *state);
+
+  /* Clear fault state */
+
+  CODE int (*clear)(FAR struct stepper_lowerhalf_s *dev, uint8_t fault);
+
+  /* Configure IDLE mode */
+
+  CODE int (*idle)(FAR struct stepper_lowerhalf_s *dev, uint8_t idle);
+
+  /* Configure stepping resolution mode */
+
+  CODE int (*microstepping)(FAR struct stepper_lowerhalf_s *dev,
+                            uint16_t resolution);
+
+  /* Lower-half logic may support platform-specific ioctl commands */
+
+  CODE int (*ioctl)(FAR struct stepper_lowerhalf_s *dev, int cmd,
+                    unsigned long arg);
+};
+
+/* This structure is the generic form of state structure used by lower half
+ * motor driver.
+ */
+
+struct stepper_lowerhalf_s
+{
+  FAR const struct stepper_ops_s *ops; /* Arch-specific operations */
+  struct stepper_job_s      param;     /* Motor settings */
+  struct stepper_state_s    state;     /* Motor state */
+  FAR void                  *priv;     /* Private data */
+};
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Function Prototypes
+ *****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/*****************************************************************************
+ * Name: stepper_register
+ *
+ * Description:
+ *   This function binds an instance of a "lower half" stepper driver with the
+ *   "upper half" stepper device and registers that device so that can be used
+ *   by application code.
+ *
+ *   We will register the character device with specified path.
+ *
+ * Input Parameters:
+ *   path  - The user specifies path name.
+ *   lower - A pointer to an instance of lower half stepper driver. This
+ *           instance is bound to the stepper driver and must persists as long
+ *           as the driver persists.
+ *
+ * Returned Value:
+ *   OK if the driver was successfully register; A negated errno value is
+ *   returned on any failure.
+ *
+ *****************************************************************************/
+
+int stepper_register(FAR const char *path,
+                     FAR struct stepper_lowerhalf_s *lower);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_STEPPER_UPPER */
+#endif /* __INCLUDE_NUTTX_DRIVERS_MOTOR_STEPPER_H */
diff --git a/include/nuttx/motor/stepper_ioctl.h 
b/include/nuttx/motor/stepper_ioctl.h
new file mode 100644
index 0000000000..dc20f65866
--- /dev/null
+++ b/include/nuttx/motor/stepper_ioctl.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+ * include/nuttx/motor/stepper_ioctl.h
+ * NuttX Motor-Related IOCTLs definitions
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_MOTOR_STEPPER_IOCTL_H
+#define __INCLUDE_NUTTX_MOTOR_STEPPER_IOCTL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/fs/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define STEPIOC_IDLE          _STEPIOC(1)
+#define STEPIOC_CLEAR_FAULT   _STEPIOC(2)
+#define STEPIOC_MICROSTEPPING _STEPIOC(3)
+
+#endif /* __INCLUDE_NUTTX_MOTOR_STEPPER_IOCTL_H */


Reply via email to