summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Short <keithshort@chromium.org>2020-07-07 17:30:36 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-05-16 10:00:24 +0000
commit89fe47e40515f301b654a30bceaced1edfe1fa34 (patch)
treef8d4064bfd113bfeb75764586fef9c9805a7e47a
parent063aa5b925361851540e35a9d3da122cc881179e (diff)
downloadchrome-ec-89fe47e40515f301b654a30bceaced1edfe1fa34.tar.gz
bmi260: Add support for using compressed config
Add a new config option CONFIG_ACCELGYRO_BMI160_COMPRESSED_CONFIG for boards that need to save space. This is intended to be a temporary option until the BMI260 config file can be read from the AP at runtime. This option saves 916 bytes in RW flash space on Volteer. BUG=b:160330682 BRANCH=none TEST=make buildall TEST=boot Volteer, run "ectool motionsense" to verify sensor data is valid. Conflicts: board/volteer/board.h: sensors were not enabled in branch. Signed-off-by: Keith Short <keithshort@chromium.org> Change-Id: I294e5e0c3f919527b51e6f7361e74c7bf4afc543 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2289216 Reviewed-by: Abe Levkoy <alevkoy@chromium.org> Commit-Queue: Abe Levkoy <alevkoy@chromium.org> (cherry picked from commit 084be04a979483d93fcb6541b8424a0eecfb74a4) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3213987 Tested-by: Rong Chang <rongchang@chromium.org> Auto-Submit: Rong Chang <rongchang@chromium.org> Commit-Queue: Rong Chang <rongchang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3631907 Commit-Queue: Henry Sun <henrysun@google.com> Tested-by: Zick Wei <zick.wei@quanta.corp-partner.google.com> Reviewed-by: Henry Sun <henrysun@google.com>
-rw-r--r--driver/accelgyro_bmi260.c199
-rw-r--r--include/config.h10
2 files changed, 199 insertions, 10 deletions
diff --git a/driver/accelgyro_bmi260.c b/driver/accelgyro_bmi260.c
index c7073d41af..f5bf1dd1cf 100644
--- a/driver/accelgyro_bmi260.c
+++ b/driver/accelgyro_bmi260.c
@@ -12,6 +12,7 @@
#include "console.h"
#include "driver/accelgyro_bmi_common.h"
#include "driver/accelgyro_bmi260.h"
+#include "endian.h"
#include "hwtimer.h"
#include "i2c.h"
#include "math_util.h"
@@ -20,6 +21,7 @@
#include "third_party/bmi260/accelgyro_bmi260_config_tbin.h"
#include "timer.h"
#include "util.h"
+#include "watchdog.h"
#define CPUTS(outstr) cputs(CC_ACCEL, outstr)
#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args)
@@ -373,10 +375,170 @@ static int irq_handler(struct motion_sensor_t *s, uint32_t *event)
}
#endif /* CONFIG_ACCEL_INTERRUPTS */
-static int init_config(const struct motion_sensor_t *s)
+/*
+ * TODO(b/160330682): Eliminate or reduce size of BMI260 initialization file.
+ * Remove this option once the BMI260 initialization file is moved to the
+ * kernel rootfs.
+ */
+#ifdef CONFIG_ACCELGYRO_BMI160_COMPRESSED_CONFIG
+
+#define INCBIN_STYLE INCBIN_STYLE_SNAKE
+#define INCBIN_PREFIX
+#include "third_party/incbin/incbin.h"
+INCBIN(bmi260_config,
+ "third_party/bmi260/accelgyro_bmi260_config_compressed.bin");
+
+#define COMPRESS_KEY 0xE9EA
+#define BMI_BUFFER_SIZE 256
+static uint8_t bmi_buffer[BMI_BUFFER_SIZE];
+static int bmi_buffer_bytes;
+static int bmi_config_offset;
+
+static int write_bmi_data(const struct motion_sensor_t *s)
{
- int init_status, ret;
+ uint8_t addr[2];
+ int ret;
+
+ if (bmi_buffer_bytes == 0)
+ return EC_SUCCESS;
+
+ addr[0] = (bmi_config_offset / 2) & 0xF;
+ addr[1] = (bmi_config_offset / 2) >> 4;
+ ret = bmi_write_n(s->port, s->addr,
+ BMI260_INIT_ADDR_0, addr, 2);
+ if (ret)
+ return ret;
+
+ ret = bmi_write_n(s->port, s->addr,
+ BMI260_INIT_DATA, bmi_buffer,
+ bmi_buffer_bytes);
+ if (ret)
+ return ret;
+
+ bmi_config_offset += bmi_buffer_bytes;
+ bmi_buffer_bytes = 0;
+
+ return EC_SUCCESS;
+}
+
+/*
+ * Stores 4 bytes of BMI configuration data into a static buffer. If the buffer
+ * is filled, write the buffer contents over I2C.
+ */
+static int enqueue_bmi_data(const struct motion_sensor_t *s, uint32_t *data)
+{
+ int ret;
+
+ memcpy(&bmi_buffer[bmi_buffer_bytes], data, 4);
+ bmi_buffer_bytes += 4;
+
+ if (bmi_buffer_bytes >= BMI_BUFFER_SIZE) {
+ ret = write_bmi_data(s);
+ if (ret)
+ return ret;
+ }
+
+ return EC_SUCCESS;
+}
+
+/*
+ * Load the BMI configuration data from a compressed buffer.
+ *
+ * Compression scheme:
+ * Repeated 32-bit words are replaced by a 16-bit key, 16-bit count, and
+ * the 32-bit data word. All values stored big-endian.
+ *
+ * For example, if the uncompressed file had the following data words:
+ * 0x89ABCDEF 0x89ABCDEF 0x89ABCDEF
+ *
+ * This is represented compressed as (key 0xE9EA):
+ * 0xE9EA0003 0x89ABCDEF
+ *
+ * Key value (0xE9EA) chosen as it wasn't found in the BMI configuration
+ * data.
+ */
+int bmi_compressed_config_load(const struct motion_sensor_t *s)
+{
+ uint32_t *bmi_compressed_config = (uint32_t *)bmi260_config_data;
+ int length = bmi260_config_size;
+ int i;
+ int output_offset;
+ uint16_t *buf16;
+ uint16_t key;
+ uint16_t repeat_count;
+ uint32_t *data32;
+ int ret;
+
+ length /= sizeof(uint32_t);
+
+ bmi_buffer_bytes = 0;
+ bmi_config_offset = 0;
+
+ output_offset = 0;
+
+ for (i = 0; i < length; i++) {
+ buf16 = (uint16_t *)&bmi_compressed_config[i];
+ key = be16toh(*buf16);
+
+ if (key == COMPRESS_KEY) {
+ repeat_count = be16toh(*++buf16);
+
+ if (repeat_count == 0) {
+ CPRINTF("BMI260 config: invalid repeat count "
+ "found at word offset %d\n",
+ i);
+ return EC_ERROR_UNKNOWN;
+ }
+
+ /*
+ * Advance to the next word in the buffer, which
+ * contains the actual data to write.
+ */
+ if (++i >= length) {
+ CPRINTF("BMI260 config: "
+ "Unexpected end of file\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ data32 = &bmi_compressed_config[i];
+
+ while (repeat_count-- > 0) {
+ ret = enqueue_bmi_data(s, data32);
+ if (ret)
+ return ret;
+
+ output_offset += 4;
+ }
+ } else {
+ data32 = &bmi_compressed_config[i];
+ ret = enqueue_bmi_data(s, data32);
+ if (ret)
+ return ret;
+
+ output_offset += 4;
+ }
+ }
+
+ ret = write_bmi_data(s);
+
+ return ret;
+}
+
+static int bmi_config_load(const struct motion_sensor_t *s)
+{
+ return EC_ERROR_UNKNOWN;
+}
+#else /* !CONFIG_ACCELGYRO_BMI160_COMPRESSED_CONFIG */
+static int bmi_compressed_config_load(const struct motion_sensor_t *s)
+{
+ return EC_ERROR_UNKNOWN;
+}
+
+static int bmi_config_load(const struct motion_sensor_t *s)
+{
+ int ret;
uint16_t i;
+
/*
* Due to i2c transaction timeout limit,
* burst_write_len should not be above 2048 to prevent timeout.
@@ -385,13 +547,6 @@ static int init_config(const struct motion_sensor_t *s)
/* We have to write the config even bytes of data every time */
BUILD_ASSERT((burst_write_len & 1) == 0);
- /* disable advance power save but remain fifo self wakeup*/
- bmi_write8(s->port, s->addr, BMI260_PWR_CONF, 2);
- msleep(1);
- /* prepare for config load */
- bmi_write8(s->port, s->addr, BMI260_INIT_CTRL, 0);
-
- /* load config file to INIT_DATA */
for (i = 0; i < g_bmi260_config_tbin_len; i += burst_write_len) {
uint8_t addr[2];
const int len = MIN(burst_write_len,
@@ -407,8 +562,32 @@ static int init_config(const struct motion_sensor_t *s)
BMI260_INIT_DATA, &g_bmi260_config_tbin[i],
len);
if (ret)
- break;
+ return ret;
+;
}
+
+ return EC_SUCCESS;
+}
+
+#endif /* CONFIG_ACCELGYRO_BMI160_COMPRESSED_CONFIG */
+
+static int init_config(const struct motion_sensor_t *s)
+{
+ int init_status, ret;
+ uint16_t i;
+
+ /* disable advance power save but remain fifo self wakeup*/
+ bmi_write8(s->port, s->addr, BMI260_PWR_CONF, 2);
+ msleep(1);
+ /* prepare for config load */
+ bmi_write8(s->port, s->addr, BMI260_INIT_CTRL, 0);
+
+ /* load config file to INIT_DATA */
+ if (IS_ENABLED(CONFIG_ACCELGYRO_BMI160_COMPRESSED_CONFIG))
+ ret = bmi_compressed_config_load(s);
+ else
+ ret = bmi_config_load(s);
+
/* finish config load */
bmi_write8(s->port, s->addr, BMI260_INIT_CTRL, 1);
/* return error if load config failed */
diff --git a/include/config.h b/include/config.h
index 7467a0fe9e..4741b1e7e0 100644
--- a/include/config.h
+++ b/include/config.h
@@ -146,6 +146,16 @@
#undef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
#undef CONFIG_ACCELGYRO_BMI260_INT2_OUTPUT
+/*
+ * If defined, use a compressed version of the BMI260 configuration file.
+ * Saves a net of about 900 bytes of flash space.
+ *
+ * TODO(b/160330682): Eliminate or reduce size of BMI260 initialization file.
+ * Remove this option once the BMI260 initialization file is moved to the
+ * kernel rootfs.
+ */
+#undef CONFIG_ACCELGYRO_BMI160_COMPRESSED_CONFIG
+
/* Specify type of Gyrometers attached. */
#undef CONFIG_GYRO_L3GD20H