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/05/23 01:15:12 UTC

[mynewt-core] branch master updated: Fix/nrf52 i2c hang (#1108)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 17279ad  Fix/nrf52 i2c hang (#1108)
17279ad is described below

commit 17279ad8a4ea38b6b3f95bf4e2054b8e0f013a48
Author: Ben McCrea <be...@users.noreply.github.com>
AuthorDate: Tue May 22 18:15:08 2018 -0700

    Fix/nrf52 i2c hang (#1108)
    
    * Workaround for TWI hang which can occur when slave exhibits bad behavior on the bus
    * Revise fix and comments for better clarity
---
 hw/mcu/nordic/nrf52xxx/src/hal_i2c.c | 33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 9104ad4..8ac5eea 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -290,12 +290,14 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
     int rc = -1;
     int i;
     uint32_t start;
+    int retry_once = 1;
 
     NRF52_HAL_I2C_RESOLVE(i2c_num, i2c);
     regs = i2c->nhi_regs;
 
     regs->ADDRESS = pdata->address;
 
+retry:
     regs->EVENTS_ERROR = 0;
     regs->EVENTS_STOPPED = 0;
     regs->EVENTS_SUSPENDED = 0;
@@ -311,7 +313,19 @@ hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
         while (!regs->EVENTS_TXDSENT && !regs->EVENTS_ERROR) {
             if (os_time_get() - start > timo) {
                 regs->TASKS_STOP = 1;
-                goto err;
+                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;
+                }
             }
         }
         if (regs->EVENTS_ERROR) {
@@ -350,10 +364,12 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
     int rc = -1;
     int i;
     uint32_t start;
+    int retry_once = 1;
 
     NRF52_HAL_I2C_RESOLVE(i2c_num, i2c);
     regs = i2c->nhi_regs;
 
+retry:
     start = os_time_get();
 
     if (regs->EVENTS_RXDREADY) {
@@ -379,12 +395,23 @@ hal_i2c_master_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
 
     for (i = 0; i < pdata->len; i++) {
         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;
-                goto err;
+                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;
+                }
             }
         }
         if (regs->EVENTS_ERROR) {

-- 
To stop receiving notification emails like this one, please contact
vipulrahane@apache.org.