ccollins476ad closed pull request #1375: I2C retries
URL: https://github.com/apache/mynewt-core/pull/1375
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/hw/drivers/bq27z561/pkg.yml b/hw/drivers/bq27z561/pkg.yml
index 45e5d52280..2861084425 100644
--- a/hw/drivers/bq27z561/pkg.yml
+++ b/hw/drivers/bq27z561/pkg.yml
@@ -28,6 +28,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/battery"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/bq27z561/src/bq27z561.c 
b/hw/drivers/bq27z561/src/bq27z561.c
index c87fd23038..ff44094d4e 100644
--- a/hw/drivers/bq27z561/src/bq27z561.c
+++ b/hw/drivers/bq27z561/src/bq27z561.c
@@ -25,6 +25,7 @@
 #include "bq27z561/bq27z561.h"
 #include "hal/hal_gpio.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 
 #include "battery/battery_prop.h"
 
@@ -141,7 +142,8 @@ bq27z561_rd_std_reg_byte(struct bq27z561 *dev, uint8_t reg, 
uint8_t *val)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
0);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 0,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         goto err;
@@ -149,7 +151,8 @@ bq27z561_rd_std_reg_byte(struct bq27z561 *dev, uint8_t reg, 
uint8_t *val)
 
     i2c.len = 1;
     i2c.buffer = (uint8_t *)val;
-    rc = hal_i2c_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1);
+    rc = i2cn_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                          MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (rd) failed 0x%02X\n", reg);
         goto err;
@@ -175,7 +178,8 @@ bq27z561_rd_std_reg_word(struct bq27z561 *dev, uint8_t reg, 
uint16_t *val)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
0);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 0,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         goto err;
@@ -183,7 +187,8 @@ bq27z561_rd_std_reg_word(struct bq27z561 *dev, uint8_t reg, 
uint16_t *val)
 
     i2c.len = 2;
     i2c.buffer = (uint8_t *)val;
-    rc = hal_i2c_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1);
+    rc = i2cn_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                          MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (rd) failed 0x%02X\n", reg);
         goto err;
@@ -216,7 +221,8 @@ bq27z561_wr_std_reg_byte(struct bq27z561 *dev, uint8_t reg, 
uint8_t val)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg write 0x%02X failed\n", reg);
     }
@@ -246,7 +252,8 @@ bq27z561_wr_std_reg_word(struct bq27z561 *dev, uint8_t reg, 
uint16_t val)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg write 0x%02X failed\n", reg);
         goto err;
@@ -284,8 +291,8 @@ bq27x561_wr_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, 
uint8_t *buf,
         memcpy(&tmpbuf[3], buf, len);
     }
 
-    i2c.len = len + 3;
     i2c.address = dev->bq27_itf.itf_addr;
+    i2c.len = len + 3;
     i2c.buffer = tmpbuf;
 
     rc = bq27z561_itf_lock(&dev->bq27_itf, MYNEWT_VAL(BQ27Z561_ITF_LOCK_TMO));
@@ -293,7 +300,8 @@ bq27x561_wr_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, 
uint8_t *buf,
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -323,8 +331,8 @@ bq27x561_rd_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, 
uint8_t *val,
     tmpbuf[1] = (uint8_t)cmd;
     tmpbuf[2] = (uint8_t)(cmd >> 8);
 
-    i2c.len = 3;
     i2c.address = dev->bq27_itf.itf_addr;
+    i2c.len = 3;
     i2c.buffer = tmpbuf;
 
     rc = bq27z561_itf_lock(&dev->bq27_itf, MYNEWT_VAL(BQ27Z561_ITF_LOCK_TMO));
@@ -332,7 +340,8 @@ bq27x561_rd_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, 
uint8_t *val,
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -344,7 +353,8 @@ bq27x561_rd_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, 
uint8_t *val,
     i2c.len = 1;
     i2c.buffer = tmpbuf;
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
0);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 0,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -354,7 +364,8 @@ bq27x561_rd_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, 
uint8_t *val,
 
     i2c.len = 36;
     i2c.buffer = tmpbuf;
-    rc = hal_i2c_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1);
+    rc = i2cn_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                          MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (rd) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -426,8 +437,8 @@ bq27x561_rd_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
     tmpbuf[1] = (uint8_t)addr;
     tmpbuf[2] = (uint8_t)(addr >> 8);
 
-    i2c.len = 3;
     i2c.address = dev->bq27_itf.itf_addr;
+    i2c.len = 3;
     i2c.buffer = tmpbuf;
 
     rc = bq27z561_itf_lock(&dev->bq27_itf, MYNEWT_VAL(BQ27Z561_ITF_LOCK_TMO));
@@ -435,7 +446,8 @@ bq27x561_rd_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -447,7 +459,8 @@ bq27x561_rd_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
     i2c.len = 1;
     i2c.buffer = tmpbuf;
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
0);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 0,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -457,7 +470,8 @@ bq27x561_rd_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
 
     i2c.len = buflen + 2;
     i2c.buffer = tmpbuf;
-    rc = hal_i2c_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1);
+    rc = i2cn_master_read(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                          MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (rd) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -507,8 +521,8 @@ bq27x561_wr_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
     tmpbuf[2] = (uint8_t)(addr >> 8);
     memcpy(&tmpbuf[3], buf, buflen);
 
-    i2c.len = buflen + 3;
     i2c.address = dev->bq27_itf.itf_addr;
+    i2c.len = buflen + 3;
     i2c.buffer = tmpbuf;
 
     rc = bq27z561_itf_lock(&dev->bq27_itf, MYNEWT_VAL(BQ27Z561_ITF_LOCK_TMO));
@@ -516,7 +530,8 @@ bq27x561_wr_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
@@ -533,7 +548,8 @@ bq27x561_wr_flash(struct bq27z561 *dev, uint16_t addr, 
uint8_t *buf, int buflen)
     i2c.len = 3;
     i2c.buffer = tmpbuf;
 
-    rc = hal_i2c_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 
1);
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
         rc = BQ27Z561_ERR_I2C_ERR;
diff --git a/hw/drivers/bq27z561/syscfg.yml b/hw/drivers/bq27z561/syscfg.yml
index edf4474dfd..1ea88ca86a 100644
--- a/hw/drivers/bq27z561/syscfg.yml
+++ b/hw/drivers/bq27z561/syscfg.yml
@@ -36,3 +36,8 @@ syscfg.defs:
     BQ27Z561_ITF_LOCK_TMO:
         description: 'BQ27Z561 interface lock timeout in milliseconds'
         value: 1000
+    BQ27Z561_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the BQ27Z561 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/chg_ctrl/adp5061/pkg.yml 
b/hw/drivers/chg_ctrl/adp5061/pkg.yml
index 7b995c8e9d..6c4ba79e63 100644
--- a/hw/drivers/chg_ctrl/adp5061/pkg.yml
+++ b/hw/drivers/chg_ctrl/adp5061/pkg.yml
@@ -28,6 +28,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - '@apache-mynewt-core/hw/hal'
     - '@apache-mynewt-core/hw/charge-control'
+    - '@apache-mynewt-core/hw/util/i2cn'
 
 pkg.deps.ADP5061_CLI:
     - '@apache-mynewt-core/sys/shell'
diff --git a/hw/drivers/chg_ctrl/adp5061/src/adp5061.c 
b/hw/drivers/chg_ctrl/adp5061/src/adp5061.c
index dfb330f574..b88da2f753 100644
--- a/hw/drivers/chg_ctrl/adp5061/src/adp5061.c
+++ b/hw/drivers/chg_ctrl/adp5061/src/adp5061.c
@@ -29,6 +29,7 @@
 #include <adp5061/adp5061.h>
 #include <bsp/bsp.h>
 #include <charge-control/charge_control.h>
+#include <i2cn/i2cn.h>
 #include "adp5061_priv.h"
 
 /**
@@ -57,10 +58,9 @@ static const struct adp5061_config default_config = {
     .iend = 0x01,
 };
 
-
 #if MYNEWT_VAL(ADP5061_INT_PIN) >= 0
 /**
-* ADP5061 interrupt hanlder CB
+* ADP5061 interrupt handler CB
 * gets interrupt status and prints to console
 */
 
@@ -81,7 +81,7 @@ adp5061_event(struct os_event *ev)
 /**
 * ADP5061 interrupt handler structure
 */
