You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2021/02/01 07:19:45 UTC

[mynewt-core] branch master updated (fdf1055 -> 8b7f0d2)

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

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


    from fdf1055  Add nucleo-l073rz BSP
     new 403e183  bus/i2c_da1469x: Fix race condition issue
     new 8b7f0d2  bus/i2c_da1469x: Small insignificant fixes

The 2 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.


Summary of changes:
 hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c | 41 ++++++++++++----------------
 1 file changed, 18 insertions(+), 23 deletions(-)


[mynewt-core] 01/02: bus/i2c_da1469x: Fix race condition issue

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 403e1835007f9c15deb89f27d16d93a67a94d2cb
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue Jan 5 15:21:23 2021 +0100

    bus/i2c_da1469x: Fix race condition issue
    
    STOP condition was correctly handled it could lead to
    cases when stop condition from previous transaction was
    detected later and disrupted code flow of next transfers.
    
    - i2c_da1469x_clear_int() was called after reading active interrupts
      but new interrupts could just pop up in after register was read.
      This is the case of stop condition interrupt that has to be clear
      by software. Now it is explicitly cleared when it was detected.
    - when interrupt was fired for M_RX_FULL and all data requested was
      read but stop condition was not detected yet. Transfer was finished
      even though NOSTOP flag was not set, and code should wait for
      stop M_STOP_DET. This lead to previous stop condition messing with
      next transfer.
    
    All this problem surfaced when system was running on 96MHz.
---
 hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c | 37 +++++++++++++---------------
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c b/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c
index 79aa2d6..084b762 100644
--- a/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c
+++ b/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c
@@ -180,7 +180,7 @@ i2c_da1469x_fill_tx_dma_buffer(struct i2c_da1469x_dev_data *dd)
             dd->tx_dma_buf[0] = I2C_I2C_DATA_CMD_REG_I2C_CMD_Msk |
                                 I2C_I2C_DATA_CMD_REG_I2C_STOP_Msk;
         } else {
-            /* Stop requested more send lentght - 1 without stop */
+            /* Stop requested more send length - 1 without stop */
             dd->tx_dma_buf[0] = I2C_I2C_DATA_CMD_REG_I2C_CMD_Msk;
             --length;
         }
@@ -256,8 +256,6 @@ i2c_da1469x_fill_fifo_for_rx(I2C_Type *i2c_regs, struct i2c_da1469x_dev_data *dd
         return;
     }
 
-    i2c_da1469x_clear_int(i2c_regs);
-
     while ((transfer->wlen > 0) &&
            i2c_regs->I2C_STATUS_REG & I2C_I2C_STATUS_REG_TFNF_Msk) {
         transfer->wlen--;
@@ -266,6 +264,8 @@ i2c_da1469x_fill_fifo_for_rx(I2C_Type *i2c_regs, struct i2c_da1469x_dev_data *dd
         } else {
             i2c_regs->I2C_DATA_CMD_REG = (1U << I2C_I2C_DATA_CMD_REG_I2C_CMD_Pos) |
                                          (1U << I2C_I2C_DATA_CMD_REG_I2C_STOP_Pos);
+            /* All data in tx buffer, no need for TX interrupt any more */
+            i2c_regs->I2C_INTR_MASK_REG &= ~I2C_I2C_INTR_MASK_REG_M_TX_EMPTY_Msk;
         }
     }
 
