You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2019/01/08 13:11:18 UTC

[mynewt-core] 03/06: hw/util/i2cn: Add write_read_transact helper

This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit e8f3ed12476873eb92274d7c9ba33a3653cc73d1
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Jan 7 11:16:24 2019 +0100

    hw/util/i2cn: Add write_read_transact helper
    
    This ensures that failed read will be followed by proper write each time
    to avoid isses when read stopped, but is incomplete (i.e. read some
    bytes, but not all of them). In such scenario retrying read only may
    lead to reading invalid data from device if it uses common pattern for
    accessing data, i.e. write register address and then increment register
    address after each read byte.
---
 hw/util/i2cn/include/i2cn/i2cn.h | 28 ++++++++++++++++++++++++++++
 hw/util/i2cn/src/i2cn.c          | 30 ++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/hw/util/i2cn/include/i2cn/i2cn.h b/hw/util/i2cn/include/i2cn/i2cn.h
index 9e7aa08..16072b0 100644
--- a/hw/util/i2cn/include/i2cn/i2cn.h
+++ b/hw/util/i2cn/include/i2cn/i2cn.h
@@ -64,6 +64,34 @@ int i2cn_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
 int i2cn_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
                       os_time_t timeout, uint8_t last_op, int retries);
 
+/**
+ * @brief Writes to and then read from an I2C slave, retrying the specified
+ * number of times on failure.
+ *
+ * This should be used whenever sequence of write (e.g. register address on
+ * sensor) and read (e.g. data from that register) is required in favor of
+ * separate write and read as it guaranteed that in case of failed read, write
+ * will be performed once more to guarantee read is handled properly by device.
+ *
+ * @param i2c_num               The index of the I2C interface to write to.
+ * @param wdata                 Additional parameters describing the write
+ *                                  operation.
+ * @param rdata                 Additional parameters describing the read
+ *                                  operation.
+ * @param timeout               The time, in OS ticks, to wait for either read
+ *                                  or write operation completion.
+ * @param last_op               1 if read is the final message in the
+ *                                  transaction.
+ *
+ * @return                      0 on success;
+ *                              HAL_I2C_ERR_[...] code on failure.
+ */
+int i2cn_master_write_read_transact(uint8_t i2c_num,
+                                    struct hal_i2c_master_data *wdata,
+                                    struct hal_i2c_master_data *rdata,
+                                    os_time_t timeout, uint8_t last_op,
+                                    int retries);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/util/i2cn/src/i2cn.c b/hw/util/i2cn/src/i2cn.c
index 2ec1113..cd350c4 100644
--- a/hw/util/i2cn/src/i2cn.c
+++ b/hw/util/i2cn/src/i2cn.c
@@ -63,3 +63,33 @@ i2cn_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
 
     return rc;
 }
+
+int
+i2cn_master_write_read_transact(uint8_t i2c_num,
+                                struct hal_i2c_master_data *wdata,
+                                struct hal_i2c_master_data *rdata,
+                                os_time_t timeout, uint8_t last_op, int retries)
+{
+    int rc = 0;
+    int i;
+
+    /* Ensure at least one try. */
+    if (retries < 0) {
+        retries = 0;
+    }
+
+    for (i = 0; i <= retries; i++) {
+        rc = hal_i2c_master_write(i2c_num, wdata, timeout, 0);
+        if (rc != 0) {
+            continue;
+        }
+
+        rc = hal_i2c_master_read(i2c_num, rdata, timeout, last_op);
+        if (rc == 0) {
+            break;
+        }
+    }
+
+    return rc;
+
+}