-static struct os_event interrup_handler = {
+static struct os_event interrupt_handler = {
     .ev_cb = adp5061_event,
 };
 
@@ -91,7 +91,7 @@ static struct os_event interrup_handler = {
 */
 static void
 adp5061_isr(void *arg){
-    os_eventq_put(os_eventq_dflt_get(), &interrup_handler);
+    os_eventq_put(os_eventq_dflt_get(), &interrupt_handler);
 }
 #endif
 
@@ -205,16 +205,16 @@ adp5061_get_reg(struct adp5061_dev *dev, uint8_t addr, 
uint8_t *value)
 
     /* Register write */
     payload = addr;
-    rc = hal_i2c_master_write(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
-            OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
+            OS_TICKS_PER_SEC / 10, 1, MYNEWT_VAL(ADP5061_I2C_RETRIES));
     if (rc) {
         goto err;
     }
 
     /* Read one byte back */
     payload = addr;
-    rc = hal_i2c_master_read(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
-            OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
+            OS_TICKS_PER_SEC / 10, 1, MYNEWT_VAL(ADP5061_I2C_RETRIES));
     *value = payload;
 
 err:
@@ -239,8 +239,8 @@ adp5061_set_reg(struct adp5061_dev *dev, uint8_t addr, 
uint8_t value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
-            OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
+            OS_TICKS_PER_SEC / 10, 1, MYNEWT_VAL(ADP5061_I2C_RETRIES));
 
     adp5061_itf_unlock(&dev->a_chg_ctrl.cc_itf);
 
@@ -270,8 +270,8 @@ adp5061_set_regs(struct adp5061_dev *dev, uint8_t addr,
         return rc;
     }
 
-    rc = hal_i2c_master_write(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
-            OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(dev->a_chg_ctrl.cc_itf.cci_num, &data_struct,
+            OS_TICKS_PER_SEC / 10, 1, MYNEWT_VAL(ADP5061_I2C_RETRIES));
 
     adp5061_itf_unlock(&dev->a_chg_ctrl.cc_itf);
 
diff --git a/hw/drivers/chg_ctrl/adp5061/syscfg.yml 
b/hw/drivers/chg_ctrl/adp5061/syscfg.yml
index 4033c3eec4..ec8ddb5f66 100644
--- a/hw/drivers/chg_ctrl/adp5061/syscfg.yml
+++ b/hw/drivers/chg_ctrl/adp5061/syscfg.yml
@@ -27,3 +27,8 @@ syscfg.defs:
     ADP5061_INT_PIN:
         description: 'ADP5061 interrupt pin'
         value: -1
+    ADP5061_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the ADP5061 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/drv2605/pkg.yml b/hw/drivers/drv2605/pkg.yml
index 38dfa91bfd..a7ededaf5b 100644
--- a/hw/drivers/drv2605/pkg.yml
+++ b/hw/drivers/drv2605/pkg.yml
@@ -32,6 +32,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.deps.DRV2605_CLI:
diff --git a/hw/drivers/drv2605/src/drv2605.c b/hw/drivers/drv2605/src/drv2605.c
index 631eb2f1ba..c394aab691 100644
--- a/hw/drivers/drv2605/src/drv2605.c
+++ b/hw/drivers/drv2605/src/drv2605.c
@@ -24,6 +24,7 @@
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
 #include "hal/hal_gpio.h"
+#include "i2cn/i2cn.h"
 #include "drv2605/drv2605.h"
 #include "drv2605_priv.h"
 #include <syscfg/syscfg.h>
@@ -84,7 +85,8 @@ drv2605_write8(struct sensor_itf *itf, uint8_t reg, uint8_t 
value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(DRV2605_I2C_RETRIES));
     if (rc) {
         DRV2605_LOG(ERROR,
                     "Failed to write to 0x%02X:0x%02X with value 0x%02X\n",
@@ -135,7 +137,8 @@ drv2605_writelen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(DRV2605_I2C_RETRIES));
     if (rc) {
         DRV2605_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     data_struct.address);
@@ -179,7 +182,8 @@ drv2605_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 0);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(DRV2605_I2C_RETRIES));
     if (rc) {
         DRV2605_LOG(ERROR,
                     "I2C register write failed at address 0x%02X:0x%02X\n",
@@ -192,7 +196,8 @@ drv2605_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Read one byte back */
     payload = 0;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(DRV2605_I2C_RETRIES));
     *value = payload;
     if (rc) {
         DRV2605_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -242,7 +247,8 @@ drv2605_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 0);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(DRV2605_I2C_RETRIES));
     if (rc) {
         DRV2605_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     data_struct.address);
@@ -255,7 +261,8 @@ drv2605_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(DRV2605_I2C_RETRIES));
     if (rc) {
         DRV2605_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
                     data_struct.address, reg);
diff --git a/hw/drivers/drv2605/syscfg.yml b/hw/drivers/drv2605/syscfg.yml
index 78acfa6486..9aadbf7c5c 100644
--- a/hw/drivers/drv2605/syscfg.yml
+++ b/hw/drivers/drv2605/syscfg.yml
@@ -71,3 +71,8 @@ syscfg.defs:
     DRV2605_CALIBRATED_BEMF_GAIN:
         description: 'Previously Computed Auto-Calibration BEMF_GAIN Result 
for SEMCO1030'
         value: 1
+    DRV2605_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the DRV2605 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/led/lp5523/pkg.yml b/hw/drivers/led/lp5523/pkg.yml
index ae78f2ca66..e96097e705 100644
--- a/hw/drivers/led/lp5523/pkg.yml
+++ b/hw/drivers/led/lp5523/pkg.yml
@@ -30,6 +30,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/drivers/led"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.deps.LP5523_CLI:
diff --git a/hw/drivers/led/lp5523/src/lp5523.c 
b/hw/drivers/led/lp5523/src/lp5523.c
index c51bd9442f..c7ed66f8a5 100644
--- a/hw/drivers/led/lp5523/src/lp5523.c
+++ b/hw/drivers/led/lp5523/src/lp5523.c
@@ -17,11 +17,12 @@
  * under the License.
  */
 
+#include <string.h>
 #include "os/mynewt.h"
 #include <hal/hal_i2c.h>
+#include <i2cn/i2cn.h>
 #include <modlog/modlog.h>
 #include <stats/stats.h>
-#include <string.h>
 
 #include "lp5523/lp5523.h"
 #include <syscfg/syscfg.h>
@@ -66,13 +67,14 @@ lp5523_set_reg(struct led_itf *itf, enum lp5523_registers 
addr,
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->li_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->li_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LP5523_I2C_RETRIES));
 
     if (rc) {
         LP5523_LOG(ERROR,
-                   "Failed to write to 0x%02X:0x%02X with value 0x%02X\n",
-                   itf->li_addr, addr, value);
+                   "Failed to write to 0x%02X:0x%02X with value 0x%02X "
+                   "(rc=%d)\n",
+                   itf->li_addr, addr, value, rc);
         STATS_INC(g_lp5523stats, read_errors);
     }
 
