You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by vi...@apache.org on 2018/10/25 03:00:54 UTC

[mynewt-core] 03/06: fixes

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

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

commit 1f81ac8d930c6f6acc3500cd578382c1fab86869
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Mon Oct 22 13:36:03 2018 -0700

     fixes
---
 hw/drivers/bq27z561/src/bq27z561.c         |   8 +-
 hw/drivers/sensors/lis2dw12/src/lis2dw12.c |  14 ++--
 hw/hal/include/hal/hal_i2c.h               |  26 +++++--
 hw/mcu/nordic/nrf52xxx/src/hal_i2c.c       | 116 +++++++++++++++++------------
 hw/mcu/nordic/nrf52xxx/syscfg.yml          |   4 +
 5 files changed, 100 insertions(+), 68 deletions(-)

diff --git a/hw/drivers/bq27z561/src/bq27z561.c b/hw/drivers/bq27z561/src/bq27z561.c
index 2ab06dd..9494d3b 100644
--- a/hw/drivers/bq27z561/src/bq27z561.c
+++ b/hw/drivers/bq27z561/src/bq27z561.c
@@ -142,7 +142,7 @@ bq27z561_rd_std_reg_byte(struct bq27z561 *dev, uint8_t reg, uint8_t *val)
     }
 
 
-    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
                            MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
@@ -178,7 +178,7 @@ bq27z561_rd_std_reg_word(struct bq27z561 *dev, uint8_t reg, uint16_t *val)
         return rc;
     }
 
-    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
                            MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", reg);
