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:51 UTC

[mynewt-core] branch dma_i2c created (now cbebd27)

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

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


      at cbebd27  add logs

This branch includes the following new commits:

     new b64e94a  Initial commit dma i2c
     new 3851097  fix prototype and console_printf
     new 1f81ac8   fixes
     new 2a6e316  fix address compare for transact_end
     new bab654e  revert bq27z561 changes to break up transactions
     new cbebd27  add logs

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[mynewt-core] 02/06: fix prototype and console_printf

Posted by vi...@apache.org.
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 38510971cea6c0369aea1197a294b5b2d081b7f8
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Thu Oct 18 14:13:35 2018 -0700

    fix prototype and console_printf
---
 hw/mcu/nordic/nrf52xxx/src/hal_i2c.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index b19e2ad..10e59d7 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -33,8 +33,11 @@
 #define I2C_WRITE 0
 #define I2C_READ  1
 
-#define WAIT_FOR_EVT(__r, __e)\
+#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;\
@@ -353,12 +356,12 @@ hal_i2c_handle_transact_start(struct nrf52_hal_i2c *i2c, uint8_t op,
     if (op == I2C_WRITE) {
         /* Start an I2C transmit transaction */
         regs->TASKS_STARTTX = 1;
-        WAIT_FOR_EVT(regs, TXSTARTED);
+        WAIT_FOR_EVT(regs, TXSTARTED, op);
         regs->EVENTS_TXSTARTED = 0;
     } else {
         /* Start an I2C receive transaction */
         regs->TASKS_STARTRX = 1;
-        WAIT_FOR_EVT(regs, RXSTARTED);
+        WAIT_FOR_EVT(regs, RXSTARTED, op);
         regs->EVENTS_RXSTARTED = 0;
     }
 
@@ -368,9 +371,8 @@ err:
 }
 
 static int
-hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint32_t start,
-                            uint32_t abs_timo, uint8_t last_op,
-                            uint8_t op)
+hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
+                            uint32_t abs_timo, uint8_t last_op)
 {
     int rc;
     uint32_t evt;
@@ -399,7 +401,7 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint32_t start,
         }
 
         if (evt) {
-            if (evt == regs->EVENTS_STOPPED) {
+            if (&evt == &regs->EVENTS_STOPPED) {
                 regs->EVENTS_LASTTX = 0;
                 regs->EVENTS_LASTRX = 0;
             }
@@ -410,6 +412,11 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, 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;
@@ -437,8 +444,9 @@ 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)) {
+    } else if ((i2c->nhi_prev_last_op == 1 &&
+               !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
@@ -450,6 +458,8 @@ hal_i2c_bus_error_detect(struct nrf52_hal_i2c *i2c)
 
     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;
 }
 


[mynewt-core] 01/06: Initial commit dma i2c

Posted by vi...@apache.org.
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 b64e94aa169e64a146cf88150ef68b5da1a4c57d
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Wed Oct 17 12:58:20 2018 -0700

    Initial commit dma i2c
---
 hw/drivers/sensors/tsl2561/src/tsl2561_shell.c |   2 +-
 hw/hal/include/hal/hal_i2c.h                   |   9 +
 hw/mcu/nordic/nrf52xxx/src/hal_i2c.c           | 376 +++++++++++++++++--------
 3 files changed, 273 insertions(+), 114 deletions(-)

diff --git a/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c b/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c
index 71201e6..169e9c3 100644
--- a/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c
+++ b/hw/drivers/sensors/tsl2561/src/tsl2561_shell.c
@@ -348,7 +348,7 @@ tsl2561_shell_cmd_en(int argc, char **argv)
     /* Update the enable state */
     if (argc == 3) {
         lval = strtol(argv[2], &endptr, 10); /* Base 10 */
-        if (argv[2] != '\0' && *endptr == '\0' &&
+        if (*argv[2] != '\0' && *endptr == '\0' &&
             lval >= 0 && lval <= 1) {
             rc = tsl2561_enable(&g_sensor_itf, lval);
             if (rc) {
diff --git a/hw/hal/include/hal/hal_i2c.h b/hw/hal/include/hal/hal_i2c.h
index be080ca..50fd1df 100644
--- a/hw/hal/include/hal/hal_i2c.h
+++ b/hw/hal/include/hal/hal_i2c.h
@@ -79,6 +79,15 @@ extern "C" {
 /** Slave responded to data byte with NACK. */
 #define HAL_I2C_ERR_DATA_NACK           5
 
+/** Overrun error */
+#define HAL_I2C_ERR_OVERRUN             6
+
+/** 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   */
+#define HAL_I2C_ERR_STOP                8
+
 /**
  * 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 b925394..b19e2ad 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -26,9 +26,22 @@
 #include <hal/hal_gpio.h>
 #include <mcu/nrf52_hal.h>
 #include "nrf_twim.h"
+#include <console/console.h>
 
 #include <nrf.h>
 
+#define I2C_WRITE 0
+#define I2C_READ  1
+
+#define WAIT_FOR_EVT(__r, __e)\
+    while (!(__r)->EVENTS_####__e) {\
+        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                                              \
@@ -48,17 +61,22 @@
 #define NRF52_SDA_PIN_CONF_CLR    NRF52_SCL_PIN_CONF_CLR
 
 struct nrf52_hal_i2c {
-    NRF_TWI_Type *nhi_regs;
+    NRF_TWIM_Type *nhi_regs;
+    /*
+     * previous last_op, this is just to check if the previous
+     * transaction actually put the I2C bus in the suspended state
+     */
+    int nhi_prev_last_op;
 };
 
 #if MYNEWT_VAL(I2C_0)
 struct nrf52_hal_i2c hal_twi_i2c0 = {
-    .nhi_regs = NRF_TWI0
+    .nhi_regs = NRF_TWIM0
 };
 #endif
 #if MYNEWT_VAL(I2C_1)
 struct nrf52_hal_i2c hal_twi_i2c1 = {
-    .nhi_regs = NRF_TWI1
+    .nhi_regs = NRF_TWIM1
 };
 #endif
 
@@ -180,6 +198,8 @@ hal_i2c_convert_status(int nrf_status)
         return HAL_I2C_ERR_DATA_NACK;
     } else if (nrf_status & NRF_TWIM_ERROR_ADDRESS_NACK) {
         return HAL_I2C_ERR_ADDR_NACK;
+    } else if (nrf_status & TWIM_ERRORSRC_OVERRUN_Msk) {
+        return HAL_I2C_ERR_OVERRUN;
     } else {
         return HAL_I2C_ERR_UNKNOWN;
     }
@@ -257,7 +277,7 @@ int
 hal_i2c_init(uint8_t i2c_num, void *usercfg)
 {
     struct nrf52_hal_i2c *i2c;
-    NRF_TWI_Type *regs;
+    NRF_TWIM_Type *regs;
     struct nrf52_hal_i2c_cfg *cfg;
     uint32_t freq;
     int rc;
@@ -275,13 +295,13 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
 
     switch (cfg->i2c_frequency) {
     case 100:
-        freq = TWI_FREQUENCY_FREQUENCY_K100;
+        freq = TWIM_FREQUENCY_FREQUENCY_K100;
         break;
     case 250:
-        freq = TWI_FREQUENCY_FREQUENCY_K250;
+        freq = TWIM_FREQUENCY_FREQUENCY_K250;
         break;
     case 400:
-        freq = TWI_FREQUENCY_FREQUENCY_K400;
+        freq = TWIM_FREQUENCY_FREQUENCY_K400;
         break;
     default:
         rc = HAL_I2C_ERR_INVAL;
@@ -297,179 +317,309 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
     scl_port->PIN_CNF[cfg->scl_pin] = NRF52_SCL_PIN_CONF;
     sda_port->PIN_CNF[cfg->sda_pin] = NRF52_SDA_PIN_CONF;
 
-    regs->PSELSCL = cfg->scl_pin;
-    regs->PSELSDA = cfg->sda_pin;
+    regs->PSEL.SCL = cfg->scl_pin;
+    regs->PSEL.SDA = cfg->sda_pin;
     regs->FREQUENCY = freq;
-    regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
+    regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
+    i2c->nhi_prev_last_op = -1;
 
     return (0);
 err:
     return (rc);
 }
 
-int
-hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
-                     uint32_t timo, uint8_t last_op)
+/*
+ * 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)
 {
-    struct nrf52_hal_i2c *i2c;
-    NRF_TWI_Type *regs;
-    int nrf_status;
+    NRF_TWIM_Type *regs;
+    uint32_t now;
     int rc;
-    int i;
-    uint32_t start;
 
-    rc = hal_i2c_resolve(i2c_num, &i2c);
-    if (rc != 0) {
-        return rc;
-    }
     regs = i2c->nhi_regs;
 
-    regs->ADDRESS = pdata->address;
-
     regs->EVENTS_ERROR = 0;
+
+    /* If a transaction was previously suspended, resume it */
+    if (regs->EVENTS_SUSPENDED) {
+        regs->TASKS_RESUME = 1;
+    }
+
     regs->EVENTS_STOPPED = 0;
     regs->EVENTS_SUSPENDED = 0;
-    regs->SHORTS = 0;
+    if (op == I2C_WRITE) {
+        /* Start an I2C transmit transaction */
+        regs->TASKS_STARTTX = 1;
+        WAIT_FOR_EVT(regs, TXSTARTED);
+        regs->EVENTS_TXSTARTED = 0;
+    } else {
+        /* Start an I2C receive transaction */
+        regs->TASKS_STARTRX = 1;
+        WAIT_FOR_EVT(regs, RXSTARTED);
+        regs->EVENTS_RXSTARTED = 0;
+    }
 
-    regs->TASKS_STARTTX = 1;
-    regs->TASKS_RESUME = 1;
+    return 0;
+err:
+    return rc;
+}
 
-    start = os_time_get();
-    for (i = 0; i < pdata->len; i++) {
-        regs->EVENTS_TXDSENT = 0;
-        regs->TXD = pdata->buffer[i];
-        while (!regs->EVENTS_TXDSENT && !regs->EVENTS_ERROR) {
-            if (os_time_get() - start > timo) {
-                rc = HAL_I2C_ERR_TIMEOUT;
-                goto err;
-            }
-        }
-        if (regs->EVENTS_ERROR) {
-            goto err;
+static int
+hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint32_t start,
+                            uint32_t abs_timo, uint8_t last_op,
+                            uint8_t 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;
         }
     }
-    /* If last_op is zero it means we dont put a stop at end. */
-    if (last_op) {
-        regs->EVENTS_STOPPED = 0;
-        regs->TASKS_STOP = 1;
-        while (!regs->EVENTS_STOPPED && !regs->EVENTS_ERROR) {
-            if (os_time_get() - start > timo) {
-                rc = HAL_I2C_ERR_TIMEOUT;
-                goto err;
+
+    while(1) {
+        /*
+         * Use last_op as the determining factor for the type of event to be
+         * monitored
+         */
+        if (last_op) {
+            evt = regs->EVENTS_STOPPED;
+        } else {
+            evt = regs->EVENTS_SUSPENDED;
+        }
+
+        if (evt) {
+            if (evt == regs->EVENTS_STOPPED) {
+                regs->EVENTS_LASTTX = 0;
+                regs->EVENTS_LASTRX = 0;
             }
+            break;
         }
+
         if (regs->EVENTS_ERROR) {
             goto err;
         }
+
+        now = os_time_get();
+        if (OS_TIME_TICK_GT(now, abs_timo)) {
+            rc = HAL_I2C_ERR_TIMEOUT;
+            goto err;
+        }
     }
 
-    rc = 0;
+    return 0;
+err:
+    return rc;
+}
+
+static int
+hal_i2c_bus_error_detect(struct nrf52_hal_i2c *i2c)
+{
+    int rc;
+    NRF_TWIM_Type *regs;
+
+    regs = i2c->nhi_regs;
+
+    if (i2c->nhi_prev_last_op == 0 && !regs->EVENTS_SUSPENDED) {
+        /*
+         * return HAL_I2C_ERR_SUSPEND if previous last_op was 0 and
+         * the bus was not in the suspended state
+         */
+        rc = HAL_I2C_ERR_SUSPEND;
+        goto err;
+    } else if (i2c->nhi_prev_last_op  == 1 &&
+               (!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
+         * which is EVENTS_SUSPENDED is 1 and EVENTS_STOPPED is 1
+         */
+        rc = HAL_I2C_ERR_STOP;
+        goto err;
+    }
 
+    return 0;
 err:
+    return rc;
+}
+
+/* Handle errors returned from the TWIM peripheral along with timeouts */
+static int
+hal_i2c_handle_errors(NRF_TWIM_Type *regs, int rc)
+{
+    int nrf_status;
+
+    regs->TASKS_RESUME = 1;
     regs->TASKS_STOP = 1;
 
     if (regs->EVENTS_ERROR) {
+        regs->EVENTS_ERROR = 0;
         nrf_status = regs->ERRORSRC;
         regs->ERRORSRC = nrf_status;
         rc = hal_i2c_convert_status(nrf_status);
-    } else if (rc == HAL_I2C_ERR_TIMEOUT) {
+    } else if (rc) {
         /* Some I2C slave peripherals cause a glitch on the bus when they
-         * reset which puts the TWI in an unresponsive state.  Disabling and
+         * reset which puts the TWI in an unresponsive state. Disabling and
          * re-enabling the TWI returns it to normal operation.
          * A clear operation is performed in case one of the devices on
          * the bus is in a bad state.
          */
-        regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
-        hal_i2c_clear_bus(regs->PSELSCL, regs->PSELSDA);
-        regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
+        regs->ENABLE = TWIM_ENABLE_ENABLE_Disabled;
+        hal_i2c_clear_bus(regs->PSEL.SCL, regs->PSEL.SDA);
+        regs->ENABLE = TWIM_ENABLE_ENABLE_Enabled;
     }
 
-    return (rc);
+    return rc;
 }
 
+/* Perform I2C master writes using TWIM/EasyDMA */
 int
-hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
-                    uint32_t timo, uint8_t last_op)
+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;
-    int nrf_status;
     int rc;
-    int i;
     uint32_t start;
+    NRF_TWIM_Type *regs;
+    struct nrf52_hal_i2c *i2c;
 
+    start = os_time_get();
+
+    /* Resolve the I2C bus */
     rc = hal_i2c_resolve(i2c_num, &i2c);
     if (rc != 0) {
         return rc;
     }
+
     regs = i2c->nhi_regs;
 
-    start = os_time_get();
+    /* Detect errors on the bus based on the previous and current
+     * condition of the bus
+     */
+    rc = hal_i2c_bus_error_detect(i2c);
+    if (rc) {
+        goto err;
+    }
 
-    if (regs->EVENTS_RXDREADY) {
-        /*
-         * If previous read was interrupted, flush RXD.
+    /* Configure the TXD registers for EasyDMA access to work with buffers of
+     * specific length and address of the slave
+     */
+    regs->ADDRESS    = pdata->address;
+    regs->TXD.MAXCNT = pdata->len;
+    regs->TXD.PTR    = (uint32_t)pdata->buffer;
+    regs->TXD.LIST   = 0;
+    /* Disable and clear interrupts */
+    regs->INTENCLR   = NRF_TWIM_ALL_INTS_MASK;
+    regs->INTEN      = 0;
+
+    /* Setup shorts to end transaction based on last_op,
+     * 0 : STOP transaction,
+     * 1 : SUSPEND transaction
+     */
+    if (last_op) {
+        /* EVENT_STOPPED would get set after LASTTX gets set at
+         * the end of the transaction for the last byte
+         */
+        regs->SHORTS = TWIM_SHORTS_LASTTX_STOP_Msk;
+    } else {
+        /* EVENT_SUSPENDED would get set after LASTTX gets set at
+         * the end of the transaction for the last byte
          */
-        (void)regs->RXD;
-        (void)regs->RXD;
+        regs->SHORTS = TWIM_SHORTS_LASTTX_SUSPEND_Msk;
     }
-    regs->EVENTS_ERROR = 0;
-    regs->EVENTS_STOPPED = 0;
-    regs->EVENTS_SUSPENDED = 0;
-    regs->EVENTS_RXDREADY = 0;
 
-    regs->ADDRESS = pdata->address;
-
-    if (pdata->len == 1 && last_op) {
-        regs->SHORTS = TWI_SHORTS_BB_STOP_Msk;
-    } else {
-        regs->SHORTS = TWI_SHORTS_BB_SUSPEND_Msk;
+    /* Starts an I2C transaction using TWIM/EasyDMA */
+    rc = hal_i2c_handle_transact_start(i2c, I2C_WRITE, start + timo);
+    if (rc) {
+        goto err;
     }
-    regs->TASKS_STARTRX = 1;
 
-    for (i = 0; i < pdata->len; i++) {
-        regs->TASKS_RESUME = 1;
-        while (!regs->EVENTS_RXDREADY && !regs->EVENTS_ERROR) {
-            if (os_time_get() - start > timo) {
-                rc = HAL_I2C_ERR_TIMEOUT;
-                goto err;
-            }
-        }
-        if (regs->EVENTS_ERROR) {
-            goto err;
-        }
-        pdata->buffer[i] = regs->RXD;
-        if (i == pdata->len - 2) {
-            if (last_op) {
-                regs->SHORTS = TWI_SHORTS_BB_STOP_Msk;
-            }
-        }
-        regs->EVENTS_RXDREADY = 0;
+    /* Ends an I2C transaction using TWIM/EasyDMA */
+    rc = hal_i2c_handle_transact_end(regs, I2C_WRITE, start, start + timo, last_op);
+    if (rc) {
+        goto err;
     }
 
-    return (0);
+    /* Save the current last op to detect bus errors later */
+    i2c->nhi_prev_last_op = last_op;
 
+    return 0;
 err:
-    regs->TASKS_STOP = 1;
-    regs->SHORTS = TWI_SHORTS_BB_STOP_Msk;
+    return hal_i2c_handle_errors(regs, rc);
+}
 
-    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.
-        * A clear operation is performed in case one of the devices on
-        * the bus is in a bad state.
-        */
-        regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
-        hal_i2c_clear_bus(regs->PSELSCL, regs->PSELSDA);
-        regs->ENABLE = TWI_ENABLE_ENABLE_Enabled;
+int
+hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
+                    uint32_t timo, uint8_t last_op)
+{
+    int rc;
+    uint32_t start;
+    NRF_TWIM_Type *regs;
+    struct nrf52_hal_i2c *i2c;
+
+    start = os_time_get();
+
+    /* Resolve the I2C bus */
+    rc = hal_i2c_resolve(i2c_num, &i2c);
+    if (rc != 0) {
+        return rc;
     }
 
-    return (rc);
+    regs = i2c->nhi_regs;
+
+    /* Detect errors on the bus based on the previous and current
+     * condition of the bus
+     */
+    rc = hal_i2c_bus_error_detect(i2c);
+    if (rc) {
+        goto err;
+    }
+
+    /* Configure the RXD registers for EasyDMA access to work with buffers of
+     * specific length and address of the slave
+     */
+    regs->ADDRESS    = pdata->address;
+    regs->RXD.MAXCNT = pdata->len;
+    regs->RXD.PTR    = (uint32_t)pdata->buffer;
+    regs->RXD.LIST   = 0;
+    /* Disable and clear interrupts */
+    regs->INTENCLR   = NRF_TWIM_ALL_INTS_MASK;
+    regs->INTEN      = 0;
+
+    /* Only set short for RX->STOP for last_op:1 since there is no suspend short
+     * available in nrf52832
+     */
+    if (last_op) {
+        regs->SHORTS = TWIM_SHORTS_LASTRX_STOP_Msk;
+    }
+
+    /* Starts an I2C transaction using TWIM/EasyDMA */
+    rc = hal_i2c_handle_transact_start(i2c, I2C_READ, start + timo);
+    if (rc) {
+        goto err;
+    }
+
+    /* Ends an I2C transaction using TWIM/EasyDMA */
+    rc = hal_i2c_handle_transact_end(regs, I2C_READ, start, start + timo, last_op);
+    if (rc) {
+        goto err;
+    }
+
+    /* Save the current last op to detect bus errors later */
+    i2c->nhi_prev_last_op = last_op;
+
+    return 0;
+err:
+    return hal_i2c_handle_errors(regs, rc);
 }
 
 int


[mynewt-core] 06/06: add logs

Posted by vi...@apache.org.
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 cbebd2798b08bfcdca82ac9f09f2410446e3a2dc
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Wed Oct 24 20:00:17 2018 -0700

    add logs
---
 hw/mcu/nordic/nrf52xxx/src/hal_i2c.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 5a81e86..c2c5e71 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -391,13 +391,15 @@ hal_i2c_handle_transact_start(struct nrf52_hal_i2c *i2c, uint8_t op,
     return 0;
 }
 
+os_time_t g_start;
+
 static int
 hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
                             os_time_t abs_timo, uint8_t last_op)
 {
     int rc;
     volatile uint32_t *evt;
-    os_time_t now;
+    os_time_t now = 0;
 
     while(1) {
         /*
@@ -432,6 +434,10 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
         }
     }
 
+    g_start = os_cputime_get32() - g_start;
+
+    console_printf("t:%lu r:%u\n", g_start, op);
+
     return 0;
 err:
     return rc;
@@ -510,6 +516,8 @@ hal_i2c_handle_errors(struct nrf52_hal_i2c *i2c, int rc, os_time_t abs_timo)
     return rc;
 }
 
+os_time_t g_start;
+
 /* Perform I2C master writes using TWIM/EasyDMA */
 int
 hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
@@ -521,6 +529,7 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
     struct nrf52_hal_i2c *i2c;
 
     start = os_time_get();
+    g_start = os_cputime_get32();
 
     /* Resolve the I2C bus */
     rc = hal_i2c_resolve(i2c_num, &i2c);
@@ -595,6 +604,7 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
     struct nrf52_hal_i2c *i2c;
 
     start = os_time_get();
+    g_start = os_cputime_get32();
 
     /* Resolve the I2C bus */
     rc = hal_i2c_resolve(i2c_num, &i2c);


[mynewt-core] 05/06: revert bq27z561 changes to break up transactions

Posted by vi...@apache.org.
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 bab654edbb4f3c2d1ff4c5e8365034545a63ea43
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Mon Oct 22 16:26:12 2018 -0700

    revert bq27z561 changes to break up transactions
    
    - not needed
---
 hw/drivers/bq27z561/src/bq27z561.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/drivers/bq27z561/src/bq27z561.c b/hw/drivers/bq27z561/src/bq27z561.c
index 9494d3b..2ab06dd 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), 1,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
                            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), 1,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
                            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), 1,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
                            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), 1,
+    rc = i2cn_master_write(dev->bq27_itf.itf_num, &i2c, MYNEWT_VAL(BQ27Z561_I2C_TIMEOUT_TICKS), 0,
                            MYNEWT_VAL(BQ27Z561_I2C_RETRIES));
     if (rc != 0) {
         BQ27Z561_LOG(ERROR, "I2C reg read (wr) failed 0x%02X\n", tmpbuf[0]);


[mynewt-core] 03/06: fixes

Posted by vi...@apache.org.
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)"


[mynewt-core] 04/06: fix address compare for transact_end

Posted by vi...@apache.org.
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 2a6e316fdfcbf5feccb683924d9903f0738f1fef
Author: Vipul Rahane <vi...@runtime.io>
AuthorDate: Mon Oct 22 16:21:03 2018 -0700

    fix address compare for transact_end
---
 hw/mcu/nordic/nrf52xxx/src/hal_i2c.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 133e330..5a81e86 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -396,7 +396,7 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
                             os_time_t abs_timo, uint8_t last_op)
 {
     int rc;
-    uint32_t evt;
+    volatile uint32_t *evt;
     os_time_t now;
 
     while(1) {
@@ -405,13 +405,13 @@ hal_i2c_handle_transact_end(NRF_TWIM_Type *regs, uint8_t op, uint32_t start,
          * monitored
          */
         if (last_op) {
-            evt = regs->EVENTS_STOPPED;
+            evt = &regs->EVENTS_STOPPED;
         } else {
-            evt = regs->EVENTS_SUSPENDED;
+            evt = &regs->EVENTS_SUSPENDED;
         }
 
-        if (evt) {
-            if (&evt == &regs->EVENTS_STOPPED) {
+        if (*evt) {
+            if (evt == &regs->EVENTS_STOPPED) {
 #if MYNEWT_VAL(NRF52_HANDLE_ANOMALY_109)
                 if (regs->FREQUENCY) {
                     regs->FREQUENCY = 0;