summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Adolfsson <sadolfsson@chromium.org>2018-05-25 14:47:32 +0200
committerchrome-bot <chrome-bot@chromium.org>2018-08-22 08:16:01 -0700
commite8252556d52f897f2ea443e1cdd1bb0ebf7174ab (patch)
treedabe6d6811a71f5839ef6590a389be47da1b44ce
parent913a697b7b385f3b03ac16e9c96313139eab3578 (diff)
downloadchrome-ec-e8252556d52f897f2ea443e1cdd1bb0ebf7174ab.tar.gz
CEC: Make buffer handling code unit testable
Moving code to common/ to be able to write some unit test. The API in cec.h will be refactored in a later commit since it does not look so nice for a common API. However, it is better to do the refactoring after the unit tests are in place Signed-off-by: Stefan Adolfsson <sadolfsson@chromium.org> BUG=b:80288314 BRANCH=none TEST=emerge-fizz chromeos-ec Change-Id: I2d675689cc40248d74bf812bd6c86125d681767d Reviewed-on: https://chromium-review.googlesource.com/1073414 Commit-Ready: Stefan Adolfsson <sadolfsson@chromium.org> Tested-by: Stefan Adolfsson <sadolfsson@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/npcx/cec.c159
-rw-r--r--common/build.mk1
-rw-r--r--common/cec.c134
-rw-r--r--include/cec.h55
4 files changed, 191 insertions, 158 deletions
diff --git a/chip/npcx/cec.c b/chip/npcx/cec.c
index 73a1c7c1cf..7d4fc3be78 100644
--- a/chip/npcx/cec.c
+++ b/chip/npcx/cec.c
@@ -4,6 +4,7 @@
*/
#include "atomic.h"
+#include "cec.h"
#include "clock_chip.h"
#include "console.h"
#include "ec_commands.h"
@@ -47,15 +48,6 @@
*/
#define CEC_MAX_RESENDS 5
-/* Size of circular buffer used to store incoming CEC messages */
-#define CEC_CIRCBUF_SIZE 20
-#if CEC_CIRCBUF_SIZE < MAX_CEC_MSG_LEN + 1
-#error "Buffer must fit at least a CEC message and a length byte"
-#endif
-#if CEC_CIRCBUF_SIZE > 255
-#error "Buffer size must not exceed 255 since offsets are uint8_t"
-#endif
-
/*
* Free time timing (us). Our free-time is calculated from the end of
* the last bit (not from the start). We compensate by having one
@@ -190,32 +182,6 @@ enum cap_edge {
CAP_EDGE_RISING
};
-/* CEC message during transfer */
-struct cec_msg_transfer {
- /* The CEC message */
- uint8_t buf[MAX_CEC_MSG_LEN];
- /* Bit offset */
- uint8_t bit;
- /* Byte offset */
- uint8_t byte;
-};
-
-/*
- * Circular buffer of completed incoming CEC messages
- * ready to be read out by AP
- */
-struct cec_rx_cb {
- /* Cicular buffer data */
- uint8_t buf[CEC_CIRCBUF_SIZE];
- /*
- * Write offset. Updated from interrupt context when we
- * have received a complete message.
- */
- uint8_t write_offset;
- /* Read offset. Updated when AP sends CEC read command */
- uint8_t read_offset;
-};
-
/* Receive buffer and states */
struct cec_rx {
/*
@@ -288,12 +254,6 @@ static uint32_t cec_events;
/* APB1 frequency. Store divided by 10k to avoid some runtime divisions */
static uint32_t apb1_freq_div_10k;
-/*
- * Mutex for the read-offset of the circular buffer. Needed since the
- * buffer is read and flushed from different contexts
- */
-static struct mutex circbuf_readoffset_mutex;
-
static void send_mkbp_event(uint32_t event)
{
atomic_or(&cec_events, event);
@@ -374,123 +334,6 @@ static void tmr2_stop(void)
SET_FIELD(NPCX_TCKC(mdl), NPCX_TCKC_C2CSEL_FIELD, 0);
}
-static int msgt_get_bit(const struct cec_msg_transfer *msgt)
-{
- if (msgt->byte >= MAX_CEC_MSG_LEN)
- return 0;
-
- return msgt->buf[msgt->byte] & (0x80 >> msgt->bit);
-}
-
-static void msgt_set_bit(struct cec_msg_transfer *msgt, int val)
-{
- uint8_t bit_flag;
-
- if (msgt->byte >= MAX_CEC_MSG_LEN)
- return;
- bit_flag = 0x80 >> msgt->bit;
- msgt->buf[msgt->byte] &= ~bit_flag;
- if (val)
- msgt->buf[msgt->byte] |= bit_flag;
-}
-
-static void msgt_inc_bit(struct cec_msg_transfer *msgt)
-{
- if (++(msgt->bit) == 8) {
- if (msgt->byte >= MAX_CEC_MSG_LEN)
- return;
- msgt->bit = 0;
- msgt->byte++;
- }
-}
-
-static int msgt_is_eom(const struct cec_msg_transfer *msgt, int len)
-{
- if (msgt->bit)
- return 0;
- return (msgt->byte == len);
-}
-
-static void rx_circbuf_flush(struct cec_rx_cb *cb)
-{
- mutex_lock(&circbuf_readoffset_mutex);
- cb->read_offset = 0;
- mutex_unlock(&circbuf_readoffset_mutex);
- cb->write_offset = 0;
-}
-
-static int rx_circbuf_push(struct cec_rx_cb *cb, uint8_t *msg, uint8_t msg_len)
-{
- int i;
- uint32_t offset;
-
- if (msg_len > MAX_CEC_MSG_LEN || msg_len == 0)
- return EC_ERROR_INVAL;
-
- offset = cb->write_offset;
- /* Fill in message length last, if successful. Set to zero for now */
- cb->buf[offset] = 0;
- offset = (offset + 1) % CEC_CIRCBUF_SIZE;
-
- for (i = 0 ; i < msg_len; i++) {
- if (offset == cb->read_offset) {
- /* Buffer full */
- return EC_ERROR_OVERFLOW;
- }
-
- cb->buf[offset] = msg[i];
- offset = (offset + 1) % CEC_CIRCBUF_SIZE;
- }
-
- /*
- * Don't commit if we caught up with read-offset
- * since that would indicate an empty buffer
- */
- if (offset == cb->read_offset) {
- /* Buffer full */
- return EC_ERROR_OVERFLOW;
- }
-
- /* Commit the push */
- cb->buf[cb->write_offset] = msg_len;
- cb->write_offset = offset;
-
- return EC_SUCCESS;
-}
-
-static int rx_circbuf_pop(struct cec_rx_cb *cb, uint8_t *msg, uint8_t *msg_len)
-{
- int i;
-
- mutex_lock(&circbuf_readoffset_mutex);
- if (cb->read_offset == cb->write_offset) {
- /* Circular buffer empty */
- mutex_unlock(&circbuf_readoffset_mutex);
- *msg_len = 0;
- return -1;
- }
-
- /* The first byte in the buffer is the message length */
- *msg_len = cb->buf[cb->read_offset];
- if (*msg_len == 0 || *msg_len > MAX_CEC_MSG_LEN) {
- mutex_unlock(&circbuf_readoffset_mutex);
- *msg_len = 0;
- CPRINTF("Invalid CEC msg size: %u\n", *msg_len);
- return -1;
- }
-
- cb->read_offset = (cb->read_offset + 1) % CEC_CIRCBUF_SIZE;
- for (i = 0; i < *msg_len; i++) {
- msg[i] = cb->buf[cb->read_offset];
- cb->read_offset = (cb->read_offset + 1) % CEC_CIRCBUF_SIZE;
-
- }
-
- mutex_unlock(&circbuf_readoffset_mutex);
-
- return 0;
-}
-
void enter_state(enum cec_state new_state)
{
int gpio = -1, timeout = -1;
diff --git a/common/build.mk b/common/build.mk
index 1b3cf67e98..fe644bf384 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -28,6 +28,7 @@ common-$(CONFIG_BLUETOOTH_LE)+=bluetooth_le.o
common-$(CONFIG_BLUETOOTH_LE_STACK)+=btle_hci_controller.o btle_ll.o
common-$(CONFIG_CAPSENSE)+=capsense.o
common-$(CONFIG_CASE_CLOSED_DEBUG_V1)+=ccd_config.o
+common-$(CONFIG_CEC)+=cec.o
common-$(CONFIG_CROS_BOARD_INFO)+=cbi.o
common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o
common-$(CONFIG_CHARGE_RAMP_HW)+=charge_ramp.o
diff --git a/common/cec.c b/common/cec.c
new file mode 100644
index 0000000000..27df7a22d8
--- /dev/null
+++ b/common/cec.c
@@ -0,0 +1,134 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "cec.h"
+#include "console.h"
+#include "task.h"
+
+#define CPRINTF(format, args...) cprintf(CC_CEC, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_CEC, format, ## args)
+
+/*
+ * Mutex for the read-offset of the circular buffer. Needed since the
+ * buffer is read and flushed from different contexts
+ */
+static struct mutex circbuf_readoffset_mutex;
+
+int msgt_get_bit(const struct cec_msg_transfer *msgt)
+{
+ if (msgt->byte >= MAX_CEC_MSG_LEN)
+ return 0;
+
+ return msgt->buf[msgt->byte] & (0x80 >> msgt->bit);
+}
+
+void msgt_set_bit(struct cec_msg_transfer *msgt, int val)
+{
+ uint8_t bit_flag;
+
+ if (msgt->byte >= MAX_CEC_MSG_LEN)
+ return;
+ bit_flag = 0x80 >> msgt->bit;
+ msgt->buf[msgt->byte] &= ~bit_flag;
+ if (val)
+ msgt->buf[msgt->byte] |= bit_flag;
+}
+
+void msgt_inc_bit(struct cec_msg_transfer *msgt)
+{
+ if (++(msgt->bit) == 8) {
+ if (msgt->byte >= MAX_CEC_MSG_LEN)
+ return;
+ msgt->bit = 0;
+ msgt->byte++;
+ }
+}
+
+int msgt_is_eom(const struct cec_msg_transfer *msgt, int len)
+{
+ if (msgt->bit)
+ return 0;
+ return (msgt->byte == len);
+}
+
+void rx_circbuf_flush(struct cec_rx_cb *cb)
+{
+ mutex_lock(&circbuf_readoffset_mutex);
+ cb->read_offset = 0;
+ mutex_unlock(&circbuf_readoffset_mutex);
+ cb->write_offset = 0;
+}
+
+int rx_circbuf_push(struct cec_rx_cb *cb, uint8_t *msg, uint8_t msg_len)
+{
+ int i;
+ uint32_t offset;
+
+ if (msg_len > MAX_CEC_MSG_LEN || msg_len == 0)
+ return EC_ERROR_INVAL;
+
+ offset = cb->write_offset;
+ /* Fill in message length last, if successful. Set to zero for now */
+ cb->buf[offset] = 0;
+ offset = (offset + 1) % CEC_CIRCBUF_SIZE;
+
+ for (i = 0 ; i < msg_len; i++) {
+ if (offset == cb->read_offset) {
+ /* Buffer full */
+ return EC_ERROR_OVERFLOW;
+ }
+
+ cb->buf[offset] = msg[i];
+ offset = (offset + 1) % CEC_CIRCBUF_SIZE;
+ }
+
+ /*
+ * Don't commit if we caught up with read-offset
+ * since that would indicate an empty buffer
+ */
+ if (offset == cb->read_offset) {
+ /* Buffer full */
+ return EC_ERROR_OVERFLOW;
+ }
+
+ /* Commit the push */
+ cb->buf[cb->write_offset] = msg_len;
+ cb->write_offset = offset;
+
+ return EC_SUCCESS;
+}
+
+int rx_circbuf_pop(struct cec_rx_cb *cb, uint8_t *msg, uint8_t *msg_len)
+{
+ int i;
+
+ mutex_lock(&circbuf_readoffset_mutex);
+ if (cb->read_offset == cb->write_offset) {
+ /* Circular buffer empty */
+ mutex_unlock(&circbuf_readoffset_mutex);
+ *msg_len = 0;
+ return -1;
+ }
+
+ /* The first byte in the buffer is the message length */
+ *msg_len = cb->buf[cb->read_offset];
+ if (*msg_len == 0 || *msg_len > MAX_CEC_MSG_LEN) {
+ mutex_unlock(&circbuf_readoffset_mutex);
+ *msg_len = 0;
+ CPRINTF("Invalid CEC msg size: %u\n", *msg_len);
+ return -1;
+ }
+
+ cb->read_offset = (cb->read_offset + 1) % CEC_CIRCBUF_SIZE;
+ for (i = 0; i < *msg_len; i++) {
+ msg[i] = cb->buf[cb->read_offset];
+ cb->read_offset = (cb->read_offset + 1) % CEC_CIRCBUF_SIZE;
+
+ }
+
+ mutex_unlock(&circbuf_readoffset_mutex);
+
+ return 0;
+}
diff --git a/include/cec.h b/include/cec.h
new file mode 100644
index 0000000000..d16378917f
--- /dev/null
+++ b/include/cec.h
@@ -0,0 +1,55 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "ec_commands.h"
+
+/* Size of circular buffer used to store incoming CEC messages */
+#define CEC_CIRCBUF_SIZE 20
+#if CEC_CIRCBUF_SIZE < MAX_CEC_MSG_LEN + 1
+#error "Buffer must fit at least a CEC message and a length byte"
+#endif
+#if CEC_CIRCBUF_SIZE > 255
+#error "Buffer size must not exceed 255 since offsets are uint8_t"
+#endif
+
+/* CEC message during transfer */
+struct cec_msg_transfer {
+ /* The CEC message */
+ uint8_t buf[MAX_CEC_MSG_LEN];
+ /* Bit offset */
+ uint8_t bit;
+ /* Byte offset */
+ uint8_t byte;
+};
+
+/*
+ * Circular buffer of completed incoming CEC messages
+ * ready to be read out by AP
+ */
+struct cec_rx_cb {
+ /*
+ * Write offset. Updated from interrupt context when we
+ * have received a complete message.
+ */
+ uint8_t write_offset;
+ /* Read offset. Updated when AP sends CEC read command */
+ uint8_t read_offset;
+ /* Cicular buffer data */
+ uint8_t buf[CEC_CIRCBUF_SIZE];
+};
+
+int msgt_get_bit(const struct cec_msg_transfer *msgt);
+
+void msgt_set_bit(struct cec_msg_transfer *msgt, int val);
+
+void msgt_inc_bit(struct cec_msg_transfer *msgt);
+
+int msgt_is_eom(const struct cec_msg_transfer *msgt, int len);
+
+void rx_circbuf_flush(struct cec_rx_cb *cb);
+
+int rx_circbuf_push(struct cec_rx_cb *cb, uint8_t *msg, uint8_t msg_len);
+
+int rx_circbuf_pop(struct cec_rx_cb *cb, uint8_t *msg, uint8_t *msg_len);