@@ -353,7 +353,7 @@ bq27x561_rd_alt_mfg_cmd(struct bq27z561 *dev, uint16_t cmd, uint8_t *val,
     i2c.len = 1;
     i2c.buffer = tmpbuf;
 
-    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
                            MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", tmpbuf[0]);
@@ -459,7 +459,7 @@ bq27x561_rd_flash(struct bq27z561 *dev, uint16_t addr, uint8_t *buf, int buflen)
     i2c.len = 1;
     i2c.buffer = tmpbuf;
 
-    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 1,
                            MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", tmpbuf[0]);
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
index bee8cf6..02deaab 100644
--- a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
@@ -235,8 +235,8 @@ lis2dw12_i2c_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *buffer,
     rc = i2cn_master_write(itf->si_num, &data_struct, MYNEWT_VAL(LIS2DW12_I2C_TIMEOUT_TICKS), 1,
                            MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
     if (rc) {
-        LIS2DW12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
-                     data_struct.address);
+        LIS2DW12_LOG(ERROR, "I2C write failed err=%d at addr:0x%02X:0x%02X\n",
+                     rc, data_struct.address, payload[0]);
         STATS_INC(g_lis2dw12stats, write_errors);
         goto err;
     }
@@ -290,7 +290,7 @@ lis2dw12_spi_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
         rc = hal_spi_tx_val(itf->si_num, payload[i]);
         if (rc == 0xFFFF) {
             rc = SYS_EINVAL;
-            LIS2DW12_LOG(ERROR, "SPI_%u write failed addr:0x%02X:0x%02X\n",
+            LIS2DW12_LOG(ERROR, "SPI_%u write failed addr:0x%02X\n",
                          itf->si_num, addr);
             STATS_INC(g_lis2dw12stats, write_errors);
             goto err;
@@ -365,8 +365,8 @@ lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer,
     rc = i2cn_master_write(itf->si_num, &data_struct, MYNEWT_VAL(LIS2DW12_I2C_TIMEOUT_TICKS), 1,
                            MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
     if (rc) {
-        LIS2DW12_LOG(ERROR, "I2C access failed at address 0x%02X\n",
-                     itf->si_addr);
+        LIS2DW12_LOG(ERROR, "I2C %u write failed at address 0x%02X:0x%02X\n",
+                     itf->si_num, itf->si_addr, reg);
         STATS_INC(g_lis2dw12stats, write_errors);
         return rc;
     }
@@ -378,8 +378,8 @@ lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer,
                           MYNEWT_VAL(LIS2DW12_I2C_RETRIES));
 
     if (rc) {
-        LIS2DW12_LOG(ERROR, "Failed to read from 0x%02X:0x%02X\n",
-                     itf->si_addr, reg);
+        LIS2DW12_LOG(ERROR, "I2C %u read failed at address 0x%02X:0x%02X\n",
+                     itf->si_num, itf->si_addr, reg);
         STATS_INC(g_lis2dw12stats, read_errors);
     }
 
diff --git a/hw/hal/include/hal/hal_i2c.h b/hw/hal/include/hal/hal_i2c.h
index 50fd1df..0d1173e 100644
--- a/hw/hal/include/hal/hal_i2c.h
+++ b/hw/hal/include/hal/hal_i2c.h
@@ -64,30 +64,40 @@ extern "C" {
 
 /*** I2C status codes (0=success). */
 
-/** Unknown error. */
+/* Unknown error. */
 #define HAL_I2C_ERR_UNKNOWN             1
 
-/** Invalid argument. */
+/* Invalid argument. */
 #define HAL_I2C_ERR_INVAL               2
 
-/** MCU failed to report result of I2C operation. */
+/* MCU failed to report result of I2C operation. */
 #define HAL_I2C_ERR_TIMEOUT             3
 
-/** Slave responded to address with NACK. */
+/* Slave responded to address with NACK. */
 #define HAL_I2C_ERR_ADDR_NACK           4
 
-/** Slave responded to data byte with NACK. */
+/* Slave responded to data byte with NACK. */
 #define HAL_I2C_ERR_DATA_NACK           5
 
-/** Overrun error */
+/* Overrun error */
 #define HAL_I2C_ERR_OVERRUN             6
 
-/** I2C bus in suspended state, but last op was 0 */
+/* I2C bus in suspended state, but last op was 0 */
 #define HAL_I2C_ERR_SUSPEND             7
 
-/** I2C bus in stopped state, but last op was 1   */
+/* I2C bus in stopped state, but last op was 1   */
 #define HAL_I2C_ERR_STOP                8
 
+/* At boot up or on facing an error I2C bus in
+ * suspended state
+ */
+#define HAL_I2C_ERR_INIT_SUSPEND        9
+
+/* At boot up or on facing an error I2C bus in
+ * suspended state
+ */
+#define HAL_I2C_ERR_INIT_STOP          10
+
 /**
  * When sending a packet, use this structure to pass the arguments.
  */
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 10e59d7..133e330 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -33,18 +33,6 @@
 #define I2C_WRITE 0
 #define I2C_READ  1
 
-#define WAIT_FOR_EVT(__r, __e, __op)\
-    while (!(__r)->EVENTS_####__e) {\
-        console_printf("while op: %u macro: STOPPED: %lu SUSPENDED: %lu LASTTX: %lu LASTRX: %lu\n",\
-                   __op, regs->EVENTS_STOPPED, regs->EVENTS_SUSPENDED, regs->EVENTS_LASTTX,\
-                   regs->EVENTS_LASTRX);\
-        now = os_time_get();\
-        if (OS_TIME_TICK_GT(now, abs_timo)) {\
-            rc = HAL_I2C_ERR_TIMEOUT;\
-            goto err;\
-        }\
-    }
-
 #define NRF52_HAL_I2C_MAX (2)
 
 #define NRF52_SCL_PIN_CONF                                              \
@@ -70,6 +58,7 @@ struct nrf52_hal_i2c {
      * transaction actually put the I2C bus in the suspended state
      */
     int nhi_prev_last_op;
+    uint32_t nhi_freq;
 };
 
 #if MYNEWT_VAL(I2C_0)
@@ -322,7 +311,13 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
 
     regs->PSEL.SCL = cfg->scl_pin;
     regs->PSEL.SDA = cfg->sda_pin;
+#if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
+    i2c->nhi_freq = freq;
+    regs->FREQUENCY = 0;
+#else
     regs->FREQUENCY = freq;
+#endif
+    regs->ADDRESS = 0;
     regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
     i2c->nhi_prev_last_op = -1;
 
@@ -331,64 +326,79 @@ err:
     return (rc);
 }
 
+static void
+hal_i2c_handle_anomaly_109(NRF_TWIM_Type *regs, uint32_t prev_freq, uint8_t address)
+{
+    if (regs->FREQUENCY == 0) {
+        regs->ENABLE = TWIM_ENABLE_ENABLE_Disabled;
+        regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
+        regs->ADDRESS = address;
+        regs->FREQUENCY = prev_freq;
+        regs->TASKS_STARTTX = 1;
+    }
+}
+
 /*
  * Starts an I2C transaction either read or write using EasyDMA/TWIM
  */
 static int
 hal_i2c_handle_transact_start(struct nrf52_hal_i2c *i2c, uint8_t op,
-                              uint32_t abs_timo)
+                              os_time_t abs_timo, uint8_t address)
 {
     NRF_TWIM_Type *regs;
-    uint32_t now;
+    os_time_t now;
     int rc;
 
     regs = i2c->nhi_regs;
 
     regs->EVENTS_ERROR = 0;
+    regs->EVENTS_STOPPED = 0;
 
     /* If a transaction was previously suspended, resume it */
     if (regs->EVENTS_SUSPENDED) {
         regs->TASKS_RESUME = 1;
+        regs->EVENTS_SUSPENDED = 0;
+        return 0;
     }
 
-    regs->EVENTS_STOPPED = 0;
-    regs->EVENTS_SUSPENDED = 0;
     if (op == I2C_WRITE) {
         /* Start an I2C transmit transaction */
         regs->TASKS_STARTTX = 1;
-        WAIT_FOR_EVT(regs, TXSTARTED, op);
+
+#if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
+        while (!regs->EVENTS_TXSTARTED) {
+            now = os_time_get();
+            if (OS_TIME_TICK_GT(now, abs_timo)) {
+                rc = HAL_I2C_ERR_TIMEOUT;
+                return rc;
+            }
+        }
+
         regs->EVENTS_TXSTARTED = 0;
+        if (!regs->FREQUENCY) {
+            hal_i2c_handle_anomaly_109(regs, i2c->nhi_freq, address);
+            regs->EVENTS_TXSTARTED = 0;
+        }
+#endif
     } else {
+        if (!regs->FREQUENCY) {
+            regs->FREQUENCY = i2c->nhi_freq;
+        }
         /* Start an I2C receive transaction */
         regs->TASKS_STARTRX = 1;
-        WAIT_FOR_EVT(regs, RXSTARTED, op);
-        regs->EVENTS_RXSTARTED = 0;
     }
 
     return 0;
-err:
-    return rc;
 }
 
 static int
 hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
-                            uint32_t abs_timo, uint8_t last_op)
+                            os_time_t abs_timo, uint8_t last_op)
 {
     int rc;
     uint32_t evt;
     os_time_t now;
 
-    if (last_op) {
-        /* this is to take care of clock stretches as per the datasheet */
-        if (regs->EVENTS_SUSPENDED) {
-            /* If there is a clock stretch, the event would be suspended for
-             * that TWIM interface, it would need to be resumed to finish the
-             * transaction
-             */
-            regs->TASKS_RESUME = 1;
-        }
-    }
-
     while(1) {
         /*
          * Use last_op as the determining factor for the type of event to be
@@ -402,8 +412,11 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
 
         if (evt) {
             if (&evt == &regs->EVENTS_STOPPED) {
-                regs->EVENTS_LASTTX = 0;
-                regs->EVENTS_LASTRX = 0;
+#if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
+                if (regs->FREQUENCY) {
+                    regs->FREQUENCY = 0;
+                }
+#endif
             }
             break;
         }
@@ -412,11 +425,6 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
             goto err;
         }
 
-        console_printf("while end: last_op: %u STOPPED: %lu SUSPENDED: %lu"
-                       "LASTTX: %lu LASTRX: %lu\n", last_op, regs->EVENTS_STOPPED,
-                       regs->EVENTS_SUSPENDED, regs->EVENTS_LASTTX,
-                       regs->EVENTS_LASTRX);
-
         now = os_time_get();
         if (OS_TIME_TICK_GT(now, abs_timo)) {
             rc = HAL_I2C_ERR_TIMEOUT;
@@ -445,8 +453,7 @@ hal_i2c_bus_error_detect(struct nrf52_hal_i2c *i2c)
         rc = HAL_I2C_ERR_SUSPEND;
         goto err;
     } else if ((i2c->nhi_prev_last_op == 1 &&
-               !regs->EVENTS_STOPPED) && regs->EVENTS_SUSPENDED) {
-
+               (!regs->EVENTS_STOPPED || regs->EVENTS_SUSPENDED))) {
         /*
          * return HAL_I2C_ERR_STOP if previous last_op was 1 and
          * the bus is not in the stopped state or in initial state
@@ -454,20 +461,29 @@ hal_i2c_bus_error_detect(struct nrf52_hal_i2c *i2c)
          */
         rc = HAL_I2C_ERR_STOP;
         goto err;
+    } else if (i2c->nhi_prev_last_op == -1 &&
+               (regs->EVENTS_STOPPED || regs->EVENTS_SUSPENDED)) {
+        if (regs->EVENTS_STOPPED) {
+            rc = HAL_I2C_ERR_INIT_STOP;
+        } else {
+            rc = HAL_I2C_ERR_INIT_SUSPEND;
+        }
+        goto err;
     }
 
     return 0;
 err:
-    console_printf("i2c failure: rc:%u evt_stopped: %lu evt_suspended: %lu\n",
-                   rc, regs->EVENTS_STOPPED, regs->EVENTS_SUSPENDED);
     return rc;
 }
 
 /* Handle errors returned from the TWIM peripheral along with timeouts */
 static int
