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);
-}