You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/12/13 05:42:24 UTC

[4/6] incubator-mynewt-core git commit: update sensor implementation, closer to final cut, still not compiling

update sensor implementation, closer to final cut, still not compiling


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/1fa93e52
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/1fa93e52
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/1fa93e52

Branch: refs/heads/sensors_branch
Commit: 1fa93e5274c9b692537884facfbd4fc3578ebe83
Parents: f449f3d
Author: Sterling Hughes <st...@apache.org>
Authored: Mon Dec 5 19:14:32 2016 -0800
Committer: Sterling Hughes <st...@apache.org>
Committed: Mon Dec 12 21:42:04 2016 -0800

----------------------------------------------------------------------
 hw/sensor/include/sensor/sensor.h | 155 +++++++------
 hw/sensor/src/sensor.c            | 398 +++++++++++++++++++++++++--------
 2 files changed, 394 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fa93e52/hw/sensor/include/sensor/sensor.h
----------------------------------------------------------------------
diff --git a/hw/sensor/include/sensor/sensor.h b/hw/sensor/include/sensor/sensor.h
index d2e0af1..24661fa 100644
--- a/hw/sensor/include/sensor/sensor.h
+++ b/hw/sensor/include/sensor/sensor.h
@@ -26,13 +26,35 @@
 extern "C" {
 #endif
 
-struct sensor_dev;
+
+/**
+ * @{ Sensor Manager API
+ */
+#define SENSOR_MGR_WAKEUP_TICKS (MYNEWT_VAL(SENSOR_MGR_WAKEUP_RATE) * \
+        (OS_TICKS_PER_SEC / 1000))
+
+int sensor_mgr_register(struct sensor *);
+
+typedef int (*sensor_mgr_compare_func_t*)(struct sensor *, void *);
+struct sensor *sensor_mgr_find_next(sensor_mgr_compare_func_t, void *,
+        struct sensor *);
+struct sensor *sensor_mgr_find_next_bytype(sensor_type_t, struct sensor *);
+struct sensor *sensor_mgr_find_next_bydevname(char *, struct sensor *);
+
+/**
+ * }@
+ */
+
+
+/**
+ * @{ Sensor API
+ */
 
 typedef enum {
     /* No sensor type, used for queries */
     SENSOR_TYPE_NONE                 = 0,
-    /* Accellerometer functionality supported */
-    SENSOR_TYPE_ACCELLEROMETER       = (1 << 0),
+    /* Accelerometer functionality supported */
+    SENSOR_TYPE_ACCELEROMETER       = (1 << 0),
     /* Ambient temperature supported */
     SENSOR_TYPE_AMBIENT_TEMPERATURE  = (1 << 1),
     /* Gravity supported */
@@ -41,8 +63,8 @@ typedef enum {
     SENSOR_TYPE_GYROSCOPE            = (1 << 3),
     /* Light supported */
     SENSOR_TYPE_LIGHT                = (1 << 4),
-    /* Linear accelleration supported */
-    SENSOR_TYPE_LINEAR_ACCELLERATION = (1 << 5),
+    /* Linear acceleration supported */
+    SENSOR_TYPE_LINEAR_ACCELERATION = (1 << 5),
     /* Magnetic field supported */
     SENSOR_TYPE_MAGNETIC_FIELD       = (1 << 6),
     /* Orientation sensor supported */
@@ -79,22 +101,31 @@ typedef enum {
 #define SENSOR_LISTENER_TYPE_NOTIFY (0)
 #define SENSOR_LISTENER_TYPE_POLL   (1)
 
-struct sensor_reading {
-    /* The timestamp, in CPU time ticks that the sensor value
-     * was read.
-     */
-    uint32_t sv_ts;
-    /* The value of the sensor, based on the type being read.
-     */
-    void *sv_value;
-};
-
+/**
+ * Opaque 32-bit value, must understand underlying sensor type
+ * format in order to interpret.
+ */
 #define SENSOR_VALUE_TYPE_OPAQUE (0)
+/**
+ * 32-bit signed integer
+ */
 #define SENSOR_VALUE_TYPE_INT32  (1)
+/**
+ * 32-bit floating point
+ */
 #define SENSOR_VALUE_TYPE_FLOAT  (2)
 
+/**
+ * Configuration structure, describing a specific sensor type off of
+ * an existing sensor.
+ */
 struct sensor_cfg {
+    /* The value type for this sensor (e.g. SENSOR_VALUE_TYPE_INT32).
+     * Used to describe the result format for the value corresponding
+     * to a specific sensor type.
+     */
     uint8_t sc_valtype;
+    /* Reserved for future usage */
     uint8_t _reserved[3];
 };
 
@@ -102,33 +133,32 @@ struct sensor_cfg {
  * Callback for handling sensor data, specified in a sensor listener.
  *
  * @param The sensor for which data is being returned
- * @param The sensor listener that's configured to handle this data.
- * @param A single sensor reading
+ * @param The argument provided to sensor_read() function.
+ * @param A single sensor reading for that sensor listener
  *
  * @return 0 on succes, non-zero error code on failure.
  */
-typedef int (*sensor_data_func_t)(struct sensor *,
-        struct sensor_listener *,
-        struct sensor_reading *v);
+typedef int (*sensor_data_func_t)(struct sensor *, void *, void *);
 
 /**
  *
  */
 struct sensor_listener {
-    /* The type of sensor listener, either notification based "tell me
-     * when there is a value," or polled - collect this value for me
-     * every 'n' seconds and notify me.
+    /* The type of sensor data to listen for, this is interpreted as a
+     * mask, and this listener is called for all sensor types on this
+     * sensor that match the mask.
      */
-    uint8_t sl_type;
-    /* Padding */
-    uint8_t _pad1;
-    /* Poll rate in miliseconds. */
-    uint16_t sl_poll_rate_ms;
-    /* The type of sensor data to listen for */
     sensor_type_t sl_sensor_type;
+
     /* Sensor data handler function, called when has data */
     sensor_data_func_t sl_func;
 
+    /* Argument for the sensor listener */
+    void *sl_arg;
+
+    /* Next item in the sensor listener list.  The head of this list is
+     * contained within the sensor object.
+     */
     SLIST_ENTRY(sensor_listener) sl_next;
 };
 
@@ -146,15 +176,22 @@ struct sensor;
 typedef void *(*sensor_get_interface_func_t)(struct sensor *, sensor_type_t);
 
 /**
- * Read a value from a sensor, given a specific sensor type (e.g. SENSOR_TYPE_PROXIMITY).
+ * Read a single value from a sensor, given a specific sensor type
+ * (e.g. SENSOR_TYPE_PROXIMITY).
  *
  * @param The sensor to read from
- * @param The type of sensor value to read
- * @param A pointer to the sensor value to place the returned result into.
+ * @param The type(s) of sensor values to read.  Mask containing that type, provide
+ *        all, to get all values.
+ * @param The function to call with each value read.  If NULL, it calls all
+ *        sensor listeners associated with this function.
+ * @param The argument to pass to the read callback.
+ * @param Timeout.  If block until result, specify OS_TIMEOUT_NEVER, 0 returns
+ *        immediately (no wait.)
  *
  * @return 0 on success, non-zero error code on failure.
  */
-typedef int (*sensor_read_func_t)(struct sensor *, sensor_type_t, void *);
+typedef int (*sensor_read_func_t)(struct sensor *, sensor_data_func_t, void *,
+        uint32_t);
 
 /**
  * Get the configuration of the sensor for the sensor type.  This includes
@@ -174,9 +211,6 @@ struct sensor_driver_funcs {
     sensor_get_config_func_t sd_get_config;
 };
 
-/* XXX: Make me a syscfg */
-#define SENSOR_DEFAULT_POLL_RATE (10 * (OS_TICKS_PER_SEC/1000))
-
 struct sensor {
     /* The OS device this sensor inherits from, this is typically a sensor specific
      * driver.
@@ -187,6 +221,16 @@ struct sensor {
      * that variable.
      */
     sensor_type_t s_types;
+    /**
+     * Poll rate in MS for this sensor.
+     */
+    uint32_t s_poll_rate;
+
+    /**
+     * The next time at which we want to poll data from this sensor
+     */
+    os_time_t s_next_run;
+
     /* Sensor driver specific functions, created by the device registering the sensor.
      */
     const struct sensor_driver_funcs s_funcs;
@@ -197,12 +241,12 @@ struct sensor {
     SLIST_ENTRY(sensor) s_next;
 };
 
-int sensor_init(struct sensor *);
-int sensor_register(struct sensor *);
+
+int sensor_init(struct sensor *, struct os_dev *dev);
 int sensor_lock(struct sensor *);
 void sensor_unlock(struct sensor *);
 int sensor_register_listener(struct sensor *, struct sensor_listener *);
-struct sensor *sensor_find_next(sensor_type_t, struct sensor *);
+int sensor_read(struct sensor *, sensor_type_t, sensor_data_func_t, uint32_t);
 
 
 /**
@@ -222,35 +266,7 @@ sensor_get_config(struct sensor *sensor, sensor_type_t type, struct sensor_confi
 }
 
 /**
- * Read the data for sensor type "type," from the sensor, "sensor" and
- * return the result into the "value" parameter.
- *
- * @param The senssor to read data from
- * @param The type of sensor data to read from the sensor
- * @param The sensor value to place data into.
- *
- * @return 0 on success, non-zero on failure.
- */
-static inline int
-sensor_read(struct sensor *sensor, sensor_type_t type, struct sensor_value *value)
-{
-    int rc;
-
-    rc = sensor_lock(sensor);
-    if (rc != 0) {
-        goto done;
-    }
-
-    rc = sensor->s_funcs.sd_read(sensor, type, value);
-
-    sensor_unlock(sensor);
-
-done:
-    return (rc);
-}
-
-/**
- * Get a more specific interface for this sensor, like accellerometer, or gyro.
+ * Get a more specific interface for this sensor, like accelerometer, or gyro.
  *
  * @param The sensor to get the interface from
  * @param The type of interface to get from this sensor
@@ -276,6 +292,9 @@ done:
     return (rc);
 }
 
+/**
+ * @}
+ */
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fa93e52/hw/sensor/src/sensor.c
----------------------------------------------------------------------
diff --git a/hw/sensor/src/sensor.c b/hw/sensor/src/sensor.c
index 3c219b2..251b171 100644
--- a/hw/sensor/src/sensor.c
+++ b/hw/sensor/src/sensor.c
@@ -24,8 +24,215 @@
 
 struct os_callout sensors_callout;
 
-TAILQ_HEAD(, struct sensor) g_sensor_list =
-    TAILQ_HEAD_INITIALIZER(&g_sensor_list);
+struct {
+    struct os_mutex mgr_lock;
+
+    struct os_callout mgr_poll_callout;
+
+    TAILQ_HEAD(, struct sensor) mgr_sensor_list;
+} sensor_mgr;
+
+static int
+sensor_mgr_lock(void)
+{
+    int rc;
+
+    rc = os_mutex_pend(&sensor_mgr.mgr_lock);
+    if (rc == 0 || rc == OS_NOT_STARTED) {
+        return (0);
+    }
+    return (rc);
+}
+
+static void
+sensor_mgr_unlock(void)
+{
+    (void) os_mutex_release(&sensor_mgr.mgr_lock);
+}
+
+static void
+sensor_mgr_remove(struct sensor *sensor)
+{
+    TAILQ_REMOVE(&sensor_mgr.mgr_sensor_list, sensor, s_next);
+}
+
+static void
+sensor_mgr_insert(struct sensor *sensor)
+{
+    struct sensor *cursor;
+
+    cursor = NULL;
+    TAILQ_FOREACH(cursor, &sensor_mgr.mgr_sensor_list, s_next) {
+        if (cursor->s_next_wakeup == OS_TIMEOUT_NEVER) {
+            break;
+        }
+
+        if (OS_TIME_TICK_LT(sensor->s_next_wakeup, cursor->s_next_wakeup)) {
+            break;
+        }
+    }
+
+    if (cursor) {
+        TAILQ_INSERT_BEFORE(cursor, sensor, s_next);
+    } else {
+        TAILQ_INSERT_TAIL(&sensor_mgr.mgr_sensor_list, s_next);
+    }
+}
+
+static os_time_t
+sensor_mgr_poll_one(struct sensor *sensor, os_time_t now)
+{
+    int rc;
+
+    rc = sensor_lock(sensor);
+    if (rc != 0) {
+        goto err;
+    }
+
+    /* Sensor read results.  Every time a sensor is read, all of its
+     * listeners are called by default.  Specify NULL as a callback,
+     * because we just want to run all the listeners.
+     */
+    sensor_read(sensor, SENSOR_TYPE_ALL, NULL, NULL, OS_TIMEOUT_NEVER);
+
+    /* Remove the sensor from the sensor list for insertion sort. */
+    sensor_mgr_remove(sensor);
+
+    /* Set next wakeup, and insertion sort the sensor back into the
+     * list.
+     */
+    sensor->s_next_run = now + os_time_ms_to_ticks(sensor->s_poll_rate);
+
+    /* Re-insert the sensor manager, with the new wakeup time. */
+    sensor_mgr_insert(sensor);
+
+    /* Unlock the sensor to allow other access */
+    sensor_unlock(sensor);
+
+    return (sensor->s_next_run);
+err:
+    /* Couldn't lock it.  Re-run task and spin until we get result. */
+    return (0);
+}
+
+/**
+ * Event that wakes up the sensor manager, this goes through the sensor
+ * list and polls any active sensors.
+ */
+static void
+sensor_mgr_wakeup_event(struct os_event *ev)
+{
+    struct sensor *cursor;
+    os_time_t now;
+    os_time_t task_next_wakeup;
+    int rc;
+
+    rc = sensor_mgr_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    now = os_time_get();
+    task_next_wakeup = now + SENSOR_MGR_WAKEUP_TICKS;
+
+    TAILQ_FOREACH(cursor, &sensor_mgr.mgr_sensor_list, s_next) {
+        /* Sensors that are not periodic are inserted at the end of the sensor
+         * list.
+         */
+        if (cursor->s_next_run == OS_TIMEOUT_NEVER) {
+            break;
+        }
+
+        /* List is sorted by what runs first.  If we reached the first element that
+         * doesn't run, break out.
+         */
+        if (OS_TIME_TICK_LT(now, cursor->s_next_run)) {
+            break;
+        }
+
+        /* Sensor poll one completes the poll, updates the sensor's "next run,"
+         * and re-inserts it into the list.  It returns the next wakeup time
+         * for this sensor.
+         */
+        next_wakeup = sensor_poll_one(cursor, now);
+
+        /* If the next wakeup time for this sensor is before the task's next
+         * scheduled wakeup, move that forward, so we can collect data from that
+         * sensor
+         */
+        if (task_next_wakeup > next_wakeup) {
+            task_next_wakeup = next_wakeup;
+        }
+    }
+
+    os_callout_reset(&sensor_mgr.mgr_wakeup_callout, task_next_wakeup);
+}
+
+
+
+
+static void
+sensor_mgr_init(void)
+{
+    memset(&sensor_mgr, 0, sizeof(sensor_mgr));
+    TAILQ_INIT(&sensor_mgr.mgr_sensor_list);
+    /**
+     * Initialize sensor polling callout and set it to fire on boot.
+     */
+    os_callout_init(&sensor_mgr.mgr_wakeup_callout, sensor_mgr_evq_get(),
+            sensor_mgr_wakeup_event, NULL);
+    os_callout_reset(&sensor_mgr.mgr_wakeup_callout, 0);
+
+    os_mutex_init(&sensor_mgr.mgr_lock);
+}
+
+
+struct sensor *
+sensor_mgr_find_next(sensor_mgr_compare_func_t compare_func, void *arg,
+        struct sensor *prev_cursor)
+{
+    struct sensor *cursor;
+    int rc;
+
+    cursor = NULL;
+
+    /* Couldn't acquire lock of sensor list, exit */
+    rc = sensor_mgr_lock();
+    if (rc != 0) {
+        goto done;
+    }
+
+    cursor = prev_cursor;
+    if (cursor == NULL) {
+        cursor = TAILQ_FIRST(&g_sensor_list);
+    }
+
+    while (cursor != NULL) {
+        if (compare_func(cursor, arg)) {
+            break;
+        }
+    }
+
+    sensor_mgr_unlock();
+
+done:
+    return (cursor);
+}
+
+
+static int
+sensor_mgr_match_bytype(struct sensor *sensor, void *arg)
+{
+    sensor_type_t *type;
+
+    type = (sensor_type_t *) arg;
+
+    if ((*type & sensor->s_type) != 0) {
+        return (1);
+    } else {
+        return (0);
+    }
+}
 
 /**
  * Find the "next" sensor available for a given sensor type.
@@ -40,25 +247,62 @@ TAILQ_HEAD(, struct sensor) g_sensor_list =
  *         none found.
  */
 struct sensor *
-sensor_find_next(sensor_type_t type, struct sensor *prev_cursor)
+sensor_mgr_find_next_bytype(sensor_type_t type, struct sensor *prev_cursor)
 {
-    struct sensor *cursor;
+    return (sensor_mgr_find_next(sensor_mgr_match_bytype, type, prev_cursor));
+}
 
-    cursor = prev_cursor;
-    if (cursor == NULL) {
-        cursor = TAILQ_FIRST(&g_sensor_list);
-    }
+static int
+sensor_mgr_match_bydevname(struct sensor *sensor, void *arg)
+{
+    char *devname;
 
-    while (cursor != NULL) {
-        if ((cursor->s_type & type) != 0) {
-            return (cursor);
-        }
-        cursor = TAILQ_NEXT(cursor);
+    devname = (char *) arg;
+
+    if (!strcmp(sensor->s_dev->od_name, devname)) {
+        return (1);
     }
 
-    return (NULL);
+    return (0);
 }
 
+
+/**
+ *
+ */
+struct sensor *
+sensor_mgr_find_next_bydevname(char *devname, struct sensor *prev_cursor)
+{
+    return (sensor_mgr_find_next(sensor_mgr_match_bydevname, devname,
+            prev_cursor));
+}
+
+
+/**
+ * Register the sensor with the global sensor list.   This makes the sensor searchable
+ * by other packages, who may want to look it up by type.
+ *
+ * @param The sensor to register
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int
+sensor_mgr_register(struct sensor *sensor)
+{
+    return (0);
+}
+
+
+void
+sensor_pkg_init(void)
+{
+    /* Ensure this is only called by sysinit */
+    SYSINIT_ASSERT_ACTIVE();
+
+    sensor_mgr_init();
+}
+
+
 /**
  * Lock access to the sensor specified by sensor.  Blocks until lock acquired.
  *
@@ -95,12 +339,13 @@ sensor_unlock(struct sensor *sensor)
 /**
  * Initialize a sensor
  *
- * @param sensor The sensor to initialize
+ * @param The sensor to initialize
+ * @param The device to associate with this sensor.
  *
  * @return 0 on success, non-zero error code on failure.
  */
 int
-sensor_init(struct sensor *sensor)
+sensor_init(struct sensor *sensor, struct os_dev *dev)
 {
     memset(sensor, 0, sizeof(*sensor));
 
@@ -108,26 +353,14 @@ sensor_init(struct sensor *sensor)
     if (rc != 0) {
         goto err;
     }
+    sensor->s_dev = dev;
+
     return (0);
 err:
     return (rc);
 }
 
 
-/**
- * Register the sensor with the global sensor list.   This makes the sensor searchable
- * by other packages, who may want to look it up by type.
- *
- * @param The sensor to register
- *
- * @return 0 on success, non-zero error code on failure.
- */
-int
-sensor_register(struct sensor *sensor)
-{
-    return (0);
-}
-
 
 /**
  * Register a sensor listener.  This allows a calling application to receive
@@ -161,80 +394,63 @@ err:
     return (rc);
 }
 
-static os_time_t
-sensor_poll_run(struct sensor *sensor, os_time_t now)
+struct sensor_read_ctx {
+    sensor_data_func_t user_func;
+    void *user_arg;
+};
+
+static int
+sensor_read_data_func(struct sensor *sensor, void *arg, void *data)
 {
     struct sensor_listener *listener;
-    struct sensor_value value;
-    os_time_t next_run;
-    int rc;
-
-    next_run = OS_TIMEOUT_NEVER;
+    struct sensor_read_ctx *ctx;
 
+    /* Notify all listeners first */
     SLIST_FOREACH(listener, &sensor->s_listener_list, sl_next) {
-        if (listener->sl_type == SENSOR_LISTENER_TYPE_NOTIFY) {
-            continue;
-        }
-        if (listener->sl_next_run >= now) {
-            rc |= sensor_read(sensor, type, &value);
-            rc |= listener->sl_func(sensor, listener, value);
-
-            listener->sl_next_run = os_time_get() +
-                os_time_ms_to_ticks(sl->sl_poll_rate_ms);
-            if (listener->sl_next_run < next_run) {
-                next_run = listener->sl_next_run;
-            }
-        }
+        listener->sl_func(sensor, listener->sl_arg, data);
     }
-    sensor->s_next_wakeup = next_run;
 
-    return (next_run);
+    /* Call data function */
+    ctx = (struct sensor_read_ctx *) arg;
+    if (ctx->user_func != NULL) {
+        return (ctx->user_func(sensor, ctx->user_arg, data));
+    } else {
+        return (0);
+    }
 }
 
-
-static void
-sensor_poll_event(struct os_event *ev)
+/**
+ * Read the data for sensor type "type," from the sensor, "sensor" and
+ * return the result into the "value" parameter.
+ *
+ * @param The senssor to read data from
+ * @param The type of sensor data to read from the sensor
+ * @param The callback to call for data returned from that sensor
+ * @param The argument to pass to this callback.
+ * @param Timeout before aborting sensor read
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+sensor_read(struct sensor *sensor, sensor_type_t type,
+        sensor_data_func_t data_func, void *arg, uint32_t timeout)
 {
-    struct sensor *cursor;
-    os_time_t time;
-    os_time_t next_wakeup;
-    os_time_t sensor_task_next_wakeup;
-
-    time = os_time_get();
+    struct sensor_read_ctx src;
+    int rc;
 
-    sensor_next_wakeup = time + SENSOR_DEFAULT_POLL_RATE;
+    rc = sensor_lock(sensor);
+    if (rc != 0) {
+        goto done;
+    }
 
-    TAILQ_FOREACH(cursor, &g_sensor_list, s_next) {
-        if (cursor->s_next_wakeup == OS_TIMEOUT_NEVER) {
-            break;
-        }
+    src.user_func = data_func;
+    src.user_arg = arg;
 
-        /* Sort lowest to highest, so when we encounter a entry in the list
-         * that isn't ready, we can exit.
-         */
-        if (cursor->s_poll_expire < time) {
-            break;
-        }
+    rc = sensor->s_funcs.sd_read(sensor, type, data_func, arg, timeout);
 
-        next_wakeup = sensor_poll_run(cursor, now);
-        if (next_wakeup < sensor_task_next_wakeup) {
-            sensor_task_next_wakeup = next_wakeup;
-        }
-    }
+    sensor_unlock(sensor);
 
-    os_callout_reset(&sensor_callout, sensor_task_next_wakeup);
+done:
+    return (rc);
 }
 
-void
-sensor_pkg_init(void)
-{
-    /* Ensure this is only called by sysinit */
-    SYSINIT_ASSERT_ACTIVE();
-
-    /**
-     * Initialize callout and set it to fire on boot.
-     */
-    os_callout_init(&sensors_callout, sensor_evq_get(), sensors_poll_event,
-            NULL);
-    os_callout_reset(&sensors_callout, 0);
-}