@@ -99,8 +101,8 @@ lp5523_get_reg(struct led_itf *itf, enum lp5523_registers 
addr,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->li_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 0);
+    rc = i2cn_master_write(itf->li_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(LP5523_I2C_RETRIES));
 
     if (rc) {
         LP5523_LOG(ERROR, "I2C access failed at address 0x%02X\n",
@@ -111,8 +113,8 @@ lp5523_get_reg(struct led_itf *itf, enum lp5523_registers 
addr,
 
     /* Read one byte back */
     data_struct.buffer = value;
-    rc = hal_i2c_master_read(itf->li_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->li_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(LP5523_I2C_RETRIES));
 
     if (rc) {
          LP5523_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -148,8 +150,8 @@ lp5523_set_n_regs(struct led_itf *itf, enum 
lp5523_registers addr,
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->li_num, &data_struct,
-                              (OS_TICKS_PER_SEC / 5), 1);
+    rc = i2cn_master_write(itf->li_num, &data_struct, (OS_TICKS_PER_SEC / 5),
+                           1, MYNEWT_VAL(LP5523_I2C_RETRIES));
 
     if (rc) {
         LP5523_LOG(ERROR, "Failed to write to 0x%02X:0x%02X\n", itf->li_addr,
@@ -181,8 +183,8 @@ lp5523_get_n_regs(struct led_itf *itf, enum 
lp5523_registers addr,
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->li_num, &data_struct,
-        (OS_TICKS_PER_SEC / 10), 0);
+    rc = i2cn_master_write(itf->li_num, &data_struct, (OS_TICKS_PER_SEC / 10),
+                           0, MYNEWT_VAL(LP5523_I2C_RETRIES));
 
     if (rc) {
         LP5523_LOG(ERROR, "Failed to write to 0x%02X:0x%02X\n", itf->li_addr,
@@ -193,8 +195,8 @@ lp5523_get_n_regs(struct led_itf *itf, enum 
lp5523_registers addr,
 
     data_struct.len = len;
     data_struct.buffer = vals;
-    rc = hal_i2c_master_read(itf->li_num, &data_struct,
-        OS_TICKS_PER_SEC / 5, 1);
+    rc = i2cn_master_read(itf->li_num, &data_struct, OS_TICKS_PER_SEC / 5, 1,
+                          MYNEWT_VAL(LP5523_I2C_RETRIES));
 
     if (rc) {
          LP5523_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n", itf->li_addr,
diff --git a/hw/drivers/led/lp5523/syscfg.yml b/hw/drivers/led/lp5523/syscfg.yml
index c61e642756..0e9df5897b 100644
--- a/hw/drivers/led/lp5523/syscfg.yml
+++ b/hw/drivers/led/lp5523/syscfg.yml
@@ -39,3 +39,8 @@ syscfg.defs:
     LP5523_LOG_MODULE:
         description: 'Numeric module ID to use for LP5523 log messages'
         value: 105
+    LP5523_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LP5523 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/adxl345/pkg.yml 
b/hw/drivers/sensors/adxl345/pkg.yml
index c54e8baf60..bdbc836434 100644
--- a/hw/drivers/sensors/adxl345/pkg.yml
+++ b/hw/drivers/sensors/adxl345/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/adxl345/src/adxl345.c 
b/hw/drivers/sensors/adxl345/src/adxl345.c
index 813c12d5fb..0da787d9aa 100644
--- a/hw/drivers/sensors/adxl345/src/adxl345.c
+++ b/hw/drivers/sensors/adxl345/src/adxl345.c
@@ -26,6 +26,7 @@
 #include "hal/hal_i2c.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_gpio.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "adxl345/adxl345.h"
@@ -122,8 +123,8 @@ adxl345_i2c_write8(struct sensor_itf *itf, uint8_t reg, 
uint8_t value)
         .buffer = payload
     };
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(ADXL345_I2C_RETRIES));
 
     if (rc) {
         ADXL345_LOG(ERROR,
@@ -156,8 +157,8 @@ adxl345_i2c_read8(struct sensor_itf *itf, uint8_t reg, 
uint8_t *value)
     };
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(ADXL345_I2C_RETRIES));
     if (rc) {
         ADXL345_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     itf->si_addr)
@@ -168,8 +169,8 @@ adxl345_i2c_read8(struct sensor_itf *itf, uint8_t reg, 
uint8_t *value)
     
     /* Read one byte back */
     data_struct.buffer = value;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(ADXL345_I2C_RETRIES));
 
     if (rc) {
         ADXL345_LOG(ERROR, "Failed to read from 0x%02X:0x%02X - %02X\n",
@@ -201,8 +202,8 @@ adxl345_i2c_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8_
     };
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(ADXL345_I2C_RETRIES));
     if (rc) {
         ADXL345_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     itf->si_addr);
@@ -213,8 +214,8 @@ adxl345_i2c_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8_
     /* Read data */
     data_struct.len = len;
     data_struct.buffer = buffer;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(ADXL345_I2C_RETRIES));
 
     if (rc) {
         ADXL345_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/adxl345/syscfg.yml 
b/hw/drivers/sensors/adxl345/syscfg.yml
index 85971c2e0d..562d81dde3 100644
--- a/hw/drivers/sensors/adxl345/syscfg.yml
+++ b/hw/drivers/sensors/adxl345/syscfg.yml
@@ -53,3 +53,8 @@ syscfg.defs:
     ADXL345_LOG_MODULE:
         description: 'Numeric module ID to use for ADXL345 log messages'
         value: 75
+    ADXL345_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the ADXL345 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/bma253/pkg.yml 
b/hw/drivers/sensors/bma253/pkg.yml
index 871402583b..55048bf695 100644
--- a/hw/drivers/sensors/bma253/pkg.yml
+++ b/hw/drivers/sensors/bma253/pkg.yml
@@ -28,6 +28,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/bma253/src/bma253.c 
b/hw/drivers/sensors/bma253/src/bma253.c
index e99523fedd..2fda7c3070 100644
--- a/hw/drivers/sensors/bma253/src/bma253.c
+++ b/hw/drivers/sensors/bma253/src/bma253.c
@@ -26,7 +26,7 @@
 #include "bma253_priv.h"
 #include "hal/hal_gpio.h"
 #include "hal/hal_i2c.h"
-#include <syscfg/syscfg.h>
+#include "i2cn/i2cn.h"
 
 #if MYNEWT_VAL(BMA253_LOG)
 #include "modlog/modlog.h"
@@ -163,8 +163,8 @@ get_register(struct bma253 * bma253,
     oper.len     = 1;
     oper.buffer  = &addr;
 
-    rc = hal_i2c_master_write(itf->si_num, &oper,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BMA253_I2C_RETRIES));
     if (rc != 0) {
         BMA253_LOG(ERROR, "I2C access failed at address 0x%02X\n", addr);
         goto err;
@@ -174,8 +174,8 @@ get_register(struct bma253 * bma253,
     oper.len     = 1;
     oper.buffer  = data;
 
-    rc = hal_i2c_master_read(itf->si_num, &oper,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(BMA253_I2C_RETRIES));
     if (rc != 0) {
         BMA253_LOG(ERROR, "I2C read failed at address 0x%02X single byte\n",
                    addr);
@@ -208,11 +208,10 @@ get_registers(struct bma253 * bma253,
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &oper,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BMA253_I2C_RETRIES));
     if (rc != 0) {
-        BMA253_LOG(ERROR, "I2C access failed at address 0x%02X\n",
-                   addr);
+        BMA253_LOG(ERROR, "I2C access failed at address 0x%02X\n", addr);
         goto err;
     }
 
@@ -220,8 +219,8 @@ get_registers(struct bma253 * bma253,
     oper.len     = size;
     oper.buffer  = data;
 
-    rc = hal_i2c_master_read(itf->si_num, &oper,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(BMA253_I2C_RETRIES));
     if (rc != 0) {
         BMA253_LOG(ERROR, "I2C read failed at address 0x%02X length %u\n",
                    addr, size);
@@ -257,8 +256,8 @@ set_register(struct bma253 * bma253,
     oper.len     = 2;
     oper.buffer  = tuple;
 
-    rc = hal_i2c_master_write(itf->si_num, &oper,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BMA253_I2C_RETRIES));
     if (rc != 0) {
         BMA253_LOG(ERROR, "I2C write failed at address 0x%02X single byte\n",
                    addr);
diff --git a/hw/drivers/sensors/bma253/syscfg.yml 
b/hw/drivers/sensors/bma253/syscfg.yml
index 2bcb66e78b..6c4261f27f 100644
--- a/hw/drivers/sensors/bma253/syscfg.yml
+++ b/hw/drivers/sensors/bma253/syscfg.yml
@@ -57,3 +57,8 @@ syscfg.defs:
     BMA253_ITF_LOCK_TMO:
         description: 'BMA253 interface lock timeout in milliseconds'
         value: 1000
+    BMA253_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the BMA253 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/bma2xx/pkg.yml 
b/hw/drivers/sensors/bma2xx/pkg.yml
index 537137a5d3..921d62fdcf 100644
--- a/hw/drivers/sensors/bma2xx/pkg.yml
+++ b/hw/drivers/sensors/bma2xx/pkg.yml
@@ -29,6 +29,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/bma2xx/src/bma2xx.c 
b/hw/drivers/sensors/bma2xx/src/bma2xx.c
index 173e46032c..f1bfbb1bfc 100644
--- a/hw/drivers/sensors/bma2xx/src/bma2xx.c
+++ b/hw/drivers/sensors/bma2xx/src/bma2xx.c
@@ -22,14 +22,14 @@
 #include <string.h>
 #include <errno.h>
 
-
+#include "os/mynewt.h"
 #include "bma2xx/bma2xx.h"
 #include "bma2xx_priv.h"
 #include "defs/error.h"
 #include "hal/hal_gpio.h"
 #include "hal/hal_i2c.h"
 #include "hal/hal_spi.h"
-#include <syscfg/syscfg.h>
+#include "i2cn/i2cn.h"
 
 #if MYNEWT_VAL(BMA2XX_LOG)
 #include "modlog/modlog.h"
@@ -267,8 +267,8 @@ i2c_readlen(struct sensor_itf * itf, uint8_t addr, uint8_t 
*payload,
     oper.len     = 1;
     oper.buffer  = &addr;
 
-    rc = hal_i2c_master_write(itf->si_num, &oper,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BMA2XX_I2C_RETRIES));
     if (rc != 0) {
         BMA2XX_LOG(ERROR, "I2C access failed at address 0x%02X\n", addr);
         return rc;
@@ -278,8 +278,8 @@ i2c_readlen(struct sensor_itf * itf, uint8_t addr, uint8_t 
*payload,
     oper.len     = len;
     oper.buffer  = payload;
 
-    rc = hal_i2c_master_read(itf->si_num, &oper,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(BMA2XX_I2C_RETRIES));
     if (rc != 0) {
         BMA2XX_LOG(ERROR, "I2C read failed at address 0x%02X length %u\n",
                    addr, len);
@@ -303,8 +303,8 @@ i2c_writereg(struct sensor_itf * itf, uint8_t addr, uint8_t 
data)
     oper.len     = 2;
     oper.buffer  = tuple;
 
-    rc = hal_i2c_master_write(itf->si_num, &oper,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &oper, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BMA2XX_I2C_RETRIES));
     if (rc != 0) {
         BMA2XX_LOG(ERROR, "I2C write failed at address 0x%02X single byte\n",
                    addr);
diff --git a/hw/drivers/sensors/bma2xx/syscfg.yml 
b/hw/drivers/sensors/bma2xx/syscfg.yml
index 1d0195f655..340d49a84d 100644
--- a/hw/drivers/sensors/bma2xx/syscfg.yml
+++ b/hw/drivers/sensors/bma2xx/syscfg.yml
@@ -51,3 +51,8 @@ syscfg.defs:
     BMA2XX_ITF_LOCK_TMO:
         description: 'BMA2XX interface lock timeout in milliseconds'
         value: 1000
+    BMA2XX_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the BMA2XX sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/bmp280/pkg.yml 
b/hw/drivers/sensors/bmp280/pkg.yml
index ed184b7c20..9afd46acfd 100644
--- a/hw/drivers/sensors/bmp280/pkg.yml
+++ b/hw/drivers/sensors/bmp280/pkg.yml
@@ -32,6 +32,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/bmp280/src/bmp280.c 
b/hw/drivers/sensors/bmp280/src/bmp280.c
index 5670a72380..8e054d9386 100644
--- a/hw/drivers/sensors/bmp280/src/bmp280.c
+++ b/hw/drivers/sensors/bmp280/src/bmp280.c
@@ -25,6 +25,7 @@
 #include "os/mynewt.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "bmp280/bmp280.h"
 #include "sensor/temperature.h"
@@ -704,9 +705,11 @@ bmp280_i2c_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     memset(buffer, 0, len);
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 0);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(BMP280_I2C_RETRIES));
     if (rc) {
-        BMP280_LOG(ERROR, "I2C access failed at address 0x%02X\n", 
data_struct.address);
+        BMP280_LOG(ERROR, "I2C access failed at address 0x%02X\n",
+                   data_struct.address);
         STATS_INC(g_bmp280stats, write_errors);
         goto err;
     }
@@ -714,9 +717,11 @@ bmp280_i2c_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(BMP280_I2C_RETRIES));
     if (rc) {
-        BMP280_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n", 
data_struct.address, addr);
+        BMP280_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
+                   data_struct.address, addr);
         STATS_INC(g_bmp280stats, read_errors);
         goto err;
     }
@@ -814,9 +819,12 @@ bmp280_i2c_writelen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
         payload[0] = addr + i;
         payload[1] = buffer[i];
 
-        rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC 
/ 10, 1);
+        rc = i2cn_master_write(itf->si_num, &data_struct,
+                               OS_TICKS_PER_SEC / 10, 1,
+                               MYNEWT_VAL(BMP280_I2C_RETRIES));
         if (rc) {
-            BMP280_LOG(ERROR, "Failed to write 0x%02X:0x%02X\n", 
data_struct.address, addr);
+            BMP280_LOG(ERROR, "Failed to write 0x%02X:0x%02X\n",
+                       data_struct.address, addr);
             STATS_INC(g_bmp280stats, write_errors);
             goto err;
         }
diff --git a/hw/drivers/sensors/bmp280/syscfg.yml 
b/hw/drivers/sensors/bmp280/syscfg.yml
index 2b2828163a..ba4b1716ce 100644
--- a/hw/drivers/sensors/bmp280/syscfg.yml
+++ b/hw/drivers/sensors/bmp280/syscfg.yml
@@ -45,3 +45,8 @@ syscfg.defs:
     BMP280_LOG_MODULE:
         description: 'Numeric module ID to use for BMP280 log messages'
         value: 209
+    BMP280_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the BMP280 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/bno055/pkg.yml 
b/hw/drivers/sensors/bno055/pkg.yml
index 1c9e441d86..6fcb3f304b 100644
--- a/hw/drivers/sensors/bno055/pkg.yml
+++ b/hw/drivers/sensors/bno055/pkg.yml
@@ -30,6 +30,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/bno055/src/bno055.c 
b/hw/drivers/sensors/bno055/src/bno055.c
index 66fed6a3aa..f7ed245db7 100644
--- a/hw/drivers/sensors/bno055/src/bno055.c
+++ b/hw/drivers/sensors/bno055/src/bno055.c
@@ -23,6 +23,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "sensor/mag.h"
@@ -84,7 +85,8 @@ bno055_write8(struct sensor_itf *itf, uint8_t reg, uint8_t 
value)
         .buffer = payload
     };
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC, 1,
+                           MYNEWT_VAL(BNO055_I2C_RETRIES));
     if (rc) {
         BNO055_LOG(ERROR,
                    "Failed to write to 0x%02X:0x%02X with value 0x%02X\n",
@@ -131,7 +133,8 @@ bno055_writelen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BNO055_I2C_RETRIES));
     if (rc) {
         BNO055_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                    data_struct.address);
@@ -141,7 +144,8 @@ bno055_writelen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
 
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, len);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10,
+                           len, MYNEWT_VAL(BNO055_I2C_RETRIES));
     if (rc) {
         BNO055_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
                    data_struct.address, reg);
@@ -182,7 +186,8 @@ bno055_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Register write */
     payload = reg;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 0);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(BNO055_I2C_RETRIES));
     if (rc) {
         BNO055_LOG(ERROR,
                    "I2C register write failed at address 0x%02X:0x%02X\n",
@@ -193,7 +198,8 @@ bno055_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Read one byte back */
     payload = 0;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(BNO055_I2C_RETRIES));
     *value = payload;
     if (rc) {
         BNO055_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -241,7 +247,8 @@ bno055_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t 
*buffer,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(BNO055_I2C_RETRIES));
     if (rc) {
         BNO055_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                    data_struct.address);
@@ -252,7 +259,8 @@ bno055_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t 
*buffer,
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(BNO055_I2C_RETRIES));
     if (rc) {
         BNO055_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
                    data_struct.address, reg);
diff --git a/hw/drivers/sensors/bno055/syscfg.yml 
b/hw/drivers/sensors/bno055/syscfg.yml
index 39a3609f30..985e62f274 100644
--- a/hw/drivers/sensors/bno055/syscfg.yml
+++ b/hw/drivers/sensors/bno055/syscfg.yml
@@ -36,3 +36,8 @@ syscfg.defs:
     BNO055_LOG_MODULE:
         description: 'Numeric module ID to use for BNO055 log messages'
         value: 85
+    BNO055_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the BNO055 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/lis2dh12/pkg.yml 
b/hw/drivers/sensors/lis2dh12/pkg.yml
index 782c9407e1..9b7c67edb9 100644
--- a/hw/drivers/sensors/lis2dh12/pkg.yml
+++ b/hw/drivers/sensors/lis2dh12/pkg.yml
@@ -28,6 +28,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/lis2dh12/src/lis2dh12.c 
b/hw/drivers/sensors/lis2dh12/src/lis2dh12.c
index 709b920bab..8cc00b842f 100644
--- a/hw/drivers/sensors/lis2dh12/src/lis2dh12.c
+++ b/hw/drivers/sensors/lis2dh12/src/lis2dh12.c
@@ -25,6 +25,7 @@
 #include "os/mynewt.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "lis2dh12/lis2dh12.h"
@@ -111,7 +112,8 @@ lis2dh12_i2c_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     memset(buffer, 0, len);
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LIS2DH12_I2C_RETRIES));
     if (rc) {
         LIS2DH12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
@@ -122,7 +124,8 @@ lis2dh12_i2c_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(LIS2DH12_I2C_RETRIES));
     if (rc) {
         LIS2DH12_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
                      data_struct.address, addr);
@@ -238,7 +241,8 @@ lis2dh12_i2c_writelen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     memcpy(&payload[1], buffer, len);
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LIS2DH12_I2C_RETRIES));
     if (rc) {
         LIS2DH12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
diff --git a/hw/drivers/sensors/lis2dh12/syscfg.yml 
b/hw/drivers/sensors/lis2dh12/syscfg.yml
index 334a2cb548..f0ff5a93ca 100644
--- a/hw/drivers/sensors/lis2dh12/syscfg.yml
+++ b/hw/drivers/sensors/lis2dh12/syscfg.yml
@@ -24,3 +24,8 @@ syscfg.defs:
     LIS2DH12_LOG_MODULE:
         description: 'Numeric module ID to use for LIS2DH12 log messages'
         value: 110
+    LIS2DH12_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LIS2DH12 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/lis2ds12/pkg.yml 
b/hw/drivers/sensors/lis2ds12/pkg.yml
index 595b74c454..cc490da464 100644
--- a/hw/drivers/sensors/lis2ds12/pkg.yml
+++ b/hw/drivers/sensors/lis2ds12/pkg.yml
@@ -29,6 +29,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/lis2ds12/src/lis2ds12.c 
b/hw/drivers/sensors/lis2ds12/src/lis2ds12.c
index d22960d94d..198ed8fb9a 100644
--- a/hw/drivers/sensors/lis2ds12/src/lis2ds12.c
+++ b/hw/drivers/sensors/lis2ds12/src/lis2ds12.c
@@ -25,6 +25,7 @@
 #include "os/mynewt.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "lis2ds12/lis2ds12.h"
@@ -139,7 +140,8 @@ lis2ds12_i2c_writelen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     memcpy(&payload[1], buffer, len);
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LIS2DS12_I2C_RETRIES));
     if (rc) {
         LIS2DS12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
@@ -260,8 +262,8 @@ lis2ds12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8
     };
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LIS2DS12_I2C_RETRIES));
     if (rc) {
         LIS2DS12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      itf->si_addr);
