summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/motion_sense.c136
-rw-r--r--driver/als_si114x.c2
-rw-r--r--include/motion_sense.h16
-rw-r--r--include/timer.h29
-rw-r--r--test/motion_angle.c2
-rw-r--r--test/motion_angle_tablet.c2
-rw-r--r--test/motion_common.h1
-rw-r--r--test/motion_lid.c3
8 files changed, 101 insertions, 90 deletions
diff --git a/common/motion_sense.c b/common/motion_sense.c
index 4b4d996cc2..3ab78cf7b4 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -45,13 +45,8 @@ const intv3_t orientation_modes[] = {
};
#endif
-/*
- * Sampling interval for measuring acceleration and calculating lid angle.
- */
-test_export_static unsigned int motion_interval;
-
/* Delay between FIFO interruption. */
-static unsigned int motion_int_interval;
+static unsigned int ap_event_interval;
/* Minimum time in between running motion sense task loop. */
unsigned int motion_min_interval = CONFIG_MOTION_MIN_SENSE_WAIT_TIME * MSEC;
@@ -212,22 +207,19 @@ static inline int motion_sensor_in_forced_mode(
#endif
}
-
-
/* Minimal amount of time since last collection before triggering a new one */
static inline int motion_sensor_time_to_read(const timestamp_t *ts,
const struct motion_sensor_t *sensor)
{
- int rate_mhz = sensor->drv->get_data_rate(sensor);
-
- if (rate_mhz == 0)
+ if (sensor->collection_rate == 0)
return 0;
+
/*
- * converting from mHz to us.
- * If within 95% of the time, check sensor.
+ * If the time is within the min motion interval (3 ms) go ahead and
+ * read from the sensor
*/
return time_after(ts->le.lo,
- sensor->last_collection + SECOND * 950 / rate_mhz);
+ sensor->next_collection - motion_min_interval);
}
static enum sensor_config motion_sense_get_ec_config(void)
@@ -301,7 +293,9 @@ int motion_sense_set_data_rate(struct motion_sensor_t *sensor)
* Reset last collection: the last collection may be so much in the past
* it may appear to be in the future.
*/
- sensor->last_collection = ts.le.lo;
+ odr = sensor->drv->get_data_rate(sensor);
+ sensor->collection_rate = odr > 0 ? SECOND * 1000 / odr : 0;
+ sensor->next_collection = ts.le.lo + sensor->collection_rate;
sensor->oversampling = 0;
mutex_unlock(&g_sensor_mutex);
return 0;
@@ -407,9 +401,9 @@ static int motion_sense_ec_rate(struct motion_sensor_t *sensor)
*
* Note: Not static to be tested.
*/
-static int motion_sense_set_motion_intervals(void)
+static void motion_sense_set_motion_intervals(void)
{
- int i, sensor_ec_rate, ec_rate = 0, ec_int_rate = 0;
+ int i, sensor_ec_rate, ec_int_rate = 0;
struct motion_sensor_t *sensor;
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
@@ -420,28 +414,20 @@ static int motion_sense_set_motion_intervals(void)
(sensor->drv->get_data_rate(sensor) == 0))
continue;
- sensor_ec_rate = motion_sense_ec_rate(sensor);
- if (sensor_ec_rate == 0)
- continue;
- if (ec_rate == 0 || sensor_ec_rate < ec_rate)
- ec_rate = sensor_ec_rate;
-
sensor_ec_rate = motion_sense_select_ec_rate(
sensor, SENSOR_CONFIG_AP, 1);
if (ec_int_rate == 0 ||
(sensor_ec_rate && sensor_ec_rate < ec_int_rate))
ec_int_rate = sensor_ec_rate;
}
- motion_interval = ec_rate;
- motion_int_interval =
+ ap_event_interval =
MAX(0, ec_int_rate - MOTION_SENSOR_INT_ADJUSTMENT_US);
/*
* Wake up the motion sense task: we want to sensor task to take
* in account the new period right away.
*/
task_wake(TASK_ID_MOTIONSENSE);
- return motion_interval;
}
static inline int motion_sense_init(struct motion_sensor_t *sensor)
@@ -717,6 +703,28 @@ static int motion_sense_read(struct motion_sensor_t *sensor)
return sensor->drv->read(sensor, sensor->raw_xyz);
}
+
+static inline void increment_sensor_collection(struct motion_sensor_t *sensor,
+ const timestamp_t *ts)
+{
+ sensor->next_collection += sensor->collection_rate;
+
+ while (time_after(ts->le.lo, sensor->next_collection)) {
+ /*
+ * If we get here it means that we completely missed a sensor
+ * collection time and we attempt to recover by incrementing
+ * the next collection time until we recover. This should not
+ * happen and if it does it means that the ec cannot handle the
+ * requested data rate.
+ */
+
+ CPRINTS("%s Missed data collection at %u - rate: %d",
+ sensor->name, sensor->next_collection,
+ sensor->collection_rate);
+ sensor->next_collection += sensor->collection_rate;
+ }
+}
+
static int motion_sense_process(struct motion_sensor_t *sensor,
uint32_t *event,
const timestamp_t *ts)
@@ -759,7 +767,7 @@ static int motion_sense_process(struct motion_sensor_t *sensor,
motion_sense_fifo_add_data(&vector, sensor, 3,
__hw_clock_source_read());
}
- sensor->last_collection = ts->le.lo;
+ increment_sensor_collection(sensor, ts);
} else {
ret = EC_ERROR_BUSY;
}
@@ -777,7 +785,7 @@ static int motion_sense_process(struct motion_sensor_t *sensor,
if (motion_sensor_time_to_read(ts, sensor)) {
/* Get latest data for local calculation */
ret = motion_sense_read(sensor);
- sensor->last_collection = ts->le.lo;
+ increment_sensor_collection(sensor, ts);
} else {
ret = EC_ERROR_BUSY;
}
@@ -925,6 +933,7 @@ void motion_sense_task(void *u)
{
int i, ret, wait_us;
timestamp_t ts_begin_task, ts_end_task;
+ int32_t time_diff;
uint32_t event = 0;
uint16_t ready_status;
struct motion_sensor_t *sensor;
@@ -998,7 +1007,6 @@ void motion_sense_task(void *u)
update_sense_data(lpc_status, &sample_id);
#endif
- ts_end_task = get_time();
#ifdef CONFIG_ACCEL_FIFO
/*
* Ask the host to flush the queue if
@@ -1010,13 +1018,13 @@ void motion_sense_task(void *u)
event & (TASK_EVENT_MOTION_ODR_CHANGE |
TASK_EVENT_MOTION_FLUSH_PENDING) ||
queue_space(&motion_sense_fifo) < CONFIG_ACCEL_FIFO_THRES ||
- (motion_int_interval > 0 &&
- time_after(ts_end_task.le.lo,
- ts_last_int.le.lo + motion_int_interval))) {
+ (ap_event_interval > 0 &&
+ time_after(ts_begin_task.le.lo,
+ ts_last_int.le.lo + ap_event_interval))) {
if ((event & TASK_EVENT_MOTION_FLUSH_PENDING) == 0)
motion_sense_insert_timestamp(
__hw_clock_source_read());
- ts_last_int = ts_end_task;
+ ts_last_int = ts_begin_task;
/*
* Count the number of event the AP is allowed to
* collect.
@@ -1040,25 +1048,36 @@ void motion_sense_task(void *u)
#endif
}
#endif
- if (motion_interval > 0) {
- /*
- * Delay appropriately to keep sampling time
- * consistent.
- */
- wait_us = motion_interval -
- (ts_end_task.val - ts_begin_task.val);
- /* and it cannnot be negative */
- wait_us = MAX(wait_us, 0);
+ ts_end_task = get_time();
+ wait_us = -1;
+
+ for (i = 0; i < motion_sensor_count; i++) {
+ struct motion_sensor_t *sensor = &motion_sensors[i];
+
+ if (!motion_sensor_in_forced_mode(sensor) ||
+ sensor->collection_rate == 0)
+ continue;
+
+ time_diff = time_until(ts_end_task.le.lo,
+ sensor->next_collection);
+ /* We missed our collection time so wake soon */
+ if (time_diff <= 0) {
+ wait_us = 0;
+ break;
+ }
+
+ if (wait_us == -1 || wait_us > time_diff)
+ wait_us = time_diff;
+ }
+
+ if (wait_us >= 0 && wait_us < motion_min_interval) {
/*
- * Guarantee some minimum delay to allow other lower
- * priority tasks to run.
- */
- if (wait_us < motion_min_interval)
- wait_us = motion_min_interval;
- } else {
- wait_us = -1;
+ * Guarantee some minimum delay to allow other lower
+ * priority tasks to run.
+ */
+ wait_us = motion_min_interval;
}
event = task_wait_event(wait_us);
@@ -1666,8 +1685,7 @@ static int command_accel_data_rate(int argc, char **argv)
sensor->drv->get_data_rate(sensor));
ccprintf("EC rate for sensor %d: %d\n", id,
motion_sense_ec_rate(sensor));
- ccprintf("Current EC rate: %d\n", motion_interval);
- ccprintf("Current Interrupt rate: %d\n", motion_int_interval);
+ ccprintf("Current Interrupt rate: %d\n", ap_event_interval);
}
return EC_SUCCESS;
@@ -1743,7 +1761,6 @@ DECLARE_CONSOLE_COMMAND(accelinit, command_accel_init,
#ifdef CONFIG_CMD_ACCEL_INFO
static int command_display_accel_info(int argc, char **argv)
{
- char *e;
int val, i, j;
if (argc > 3)
@@ -1780,21 +1797,6 @@ static int command_display_accel_info(int argc, char **argv)
accel_disp = val;
}
- /*
- * Second arg changes the accel task time interval. Note accel
- * sampling interval will be clobbered when chipset suspends or
- * resumes.
- */
- if (argc > 2) {
- val = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- motion_interval = val * MSEC;
- task_wake(TASK_ID_MOTIONSENSE);
-
- }
-
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(accelinfo, command_display_accel_info,
diff --git a/driver/als_si114x.c b/driver/als_si114x.c
index 17f178080f..be3f090db3 100644
--- a/driver/als_si114x.c
+++ b/driver/als_si114x.c
@@ -295,6 +295,7 @@ static int read(const struct motion_sensor_t *s, intv3_t v)
case SI114X_NOT_READY:
ret = EC_ERROR_NOT_POWERED;
}
+#if 0 /* This code is incorrect https://crbug.com/956569 */
if (ret == EC_ERROR_ACCESS_DENIED &&
s->type == MOTIONSENSE_TYPE_LIGHT) {
timestamp_t ts_now = get_time();
@@ -315,6 +316,7 @@ static int read(const struct motion_sensor_t *s, intv3_t v)
init(s);
}
}
+#endif
return ret;
}
diff --git a/include/motion_sense.h b/include/motion_sense.h
index cebd7907a7..b5fc36dfe4 100644
--- a/include/motion_sense.h
+++ b/include/motion_sense.h
@@ -180,13 +180,17 @@ struct motion_sensor_t {
uint16_t lost;
/*
- * Time since last collection:
- * For sensor with hardware FIFO, time since last sample
- * has move from the hardware FIFO to the FIFO (used if fifo rate != 0).
- * For sensor without FIFO, time since the last event was collect
- * from sensor registers.
+ * For sensors in forced mode the ideal time to collect the next
+ * measurement.
+ *
+ * This is unused with sensors that interrupt the ec like hw fifo chips.
+ */
+ uint32_t next_collection;
+
+ /*
+ * The time in us between collection measurements
*/
- uint32_t last_collection;
+ uint32_t collection_rate;
/* Minimum supported sampling frequency in miliHertz for this sensor */
uint32_t min_frequency;
diff --git a/include/timer.h b/include/timer.h
index 02a50070c1..47fbe7a4bd 100644
--- a/include/timer.h
+++ b/include/timer.h
@@ -134,6 +134,23 @@ void force_time(timestamp_t ts);
void timer_print_info(void);
/**
+ * Returns a free running millisecond clock counter, which matches tpm2
+ * library expectations.
+ */
+clock_t clock(void);
+
+/**
+ * Compute how far to_time is from from_time with rollover taken into account
+ *
+ * Return us until to_time given from_time, if negative then to_time has
+ * passeed from_time.
+ */
+static inline int time_until(uint32_t from_time, uint32_t to_time)
+{
+ return (int32_t)(to_time - from_time);
+}
+
+/**
* Returns the number of microseconds that have elapsed from a start time.
*
* This function is for timing short delays typically of a few milliseconds
@@ -143,27 +160,21 @@ void timer_print_info(void);
* hour. After that, the value returned will wrap.
*
* @param start Start time to compare against
- * @return number of microseconds that have elspsed since that start time
+ * @return number of microseconds that have elapsed since that start time
*/
static inline unsigned time_since32(timestamp_t start)
{
- return get_time().le.lo - start.le.lo;
+ return time_until(start.le.lo, get_time().le.lo);
}
/**
- * Returns a free running millisecond clock counter, which matches tpm2
- * library expectations.
- */
-clock_t clock(void);
-
-/**
* To compare time and deal with rollover
*
* Return true if a is after b.
*/
static inline int time_after(uint32_t a, uint32_t b)
{
- return (int32_t)(b - a) < 0;
+ return time_until(a, b) < 0;
}
#endif /* __CROS_EC_TIMER_H */
diff --git a/test/motion_angle.c b/test/motion_angle.c
index c69f1dccc2..37157dc0c0 100644
--- a/test/motion_angle.c
+++ b/test/motion_angle.c
@@ -41,7 +41,6 @@ static int test_lid_angle_less180(void)
hook_notify(HOOK_CHIPSET_SHUTDOWN);
TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S5);
TEST_ASSERT(lid->drv->get_data_rate(lid) == 0);
- TEST_ASSERT(motion_interval == 0);
/* Go to S0 state */
hook_notify(HOOK_CHIPSET_SUSPEND);
@@ -49,7 +48,6 @@ static int test_lid_angle_less180(void)
msleep(1000);
TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S0);
TEST_ASSERT(lid->drv->get_data_rate(lid) == TEST_LID_FREQUENCY);
- TEST_ASSERT(motion_interval == TEST_LID_EC_RATE);
/* Open lid, testing close to 180 degree. */
gpio_set_level(GPIO_LID_OPEN, 1);
diff --git a/test/motion_angle_tablet.c b/test/motion_angle_tablet.c
index ee241d3172..5f096b1603 100644
--- a/test/motion_angle_tablet.c
+++ b/test/motion_angle_tablet.c
@@ -43,7 +43,6 @@ static int test_lid_angle_less180(void)
hook_notify(HOOK_CHIPSET_SHUTDOWN);
TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S5);
TEST_ASSERT(lid->drv->get_data_rate(lid) == 0);
- TEST_ASSERT(motion_interval == 0);
/* Go to S0 state */
hook_notify(HOOK_CHIPSET_SUSPEND);
@@ -51,7 +50,6 @@ static int test_lid_angle_less180(void)
msleep(1000);
TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S0);
TEST_ASSERT(lid->drv->get_data_rate(lid) == TEST_LID_FREQUENCY);
- TEST_ASSERT(motion_interval == TEST_LID_EC_RATE);
/* Open lid, testing close to 180 degree. */
gpio_set_level(GPIO_LID_OPEN, 1);
diff --git a/test/motion_common.h b/test/motion_common.h
index 3adb9f24e5..45d856d9ef 100644
--- a/test/motion_common.h
+++ b/test/motion_common.h
@@ -24,7 +24,6 @@
#define TEST_LID_SAMPLE_SIZE (2 * 3)
extern enum chipset_state_mask sensor_active;
-extern unsigned int motion_interval;
extern struct motion_sensor_t motion_sensors[];
extern const unsigned int motion_sensor_count;
diff --git a/test/motion_lid.c b/test/motion_lid.c
index 6dc5f05831..a8e16f8cd1 100644
--- a/test/motion_lid.c
+++ b/test/motion_lid.c
@@ -21,7 +21,6 @@
#include "util.h"
extern enum chipset_state_mask sensor_active;
-extern unsigned motion_interval;
/*
* Period in us for the motion task period.
@@ -181,7 +180,6 @@ static int test_lid_angle(void)
hook_notify(HOOK_CHIPSET_SHUTDOWN);
TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S5);
TEST_ASSERT(accel_get_data_rate(lid) == 0);
- TEST_ASSERT(motion_interval == 0);
/* Go to S0 state */
hook_notify(HOOK_CHIPSET_SUSPEND);
@@ -189,7 +187,6 @@ static int test_lid_angle(void)
msleep(1000);
TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S0);
TEST_ASSERT(accel_get_data_rate(lid) == 119000);
- TEST_ASSERT(motion_interval == TEST_LID_EC_RATE);
/*
* Set the base accelerometer as if it were sitting flat on a desk