-hal_i2c_handle_errors(NRF_TWIM_Type *regs, int rc)
+hal_i2c_handle_errors(struct nrf52_hal_i2c *i2c, int rc, os_time_t abs_timo)
 {
     int nrf_status;
+    NRF_TWIM_Type *regs;
+
+    regs = i2c->nhi_regs;
 
     regs->TASKS_RESUME = 1;
     regs->TASKS_STOP = 1;
@@ -487,6 +503,8 @@ hal_i2c_handle_errors(NRF_TWIM_Type *regs, int rc)
         regs->ENABLE = TWIM_ENABLE_ENABLE_Disabled;
         hal_i2c_clear_bus(regs->PSEL.SCL, regs->PSEL.SDA);
         regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
+        i2c->nhi_prev_last_op = -1;
+        regs->EVENTS_STOPPED = 0;
     }
 
     return rc;
@@ -548,7 +566,7 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
     }
 
     /* Starts an I2C transaction using TWIM/EasyDMA */
-    rc = hal_i2c_handle_transact_start(i2c, I2C_WRITE, start + timo);
+    rc = hal_i2c_handle_transact_start(i2c, I2C_WRITE, start + timo, pdata->address);
     if (rc) {
         goto err;
     }
@@ -564,7 +582,7 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
 
     return 0;
 err:
-    return hal_i2c_handle_errors(regs, rc);
+    return hal_i2c_handle_errors(i2c, rc, start + timo);
 }
 
 int
@@ -613,7 +631,7 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
     }
 
     /* Starts an I2C transaction using TWIM/EasyDMA */
-    rc = hal_i2c_handle_transact_start(i2c, I2C_READ, start + timo);
+    rc = hal_i2c_handle_transact_start(i2c, I2C_READ, start + timo, pdata->address);
     if (rc) {
         goto err;
     }
@@ -629,7 +647,7 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
 
     return 0;
 err:
-    return hal_i2c_handle_errors(regs, rc);
+    return hal_i2c_handle_errors(i2c, rc, start + timo);
 }
 
 int
diff --git a/hw/mcu/nordic/nrf52xxx/syscfg.yml b/hw/mcu/nordic/nrf52xxx/syscfg.yml
index 2028a3c..f90c32c 100644
--- a/hw/mcu/nordic/nrf52xxx/syscfg.yml
+++ b/hw/mcu/nordic/nrf52xxx/syscfg.yml
@@ -394,6 +394,10 @@ syscfg.defs:
             - "!XTAL_RC"
             - "!XTAL_32768"
 
+    NRF52_HANDLE_ANOMALY_109:
+        description: 'TWIM NRF52XXX anomaly 109 fix'
+        value: 1
+
 syscfg.restrictions:
     - "MCU_NRF52832 ^^ MCU_NRF52840"
     - "!I2C_0 || (I2C_0_PIN_SCL && I2C_0_PIN_SDA)"