@@ -272,8 +274,8 @@ lis2ds12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8
     /* Read data */
     data_struct.len = len;
     data_struct.buffer = buffer;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(LIS2DS12_I2C_RETRIES));
 
     if (rc) {
         LIS2DS12_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/lis2ds12/syscfg.yml 
b/hw/drivers/sensors/lis2ds12/syscfg.yml
index 4dc310b690..b9d57f6b79 100644
--- a/hw/drivers/sensors/lis2ds12/syscfg.yml
+++ b/hw/drivers/sensors/lis2ds12/syscfg.yml
@@ -47,3 +47,8 @@ syscfg.defs:
     LIS2DS12_LOG_MODULE:
         description: 'Numeric module ID to use for LIS2DS12 log messages'
         value: 212
+    LIS2DS12_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LIS2DS12 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/lis2dw12/pkg.yml 
b/hw/drivers/sensors/lis2dw12/pkg.yml
index d5634bdeb7..2d71684020 100644
--- a/hw/drivers/sensors/lis2dw12/pkg.yml
+++ b/hw/drivers/sensors/lis2dw12/pkg.yml
@@ -29,6 +29,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c 
b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
index 6dae73ab1e..52a801e383 100644
--- a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
@@ -25,6 +25,7 @@
 #include "os/mynewt.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "lis2dw12/lis2dw12.h"
@@ -206,8 +207,8 @@ lis2dw12_i2c_writelen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     memcpy(&payload[1], buffer, len);
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
     if (rc) {
         LIS2DW12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
@@ -336,8 +337,8 @@ lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
     };
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
     if (rc) {
         LIS2DW12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      itf->si_addr);
@@ -348,8 +349,8 @@ lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer,
     /* Read data */
     data_struct.len = len;
     data_struct.buffer = buffer;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
 
     if (rc) {
         LIS2DW12_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/lis2dw12/syscfg.yml 
b/hw/drivers/sensors/lis2dw12/syscfg.yml
index 3d31eb88d2..5c3861ad0a 100644
--- a/hw/drivers/sensors/lis2dw12/syscfg.yml
+++ b/hw/drivers/sensors/lis2dw12/syscfg.yml
@@ -50,3 +50,8 @@ syscfg.defs:
     LIS2DW12_LOG_MODULE:
         description: 'Numeric module ID to use for LIS2DW12 log messages'
         value: 213
+    LIS2DW12_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LIS2DW12 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/lps33hw/pkg.yml 
b/hw/drivers/sensors/lps33hw/pkg.yml
index ea9a608032..8ac137fd7d 100644
--- a/hw/drivers/sensors/lps33hw/pkg.yml
+++ b/hw/drivers/sensors/lps33hw/pkg.yml
@@ -33,6 +33,7 @@ pkg.deps:
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/lps33hw/src/lps33hw.c 
b/hw/drivers/sensors/lps33hw/src/lps33hw.c
index 815cff675b..b6628f2248 100644
--- a/hw/drivers/sensors/lps33hw/src/lps33hw.c
+++ b/hw/drivers/sensors/lps33hw/src/lps33hw.c
@@ -26,6 +26,7 @@
 #include "hal/hal_i2c.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_gpio.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/pressure.h"
 #include "sensor/temperature.h"
@@ -175,8 +176,8 @@ lps33hw_i2c_set_reg(struct sensor_itf *itf, uint8_t reg, 
uint8_t value)
         .buffer = payload
     };
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LPS33HW_I2C_RETRIES));
 
     if (rc) {
         LPS33HW_LOG(ERROR,
@@ -346,8 +347,8 @@ lps33hw_i2c_get_regs(struct sensor_itf *itf, uint8_t reg, 
uint8_t size,
     };
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LPS33HW_I2C_RETRIES));
     if (rc) {
         LPS33HW_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     itf->si_addr);
