This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit f26227f431ba7d0451274b0fdc473236de4cc70d Author: Max Kriegleder <[email protected]> AuthorDate: Mon Oct 26 20:58:50 2026 +0100 arch/arm/nrf53: Use a repeated START for an I2C register read. nrf53_i2c.c is the nRF52 TWIM driver with more instances and ignores I2C_M_NOSTOP the same way. Apply the nRF52 change: a write with I2C_M_NOSTOP followed by a read from the same address runs as one TWIM transfer with a repeated START. Also indent the frequency switch's case labels as on the nRF52 (whitespace only). Build-tested only (nrf5340-dk with NRF53_I2C0_MASTER); the code is the one tested on the nRF52840 and the nRF9160. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Max Kriegleder <[email protected]> --- arch/arm/src/nrf53/nrf53_i2c.c | 56 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/arch/arm/src/nrf53/nrf53_i2c.c b/arch/arm/src/nrf53/nrf53_i2c.c index c1f9d3dd020..429e9b5ae8e 100644 --- a/arch/arm/src/nrf53/nrf53_i2c.c +++ b/arch/arm/src/nrf53/nrf53_i2c.c @@ -28,6 +28,7 @@ #include <assert.h> #include <errno.h> +#include <stdbool.h> #include <nuttx/debug.h> #include <nuttx/irq.h> @@ -262,6 +263,7 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev, struct nrf53_i2c_priv_s *priv = (struct nrf53_i2c_priv_s *)dev; uint32_t regval = 0; int ret = OK; + bool rx_after = false; #ifndef CONFIG_NRF53_I2C_MASTER_DISABLE_NOSTART uint8_t *pack_buf = NULL; #endif @@ -294,25 +296,25 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev, switch (priv->msgv->frequency) { - case 100000: + case 100000: { regval = TWIM_FREQUENCY_100KBPS; break; } - case 250000: + case 250000: { regval = TWIM_FREQUENCY_250KBPS; break; } - case 400000: + case 400000: { regval = TWIM_FREQUENCY_400KBPS; break; } - default: + default: { ret = -EINVAL; goto errout; @@ -342,6 +344,8 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev, i2cinfo("ptr=%p dcnt=%d flags=%d addr=%d\n", priv->ptr, priv->dcnt, priv->flags, priv->addr); + rx_after = false; + /* Write TWI address */ regval = priv->addr; @@ -421,10 +425,42 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev, regval = priv->dcnt; nrf53_i2c_putreg(priv, NRF53_TWIM_TXDMAXCNT_OFFSET, regval); - /* Shortcut from LASTTX to STOP */ + /* A write without STOP followed by a read from the same address + * (a register read): repeated START into the read, then STOP. + * Both run as one transfer ending in one STOPPED event. Only + * for data in both directions, as the shortcuts need the LASTTX + * and LASTRX events. + */ - nrf53_i2c_putreg(priv, NRF53_TWIM_SHORTS_OFFSET, - TWIM_SHORTS_LASTTX_STOP); + rx_after = (priv->flags & I2C_M_NOSTOP) != 0 && + priv->dcnt > 0 && + priv->msgc > 1 && + priv->msgv[1].length > 0 && + (priv->msgv[1].flags & I2C_M_READ) != 0 && + (priv->msgv[1].flags & I2C_M_NOSTART) == 0 && + priv->msgv[1].addr == priv->addr; + + if (rx_after) + { + regval = (uint32_t)priv->msgv[1].buffer; + DEBUGASSERT(nrf53_easydma_valid(regval)); + nrf53_i2c_putreg(priv, NRF53_TWIM_RXDPTR_OFFSET, regval); + nrf53_i2c_putreg(priv, NRF53_TWIM_RXDMAXCNT_OFFSET, + priv->msgv[1].length); + + /* Shortcuts from LASTTX to STARTRX, LASTRX to STOP */ + + nrf53_i2c_putreg(priv, NRF53_TWIM_SHORTS_OFFSET, + TWIM_SHORTS_LASTTX_STARTRX | + TWIM_SHORTS_LASTRX_STOP); + } + else + { + /* Shortcut from LASTTX to STOP */ + + nrf53_i2c_putreg(priv, NRF53_TWIM_SHORTS_OFFSET, + TWIM_SHORTS_LASTTX_STOP); + } /* Start TX sequence */ @@ -491,10 +527,10 @@ static int nrf53_i2c_transfer(struct i2c_master_s *dev, } #endif - /* Next message */ + /* Next message (two after a write with its read) */ - priv->msgc -= 1; - priv->msgv += 1; + priv->msgc -= rx_after ? 2 : 1; + priv->msgv += rx_after ? 2 : 1; } while (priv->msgc > 0);