@@ -275,29 +275,28 @@ i2c_da1469x_fill_fifo_for_rx(I2C_Type *i2c_regs, struct i2c_da1469x_dev_data *dd
             *transfer->data++ = (uint8_t)i2c_regs->I2C_DATA_CMD_REG;
             transfer->rlen--;
             if (transfer->rlen == 0) {
-                i2c_regs->I2C_INTR_MASK_REG = 0;
-                i2c_da1469x_clear_int(i2c_regs);
-                transfer->started = 0;
-                os_sem_release(&dd->sem);
+                i2c_regs->I2C_INTR_MASK_REG &= ~I2C_I2C_INTR_MASK_REG_M_RX_FULL_Msk;
+                if (transfer->nostop) {
+                    transfer->started = 0;
+                    dd->errorsrc = 0;
+                    os_sem_release(&dd->sem);
+                }
             }
         }
     }
 
     if (intr_stat & I2C_I2C_INTR_MASK_REG_M_STOP_DET_Msk) {
+        /* Clear STOP condition interrupt */
+        (void)i2c_regs->I2C_CLR_STOP_DET_REG;
         i2c_regs->I2C_INTR_MASK_REG = 0;
-        assert(transfer->started == 0 && transfer->rlen == 0);
-        if (transfer->started || transfer->rlen) {
+        if (transfer->started) {
             transfer->started = 0;
+            if (transfer->rlen > 0) {
+                dd->errorsrc = I2C_I2C_TX_ABRT_SOURCE_REG_ABRT_USER_ABRT_Msk;
+            }
             transfer->rlen = 0;
-            dd->errorsrc = I2C_I2C_TX_ABRT_SOURCE_REG_ABRT_USER_ABRT_Msk;
             os_sem_release(&dd->sem);
         }
-        return;
-    }
-
-    /* All data in tx buffer, no need for TX interrupt any more */
-    if (transfer->wlen == 0) {
-        i2c_regs->I2C_INTR_MASK_REG &= ~I2C_I2C_INTR_MASK_REG_M_TX_EMPTY_Msk;
     }
 }
 
@@ -332,8 +331,6 @@ i2c_da1469x_fill_fifo_for_tx(I2C_Type *i2c_regs, struct i2c_da1469x_dev_data *dd
         return;
     }
 
-    i2c_da1469x_clear_int(i2c_regs);
-
     while ((transfer->wlen > 0) &&
            i2c_regs->I2C_STATUS_REG & I2C_I2C_STATUS_REG_TFNF_Msk) {
         transfer->wlen--;
@@ -346,7 +343,6 @@ i2c_da1469x_fill_fifo_for_tx(I2C_Type *i2c_regs, struct i2c_da1469x_dev_data *dd
         if (transfer->wlen == 0) {
             if (transfer->nostop) {
                 i2c_regs->I2C_INTR_MASK_REG = 0;
-                i2c_da1469x_clear_int(i2c_regs);
                 transfer->started = 0;
                 os_sem_release(&dd->sem);
             }
@@ -357,6 +353,8 @@ i2c_da1469x_fill_fifo_for_tx(I2C_Type *i2c_regs, struct i2c_da1469x_dev_data *dd
     }
 
     if (intr_stat & I2C_I2C_INTR_MASK_REG_M_STOP_DET_Msk) {
+        /* Clear STOP condition interrupt */
+        (void)i2c_regs->I2C_CLR_STOP_DET_REG;
         i2c_regs->I2C_INTR_MASK_REG = 0;
         if (transfer->started) {
             transfer->started = 0;
@@ -563,7 +561,6 @@ i2c_da1469x_write(struct bus_dev *bdev, struct bus_node *bnode,
     BUS_DEBUG_VERIFY_DEV(dev);
     BUS_DEBUG_VERIFY_NODE(node);
 
-
     i2c_regs = da1469x_i2c[dev->cfg.i2c_num].regs;
     dd = &i2c_dev_data[dev->cfg.i2c_num];
 


[mynewt-core] 02/02: bus/i2c_da1469x: Small insignificant fixes

Posted by je...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 8b7f0d2325455634fe4bdc06683826093e484211
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Fri Jan 8 13:14:24 2021 +0100

    bus/i2c_da1469x: Small insignificant fixes
    
    - unused wariable warning removed
    - inclusion of dma header was unnecessarily conditional
---
 hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c b/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c
index 084b762..5fb4a2c 100644
--- a/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c
+++ b/hw/bus/drivers/i2c_da1469x/src/i2c_da1469x.c
@@ -26,10 +26,7 @@
 #include "bus/bus_driver.h"
 #include "bus/drivers/i2c_common.h"
 #include "mcu/mcu.h"
-
-#if MYNEWT_VAL(I2C_DA1469X_BUS_DRIVER)
 #include "mcu/da1469x_dma.h"
-#endif
 
 #if MYNEWT_VAL(I2C_DA1469X_STAT)
 #include "stats/stats.h"
@@ -388,6 +385,7 @@ i2c_da1469x_init_node(struct bus_dev *bdev, struct bus_node *bnode, void *arg)
 {
     struct bus_i2c_node *node = (struct bus_i2c_node *)bnode;
     struct bus_i2c_node_cfg *cfg = arg;
+    (void)bdev;
 
     BUS_DEBUG_POISON_NODE(node);