@@ -358,8 +359,9 @@ lps33hw_i2c_get_regs(struct sensor_itf *itf, uint8_t reg, 
uint8_t size,
     /* Read */
     data_struct.len = size;
     data_struct.buffer = buffer;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             (OS_TICKS_PER_SEC / 10) * size, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct,
+                          (OS_TICKS_PER_SEC / 10) * size, 1,
+                          MYNEWT_VAL(LPS33HW_I2C_RETRIES));
 
     if (rc) {
         LPS33HW_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/lps33hw/syscfg.yml 
b/hw/drivers/sensors/lps33hw/syscfg.yml
index dd358dba50..407d2429e6 100644
--- a/hw/drivers/sensors/lps33hw/syscfg.yml
+++ b/hw/drivers/sensors/lps33hw/syscfg.yml
@@ -38,3 +38,8 @@ syscfg.defs:
     LPS33HW_LOG_MODULE:
         description: 'Numeric module ID to use for LPS33HW log messages'
         value: 133
+    LPS33HW_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LPS33HW sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/lps33thw/pkg.yml 
b/hw/drivers/sensors/lps33thw/pkg.yml
index 669046e8dc..1dc6fcb831 100644
--- a/hw/drivers/sensors/lps33thw/pkg.yml
+++ b/hw/drivers/sensors/lps33thw/pkg.yml
@@ -32,6 +32,7 @@ pkg.deps:
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/lps33thw/src/lps33thw.c 
b/hw/drivers/sensors/lps33thw/src/lps33thw.c
index 3c6e67d8be..4b896f1a97 100644
--- a/hw/drivers/sensors/lps33thw/src/lps33thw.c
+++ b/hw/drivers/sensors/lps33thw/src/lps33thw.c
@@ -26,6 +26,7 @@
 #include "hal/hal_i2c.h"
 #include "hal/hal_spi.h"
 #include "hal/hal_gpio.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/pressure.h"
 #include "sensor/temperature.h"
@@ -175,8 +176,8 @@ lps33thw_i2c_set_reg(struct sensor_itf *itf, uint8_t reg, 
uint8_t value)
         .buffer = payload
     };
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LPS33THW_I2C_RETRIES));
 
     if (rc) {
         LPS33THW_LOG(ERROR,
@@ -346,8 +347,8 @@ lps33thw_i2c_get_regs(struct sensor_itf *itf, uint8_t reg, 
uint8_t size,
     };
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LPS33THW_I2C_RETRIES));
     if (rc) {
         LPS33THW_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     itf->si_addr);
@@ -358,8 +359,9 @@ lps33thw_i2c_get_regs(struct sensor_itf *itf, uint8_t reg, 
uint8_t size,
     /* Read */
     data_struct.len = size;
     data_struct.buffer = buffer;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             (OS_TICKS_PER_SEC / 10) * size, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct,
+                          (OS_TICKS_PER_SEC / 10) * size, 1,
+                          MYNEWT_VAL(LPS33THW_I2C_RETRIES));
 
     if (rc) {
         LPS33THW_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/lps33thw/syscfg.yml 
b/hw/drivers/sensors/lps33thw/syscfg.yml
index 30f491d433..452bda4ecf 100644
--- a/hw/drivers/sensors/lps33thw/syscfg.yml
+++ b/hw/drivers/sensors/lps33thw/syscfg.yml
@@ -37,4 +37,9 @@ syscfg.defs:
         value: 1000
     LPS33THW_LOG_MODULE:
         description: 'Numeric module ID to use for LPS33THW log messages'
-        value: 233
\ No newline at end of file
+        value: 233
+    LPS33THW_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LPS33THW sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/lsm303dlhc/pkg.yml 
b/hw/drivers/sensors/lsm303dlhc/pkg.yml
index 3b96f9a280..0ae5a94003 100644
--- a/hw/drivers/sensors/lsm303dlhc/pkg.yml
+++ b/hw/drivers/sensors/lsm303dlhc/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/lsm303dlhc/src/lsm303dlhc.c 
b/hw/drivers/sensors/lsm303dlhc/src/lsm303dlhc.c
index d6bf72c62c..95d47029f9 100644
--- a/hw/drivers/sensors/lsm303dlhc/src/lsm303dlhc.c
+++ b/hw/drivers/sensors/lsm303dlhc/src/lsm303dlhc.c
@@ -23,6 +23,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "sensor/mag.h"
@@ -108,8 +109,8 @@ lsm303dlhc_write8(struct sensor_itf *itf, uint8_t addr, 
uint8_t reg,
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LSM303DLHC_I2C_RETRIES));
     if (rc) {
         LSM303DLHC_LOG(ERROR,
                        "Failed to write to 0x%02X:0x%02X with value 0x%02lX\n",
@@ -152,8 +153,8 @@ lsm303dlhc_read8(struct sensor_itf *itf, uint8_t addr, 
uint8_t reg,
 
     /* Register write */
     payload = reg;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LSM303DLHC_I2C_RETRIES));
     if (rc) {
         LSM303DLHC_LOG(ERROR, "I2C access failed at address 0x%02X\n", addr);
         STATS_INC(g_lsm303dlhcstats, errors);
@@ -162,8 +163,8 @@ lsm303dlhc_read8(struct sensor_itf *itf, uint8_t addr, 
uint8_t reg,
 
     /* Read one byte back */
     payload = 0;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(LSM303DLHC_I2C_RETRIES));
     *value = payload;
     if (rc) {
         LSM303DLHC_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -209,8 +210,8 @@ lsm303dlhc_read48(struct sensor_itf *itf, uint8_t addr, 
uint8_t reg,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(LSM303DLHC_I2C_RETRIES));
     if (rc) {
         LSM303DLHC_LOG(ERROR, "I2C access failed at address 0x%02X\n", addr);
         STATS_INC(g_lsm303dlhcstats, errors);
@@ -220,8 +221,8 @@ lsm303dlhc_read48(struct sensor_itf *itf, uint8_t addr, 
uint8_t reg,
     /* Read six bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = 6;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(LSM303DLHC_I2C_RETRIES));
 
     if (rc) {
         LSM303DLHC_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/lsm303dlhc/syscfg.yml 
b/hw/drivers/sensors/lsm303dlhc/syscfg.yml
index 981725a588..b15a03dc2d 100644
--- a/hw/drivers/sensors/lsm303dlhc/syscfg.yml
+++ b/hw/drivers/sensors/lsm303dlhc/syscfg.yml
@@ -23,3 +23,8 @@ syscfg.defs:
     LSM303DLHC_LOG_MODULE:
         description: 'Numeric module ID to use for LSM303DLHC log messages'
         value: 195
+    LSM303DLHC_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the LSM303DLHC sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/mpu6050/pkg.yml 
b/hw/drivers/sensors/mpu6050/pkg.yml
index 2355a26d33..b9b639fbf8 100644
--- a/hw/drivers/sensors/mpu6050/pkg.yml
+++ b/hw/drivers/sensors/mpu6050/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/mpu6050/src/mpu6050.c 
b/hw/drivers/sensors/mpu6050/src/mpu6050.c
index c236f5f0ca..73680556b2 100644
--- a/hw/drivers/sensors/mpu6050/src/mpu6050.c
+++ b/hw/drivers/sensors/mpu6050/src/mpu6050.c
@@ -23,6 +23,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
 #include "sensor/gyro.h"
@@ -87,8 +88,8 @@ mpu6050_write8(struct sensor_itf *itf, uint8_t reg, uint32_t 
value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(MPU6050_I2C_RETRIES));
 
     if (rc) {
         MPU6050_LOG(ERROR,
@@ -128,8 +129,8 @@ mpu6050_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 0);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(MPU6050_I2C_RETRIES));
     if (rc) {
         MPU6050_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     itf->si_addr);
@@ -139,8 +140,8 @@ mpu6050_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Read one byte back */
     data_struct.buffer = value;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(MPU6050_I2C_RETRIES));
 
     if (rc) {
         MPU6050_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -179,8 +180,8 @@ mpu6050_read48(struct sensor_itf *itf, uint8_t reg, uint8_t 
*buffer)
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 0);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 0,
+                           MYNEWT_VAL(MPU6050_I2C_RETRIES));
     if (rc) {
         MPU6050_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                     itf->si_addr);
@@ -191,8 +192,8 @@ mpu6050_read48(struct sensor_itf *itf, uint8_t reg, uint8_t 
*buffer)
     /* Read six bytes back */
     data_struct.len = 6;
     data_struct.buffer = buffer;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(MPU6050_I2C_RETRIES));
 
     if (rc) {
         MPU6050_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
diff --git a/hw/drivers/sensors/mpu6050/syscfg.yml 
b/hw/drivers/sensors/mpu6050/syscfg.yml
index 429c6fe647..b03ba53710 100644
--- a/hw/drivers/sensors/mpu6050/syscfg.yml
+++ b/hw/drivers/sensors/mpu6050/syscfg.yml
@@ -23,3 +23,8 @@ syscfg.defs:
     MPU6050_LOG_MODULE:
         description: 'Numeric module ID to use for MPU6050 log messages'
         value: 115
+    MPU6050_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the MPU6050 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/ms5837/pkg.yml 
b/hw/drivers/sensors/ms5837/pkg.yml
index 784a648859..a0a7c52c17 100644
--- a/hw/drivers/sensors/ms5837/pkg.yml
+++ b/hw/drivers/sensors/ms5837/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/ms5837/src/ms5837.c 
b/hw/drivers/sensors/ms5837/src/ms5837.c
index 37089b9f13..231704e723 100644
--- a/hw/drivers/sensors/ms5837/src/ms5837.c
+++ b/hw/drivers/sensors/ms5837/src/ms5837.c
@@ -24,6 +24,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "ms5837/ms5837.h"
 #include "sensor/temperature.h"
@@ -335,7 +336,8 @@ ms5837_writelen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(MS5837_I2C_RETRIES));
     if (rc) {
         MS5837_LOG(ERROR, "I2C write command write failed at address 0x%02X\n",
                    data_struct.address);
@@ -379,7 +381,8 @@ ms5837_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     }
 
     /* Command write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(MS5837_I2C_RETRIES));
     if (rc) {
         MS5837_LOG(ERROR, "I2C read command write failed at address 0x%02X\n",
                    data_struct.address);
@@ -390,7 +393,8 @@ ms5837_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(MS5837_I2C_RETRIES));
     if (rc) {
         MS5837_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
                    data_struct.address, addr);
diff --git a/hw/drivers/sensors/ms5837/syscfg.yml 
b/hw/drivers/sensors/ms5837/syscfg.yml
index 2cacb293d6..1d60ba607d 100644
--- a/hw/drivers/sensors/ms5837/syscfg.yml
+++ b/hw/drivers/sensors/ms5837/syscfg.yml
@@ -23,3 +23,8 @@ syscfg.defs:
     MS5837_LOG_MODULE:
         description: 'Numeric module ID to use for MS5837 log messages'
         value: 140
+    MS5837_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the MS5837 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/ms5840/pkg.yml 
b/hw/drivers/sensors/ms5840/pkg.yml
index d990ce0f00..7ea322d27e 100644
--- a/hw/drivers/sensors/ms5840/pkg.yml
+++ b/hw/drivers/sensors/ms5840/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/ms5840/src/ms5840.c 
b/hw/drivers/sensors/ms5840/src/ms5840.c
index 6f4e444ff6..f7a3eb26be 100644
--- a/hw/drivers/sensors/ms5840/src/ms5840.c
+++ b/hw/drivers/sensors/ms5840/src/ms5840.c
@@ -26,6 +26,7 @@
 #include "os/os.h"
 #include "sysinit/sysinit.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "ms5840/ms5840.h"
 #include "sensor/temperature.h"
@@ -336,8 +337,8 @@ ms5840_writelen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(MS5840_I2C_RETRIES));
     if (rc) {
         MS5840_LOG(ERROR, "I2C write command write failed at address 0x%02X\n",
                    data_struct.address);
@@ -381,8 +382,8 @@ ms5840_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     }
 
     /* Command write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(MS5840_I2C_RETRIES));
     if (rc) {
         MS5840_LOG(ERROR, "I2C read command write failed at address 0x%02X\n",
                    data_struct.address);
@@ -393,8 +394,8 @@ ms5840_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *buffer,
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(MS5840_I2C_RETRIES));
     if (rc) {
         MS5840_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
                    data_struct.address, addr);
diff --git a/hw/drivers/sensors/ms5840/syscfg.yml 
b/hw/drivers/sensors/ms5840/syscfg.yml
index a8e2acdb14..56fb0b9abd 100644
--- a/hw/drivers/sensors/ms5840/syscfg.yml
+++ b/hw/drivers/sensors/ms5840/syscfg.yml
@@ -23,3 +23,8 @@ syscfg.defs:
     MS5840_LOG_MODULE:
         description: 'Numeric module ID to use for MS5840 log messages'
         value: 170
+    MS5840_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the MS5840 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/tcs34725/pkg.yml 
b/hw/drivers/sensors/tcs34725/pkg.yml
index 92049f1754..90f7cff626 100644
--- a/hw/drivers/sensors/tcs34725/pkg.yml
+++ b/hw/drivers/sensors/tcs34725/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/tcs34725/src/tcs34725.c 
b/hw/drivers/sensors/tcs34725/src/tcs34725.c
index 98b964102f..aa5fc05e0d 100644
--- a/hw/drivers/sensors/tcs34725/src/tcs34725.c
+++ b/hw/drivers/sensors/tcs34725/src/tcs34725.c
@@ -23,6 +23,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "tcs34725/tcs34725.h"
 #include "tcs34725_priv.h"
@@ -98,8 +99,8 @@ tcs34725_write8(struct sensor_itf *itf, uint8_t reg, uint32_t 
value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TCS34725_I2C_RETRIES));
     if (rc) {
         TCS34725_LOG(ERROR,
                      "Failed to write to 0x%02X:0x%02X with value 0x%02lX\n",
@@ -140,7 +141,8 @@ tcs34725_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Register write */
     payload = reg | TCS34725_COMMAND_BIT;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 
10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TCS34725_I2C_RETRIES));
     if (rc) {
         TCS34725_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
@@ -150,7 +152,8 @@ tcs34725_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Read one byte back */
     payload = 0;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 
1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(TCS34725_I2C_RETRIES));
     *value = payload;
     if (rc) {
         TCS34725_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -194,8 +197,8 @@ tcs34725_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8_t l
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TCS34725_I2C_RETRIES));
     if (rc) {
         TCS34725_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
@@ -206,8 +209,8 @@ tcs34725_readlen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8_t l
     /* Read len bytes back */
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(TCS34725_I2C_RETRIES));
 
     if (rc) {
         TCS34725_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -259,8 +262,8 @@ tcs34725_writelen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8_t
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TCS34725_I2C_RETRIES));
     if (rc) {
         TCS34725_LOG(ERROR, "I2C access failed at address 0x%02X\n",
                      data_struct.address);
@@ -270,8 +273,8 @@ tcs34725_writelen(struct sensor_itf *itf, uint8_t reg, 
uint8_t *buffer, uint8_t
 
     memset(payload, 0, sizeof(payload));
     data_struct.len = len;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, len);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10,
+                           len, MYNEWT_VAL(TCS34725_I2C_RETRIES));
 
     if (rc) {
         TCS34725_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
@@ -977,8 +980,8 @@ tcs34725_clear_interrupt(struct sensor_itf *itf)
         .buffer = &payload
     };
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TCS34725_I2C_RETRIES));
     if (rc) {
         goto err;
     }
diff --git a/hw/drivers/sensors/tcs34725/syscfg.yml 
b/hw/drivers/sensors/tcs34725/syscfg.yml
index 7922406b45..1dc3ff4bbf 100644
--- a/hw/drivers/sensors/tcs34725/syscfg.yml
+++ b/hw/drivers/sensors/tcs34725/syscfg.yml
@@ -36,3 +36,8 @@ syscfg.defs:
     TCS34725_LOG_MODULE:
         description: 'Numeric module ID to use for TCS34725 log messages'
         value: 254
+    TCS34725_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the TCS34725 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/tsl2561/pkg.yml 
b/hw/drivers/sensors/tsl2561/pkg.yml
index c0c8e91eee..79c057a634 100644
--- a/hw/drivers/sensors/tsl2561/pkg.yml
+++ b/hw/drivers/sensors/tsl2561/pkg.yml
@@ -34,6 +34,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/tsl2561/src/tsl2561.c 
b/hw/drivers/sensors/tsl2561/src/tsl2561.c
index c934552d48..506f8e889d 100644
--- a/hw/drivers/sensors/tsl2561/src/tsl2561.c
+++ b/hw/drivers/sensors/tsl2561/src/tsl2561.c
@@ -41,6 +41,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/light.h"
 #include "tsl2561/tsl2561.h"
@@ -95,8 +96,8 @@ tsl2561_write8(struct sensor_itf *itf, uint8_t reg, uint32_t 
value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2561_I2C_RETRIES));
     if (rc) {
         TSL2561_LOG(ERROR,
                     "Failed to write 0x%02X:0x%02X with value 0x%02lX\n",
@@ -126,8 +127,8 @@ tsl2561_write16(struct sensor_itf *itf, uint8_t reg, 
uint16_t value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2561_I2C_RETRIES));
     if (rc) {
         TSL2561_LOG(ERROR,
                     "Failed to write @0x%02X with value 0x%02X 0x%02X\n",
@@ -158,8 +159,8 @@ tsl2561_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Register write */
     payload = reg;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2561_I2C_RETRIES));
     if (rc) {
         TSL2561_LOG(ERROR, "Failed to address sensor\n");
         goto err;
@@ -167,8 +168,8 @@ tsl2561_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Read one byte back */
     payload = 0;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(TSL2561_I2C_RETRIES));
     *value = payload;
     if (rc) {
         TSL2561_LOG(ERROR, "Failed to read @0x%02X\n", reg);
@@ -198,8 +199,8 @@ tsl2561_read16(struct sensor_itf *itf, uint8_t reg, 
uint16_t *value)
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2561_I2C_RETRIES));
     if (rc) {
         TSL2561_LOG(ERROR, "Failed to address sensor\n");
         goto err;
@@ -208,8 +209,8 @@ tsl2561_read16(struct sensor_itf *itf, uint8_t reg, 
uint16_t *value)
     /* Read two bytes back */
     memset(payload, 0, 2);
     data_struct.len = 2;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(TSL2561_I2C_RETRIES));
     *value = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8);
     if (rc) {
         TSL2561_LOG(ERROR, "Failed to read @0x%02X\n", reg);
@@ -553,8 +554,8 @@ tsl2561_clear_interrupt(struct sensor_itf *itf)
     };
 
     /* To clear the interrupt set the CLEAR bit in the COMMAND register */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2561_I2C_RETRIES));
     if (rc) {
         goto err;
     }
diff --git a/hw/drivers/sensors/tsl2561/syscfg.yml 
b/hw/drivers/sensors/tsl2561/syscfg.yml
index 3c3fff99a0..c617584c5c 100644
--- a/hw/drivers/sensors/tsl2561/syscfg.yml
+++ b/hw/drivers/sensors/tsl2561/syscfg.yml
@@ -39,3 +39,8 @@ syscfg.defs:
     TSL2561_LOG_MODULE:
         description: 'Numeric module ID to use for TSL2561 log messages'
         value: 107
+    TSL2561_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the TSL2561 sends an unexpected NACK.
+        value: 2
diff --git a/hw/drivers/sensors/tsl2591/pkg.yml 
b/hw/drivers/sensors/tsl2591/pkg.yml
index d74225b835..b0926a8f47 100644
--- a/hw/drivers/sensors/tsl2591/pkg.yml
+++ b/hw/drivers/sensors/tsl2591/pkg.yml
@@ -31,6 +31,7 @@ pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/hw/sensor"
+    - "@apache-mynewt-core/hw/util/i2cn"
     - "@apache-mynewt-core/sys/log/modlog"
 
 pkg.req_apis:
diff --git a/hw/drivers/sensors/tsl2591/src/tsl2591.c 
b/hw/drivers/sensors/tsl2591/src/tsl2591.c
index bdc93412a0..6eb841cfb5 100644
--- a/hw/drivers/sensors/tsl2591/src/tsl2591.c
+++ b/hw/drivers/sensors/tsl2591/src/tsl2591.c
@@ -24,6 +24,7 @@
 
 #include "os/mynewt.h"
 #include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
 #include "sensor/sensor.h"
 #include "sensor/light.h"
 #include "tsl2591/tsl2591.h"
@@ -88,8 +89,8 @@ tsl2591_write8(struct sensor_itf *itf, uint8_t reg, uint32_t 
value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2591_I2C_RETRIES));
     if (rc) {
         TSL2591_LOG(ERROR,
                     "Failed to write 0x%02X:0x%02X with value 0x%02lX\n",
@@ -119,8 +120,8 @@ tsl2591_write16(struct sensor_itf *itf, uint8_t reg, 
uint16_t value)
         return rc;
     }
 
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2591_I2C_RETRIES));
     if (rc) {
         TSL2591_LOG(ERROR,
                     "Failed to write @0x%02X with value 0x%02X 0x%02X\n",
@@ -152,8 +153,8 @@ tsl2591_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Register write */
     payload = reg;
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2591_I2C_RETRIES));
     if (rc) {
         TSL2591_LOG(ERROR, "Failed to address sensor\n");
         STATS_INC(g_tsl2591stats, errors);
@@ -162,8 +163,8 @@ tsl2591_read8(struct sensor_itf *itf, uint8_t reg, uint8_t 
*value)
 
     /* Read one byte back */
     payload = 0;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(TSL2591_I2C_RETRIES));
     *value = payload;
     if (rc) {
         TSL2591_LOG(ERROR, "Failed to read @0x%02X\n", reg);
@@ -194,8 +195,8 @@ tsl2591_read16(struct sensor_itf *itf, uint8_t reg, 
uint16_t *value)
     }
 
     /* Register write */
-    rc = hal_i2c_master_write(itf->si_num, &data_struct,
-                              OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                           MYNEWT_VAL(TSL2591_I2C_RETRIES));
     if (rc) {
         TSL2591_LOG(ERROR, "Failed to address sensor\n");
         STATS_INC(g_tsl2591stats, errors);
@@ -205,8 +206,8 @@ tsl2591_read16(struct sensor_itf *itf, uint8_t reg, 
uint16_t *value)
     /* Read two bytes back */
     memset(payload, 0, 2);
     data_struct.len = 2;
-    rc = hal_i2c_master_read(itf->si_num, &data_struct,
-                             OS_TICKS_PER_SEC / 10, 1);
+    rc = i2cn_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1,
+                          MYNEWT_VAL(TSL2591_I2C_RETRIES));
     *value = (uint16_t)payload[0] | ((uint16_t)payload[1] << 8);
     if (rc) {
         TSL2591_LOG(ERROR, "Failed to read @0x%02X\n", reg);
diff --git a/hw/drivers/sensors/tsl2591/syscfg.yml 
b/hw/drivers/sensors/tsl2591/syscfg.yml
index 0efb9d238a..13ef62d104 100644
--- a/hw/drivers/sensors/tsl2591/syscfg.yml
+++ b/hw/drivers/sensors/tsl2591/syscfg.yml
@@ -42,3 +42,8 @@ syscfg.defs:
     TSL2591_LOG_MODULE:
         description: 'Numeric module ID to use for TSL2591 log messages'
         value: 108
+    TSL2591_I2C_RETRIES:
+        description: >
+            Number of retries to use for failed I2C communication.  A retry is
+            used when the TSL2591 sends an unexpected NACK.
+        value: 2
diff --git a/hw/hal/include/hal/hal_i2c.h b/hw/hal/include/hal/hal_i2c.h
index 22f8f8e1e6..be080ca0cd 100644
--- a/hw/hal/include/hal/hal_i2c.h
+++ b/hw/hal/include/hal/hal_i2c.h
@@ -62,6 +62,23 @@ extern "C" {
  *      :c:func:`hal_i2c_read()`; --- read back data, setting 'last_op' to '1'
  */
 
+/*** I2C status codes (0=success). */
+
+/** Unknown error. */
+#define HAL_I2C_ERR_UNKNOWN             1
+
+/** Invalid argument. */
+#define HAL_I2C_ERR_INVAL               2
+
+/** MCU failed to report result of I2C operation. */
+#define HAL_I2C_ERR_TIMEOUT             3
+
+/** Slave responded to address with NACK. */
+#define HAL_I2C_ERR_ADDR_NACK           4
+
+/** Slave responded to data byte with NACK. */
+#define HAL_I2C_ERR_DATA_NACK           5
+
 /**
  * When sending a packet, use this structure to pass the arguments.
  */
@@ -77,8 +94,8 @@ struct hal_i2c_master_data {
      * writing a 0x81 in its protocol, you would pass
      * only the top 7-bits to this function as 0x40
      */
-    uint8_t  address
-    /** Number of buffer bytes to transmit or receive */;
+    uint8_t  address;
+    /** Number of buffer bytes to transmit or receive */
     uint16_t len;
     /** Buffer space to hold the transmit or receive */
     uint8_t *buffer;
@@ -129,7 +146,7 @@ int hal_i2c_master_write(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
  * @return 0 on success, and non-zero error code on failure
  */
 int hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
-                         uint32_t timeout, uint8_t last_op);
+                        uint32_t timeout, uint8_t last_op);
 
 /**
  * Probes the i2c bus for a device with this address.  THIS API
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c 
b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 8ac5eea358..85c18fecb4 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -25,6 +25,7 @@
 #include <hal/hal_i2c.h>
 #include <hal/hal_gpio.h>
 #include <mcu/nrf52_hal.h>
+#include "nrf_twim.h"
 
 #include <nrf.h>
 
@@ -46,17 +47,6 @@
       (GPIO_PIN_CNF_DIR_Output     << GPIO_PIN_CNF_DIR_Pos))
 #define NRF52_SDA_PIN_CONF_CLR    NRF52_SCL_PIN_CONF_CLR
 
-#define NRF52_HAL_I2C_RESOLVE(__n, __v)                      \
-    if ((__n) >= NRF52_HAL_I2C_MAX) {                        \
-        rc = EINVAL;                                         \
-        goto err;                                            \
-    }                                                        \
-    (__v) = (struct nrf52_hal_i2c *) nrf52_hal_i2cs[(__n)];  \
-    if ((__v) == NULL) {                                     \
-        rc = EINVAL;                                         \
-        goto err;                                            \
-    }
-
 struct nrf52_hal_i2c {
     NRF_TWI_Type *nhi_regs;
 };
@@ -72,7 +62,7 @@ struct nrf52_hal_i2c hal_twi_i2c1 = {
 };
 #endif
 
-static const struct nrf52_hal_i2c *nrf52_hal_i2cs[NRF52_HAL_I2C_MAX] = {
+static struct nrf52_hal_i2c *nrf52_hal_i2cs[NRF52_HAL_I2C_MAX] = {
 #if MYNEWT_VAL(I2C_0)
     &hal_twi_i2c0,
 #else
@@ -162,6 +152,39 @@ __ASM volatile (
     : "+r" (delay));
 }
 
+static int
+hal_i2c_resolve(uint8_t i2c_num, struct nrf52_hal_i2c **out_i2c)
+{
+    if (i2c_num >= NRF52_HAL_I2C_MAX) {
+        *out_i2c = NULL;
+        return HAL_I2C_ERR_INVAL;
+    }
+
+    *out_i2c = nrf52_hal_i2cs[i2c_num];
+    if (*out_i2c == NULL) {
+        return HAL_I2C_ERR_INVAL;
+    }
+
+    return 0;
+}
+
+/**
+ * Converts an nRF SDK I2C status to a HAL I2C error code.
+ */
+static int
+hal_i2c_convert_status(int nrf_status)
+{
+    if (nrf_status == 0) {
+        return 0;
+    } else if (nrf_status & NRF_TWIM_ERROR_DATA_NACK) {
+        return HAL_I2C_ERR_DATA_NACK;
+    } else if (nrf_status & NRF_TWIM_ERROR_ADDRESS_NACK) {
+        return HAL_I2C_ERR_ADDR_NACK;
+    } else {
+        return HAL_I2C_ERR_UNKNOWN;
+    }
+}
+
 /**
  * Reads the input buffer of the specified pin regardless
  * of if it is set as output or input
@@ -242,7 +265,10 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
 
     assert(usercfg != NULL);
 
-    NRF52_HAL_I2C_RESOLVE(i2c_num, i2c);
+    rc = hal_i2c_resolve(i2c_num, &i2c);
+    if (rc != 0) {
+        goto err;
+    }
 
     cfg = (struct nrf52_hal_i2c_cfg *) usercfg;
     regs = i2c->nhi_regs;
@@ -258,7 +284,7 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
         freq = TWI_FREQUENCY_FREQUENCY_K400;
         break;
     default:
-        rc = EINVAL;
+        rc = HAL_I2C_ERR_INVAL;
         goto err;
     }
 
@@ -286,18 +312,20 @@ hal_i2c_master_write(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
                      uint32_t timo, uint8_t last_op)
 {
     struct nrf52_hal_i2c *i2c;
-    NRF_TWI_Type *regs = NULL;
-    int rc = -1;
+    NRF_TWI_Type *regs;
+    int nrf_status;
+    int rc;
     int i;
     uint32_t start;
-    int retry_once = 1;
 
-    NRF52_HAL_I2C_RESOLVE(i2c_num, i2c);
+    rc = hal_i2c_resolve(i2c_num, &i2c);
+    if (rc != 0) {
+        return rc;
+    }
     regs = i2c->nhi_regs;
 
     regs->ADDRESS = pdata->address;
 
-retry:
     regs->EVENTS_ERROR = 0;
     regs->EVENTS_STOPPED = 0;
     regs->EVENTS_SUSPENDED = 0;
@@ -312,20 +340,8 @@ hal_i2c_master_write(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
         regs->TXD = pdata->buffer[i];
         while (!regs->EVENTS_TXDSENT && !regs->EVENTS_ERROR) {
             if (os_time_get() - start > timo) {
-                regs->TASKS_STOP = 1;
-                if (retry_once) {
-                   /* 
-                    * Some I2C slave peripherals cause a glitch on the bus when
-                    * they reset which puts the TWI in an unresponsive state.
-                    * Disabling and re-enabling the TWI returns it to normal 
operation.
-                    */
-                    retry_once = 0;
-                    regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
-                    regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
-                    goto retry;
-                } else {
-                    goto err;
-                }
+                rc = HAL_I2C_ERR_TIMEOUT;
+                goto err;
             }
         }
         if (regs->EVENTS_ERROR) {
@@ -338,6 +354,7 @@ hal_i2c_master_write(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
         regs->TASKS_STOP = 1;
         while (!regs->EVENTS_STOPPED && !regs->EVENTS_ERROR) {
             if (os_time_get() - start > timo) {
+                rc = HAL_I2C_ERR_TIMEOUT;
                 goto err;
             }
         }
@@ -345,13 +362,25 @@ hal_i2c_master_write(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
             goto err;
         }
     }
-    return (0);
+
+    rc = 0;
+
 err:
-    if (regs && regs->EVENTS_ERROR) {
-        rc = regs->ERRORSRC;
-        regs->TASKS_STOP = 1;
-        regs->ERRORSRC = rc;
+    regs->TASKS_STOP = 1;
+
+    if (regs->EVENTS_ERROR) {
+        nrf_status = regs->ERRORSRC;
+        regs->ERRORSRC = nrf_status;
+        rc = hal_i2c_convert_status(nrf_status);
+    } else if (rc == HAL_I2C_ERR_TIMEOUT) {
+       /* Some I2C slave peripherals cause a glitch on the bus when they
+        * reset which puts the TWI in an unresponsive state.  Disabling and
+        * re-enabling the TWI returns it to normal operation.
+        */
+        regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
+        regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
     }
+
     return (rc);
 }
 
@@ -360,16 +389,18 @@ hal_i2c_master_read(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
                     uint32_t timo, uint8_t last_op)
 {
     struct nrf52_hal_i2c *i2c;
-    NRF_TWI_Type *regs = NULL;
-    int rc = -1;
+    NRF_TWI_Type *regs;
+    int nrf_status;
+    int rc;
     int i;
     uint32_t start;
-    int retry_once = 1;
 
-    NRF52_HAL_I2C_RESOLVE(i2c_num, i2c);
+    rc = hal_i2c_resolve(i2c_num, &i2c);
+    if (rc != 0) {
+        return rc;
+    }
     regs = i2c->nhi_regs;
 
-retry:
     start = os_time_get();
 
     if (regs->EVENTS_RXDREADY) {
@@ -397,21 +428,8 @@ hal_i2c_master_read(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
         regs->TASKS_RESUME = 1;
         while (!regs->EVENTS_RXDREADY && !regs->EVENTS_ERROR) {
             if (os_time_get() - start > timo) {
-                regs->SHORTS = TWI_SHORTS_BB_STOP_Msk;
-                regs->TASKS_STOP = 1;
-                if (retry_once) {
-                   /* 
-                    * Some I2C slave peripherals cause a glitch on the bus when
-                    * they reset which puts the TWI in an unresponsive state.
-                    * Disabling and re-enabling the TWI returns it to normal 
operation.
-                    */
-                    retry_once = 0;
-                    regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
-                    regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
-                    goto retry;
-                } else {
-                    goto err;
-                }
+                rc = HAL_I2C_ERR_TIMEOUT;
+                goto err;
             }
         }
         if (regs->EVENTS_ERROR) {
@@ -425,13 +443,26 @@ hal_i2c_master_read(uint8_t i2c_num, struct 
hal_i2c_master_data *pdata,
         }
         regs->EVENTS_RXDREADY = 0;
     }
+
     return (0);
+
 err:
-    if (regs && regs->EVENTS_ERROR) {
-        rc = regs->ERRORSRC;
-        regs->TASKS_STOP = 1;
-        regs->ERRORSRC = rc;
+    regs->TASKS_STOP = 1;
+    regs->SHORTS = TWI_SHORTS_BB_STOP_Msk;
+
+    if (regs->EVENTS_ERROR) {
+        nrf_status = regs->ERRORSRC;
+        regs->ERRORSRC = nrf_status;
+        rc = hal_i2c_convert_status(nrf_status);
+    } else if (rc == HAL_I2C_ERR_TIMEOUT) {
+       /* Some I2C slave peripherals cause a glitch on the bus when they
+        * reset which puts the TWI in an unresponsive state.  Disabling and
+        * re-enabling the TWI returns it to normal operation.
+        */
+        regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
+        regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
     }
+
     return (rc);
 }
 
diff --git a/hw/util/i2cn/include/i2cn/i2cn.h b/hw/util/i2cn/include/i2cn/i2cn.h
new file mode 100644
index 0000000000..f5f762db8d
--- /dev/null
+++ b/hw/util/i2cn/include/i2cn/i2cn.h
@@ -0,0 +1,52 @@
+#ifndef H_I2CN_
+#define H_I2CN_
+
+#include <inttypes.h>
+#include "os/mynewt.h"
+struct hal_i2c_master_data;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Reads from an I2C slave, retrying the specified number of times on
+ * failure.
+ *
+ * @param i2c_num               The index of the I2C interface to read from.
+ * @param pdata                 Additional parameters describing the read
+ *                                  operation.
+ * @param timeout               The time, in OS ticks, to wait for the MCU to
+ *                                  indicate completion of each clocked byte.
+ * @param last_op               1 if this is the final message in the
+ *                                  transaction.
+ *
+ * @return                      0 on success;
+ *                              HAL_I2C_ERR_[...] code on failure.
+ */
+int i2cn_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                     uint32_t timeout, uint8_t last_op, int retries);
+
+/**
+ * @brief Writes to an I2C slave, retrying the specified number of times on
+ * failure.
+ *
+ * @param i2c_num               The index of the I2C interface to write to.
+ * @param pdata                 Additional parameters describing the write
+ *                                  operation.
+ * @param timeout               The time, in OS ticks, to wait for the MCU to
+ *                                  indicate completion of each clocked byte.
+ * @param last_op               1 if this is the final message in the
+ *                                  transaction.
+ *
+ * @return                      0 on success;
+ *                              HAL_I2C_ERR_[...] code on failure.
+ */
+int i2cn_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                      uint32_t timeout, uint8_t last_op, int retries);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hw/util/i2cn/pkg.yml b/hw/util/i2cn/pkg.yml
new file mode 100644
index 0000000000..c28ca6e556
--- /dev/null
+++ b/hw/util/i2cn/pkg.yml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/util/i2cn
+pkg.description: 'I2C-N: I2C operations with N retries.'
+pkg.author: "Apache Mynewt <d...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/hal"
diff --git a/hw/util/i2cn/src/i2cn.c b/hw/util/i2cn/src/i2cn.c
new file mode 100644
index 0000000000..f6d4234f7c
--- /dev/null
+++ b/hw/util/i2cn/src/i2cn.c
@@ -0,0 +1,46 @@
+#include "hal/hal_i2c.h"
+#include "i2cn/i2cn.h"
+
+int
+i2cn_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                 uint32_t timeout, uint8_t last_op, int retries)
+{
+    int rc;
+    int i;
+
+    /* Ensure at least one try. */
+    if (retries < 0) {
+        retries = 0;
+    }
+
+    for (i = 0; i <= retries; i++) {
+        rc = hal_i2c_master_read(i2c_num, pdata, timeout, last_op);
+        if (rc == 0) {
+            break;
+        }
+    }
+
+    return rc;
+}
+
+int
+i2cn_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                  uint32_t timeout, uint8_t last_op, int retries)
+{
+    int rc;
+    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, pdata, timeout, last_op);
+        if (rc == 0) {
+            break;
+        }
+    }
+
+    return rc;
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to