Skip to content

Commit 7ae44ec

Browse files
Brandon-Hurstkartben
authored andcommitted
drivers: i2c: i2c_max32.c: Fix handling of 0-length I2C scan transactions
The I2C shell allows a user to input "i2c scan i2c0" for instance, to scan addresses on the i2c0 bus enabled in DT. This currently causes an infinite loop when CONFIG_I2C_MAX32_INTERRUPT is enabled. The infinite loops happens because 0-length transactions (tx_len == rx_len == 0) not being handled both by the Async i2c_max32_transfer and by the controller ISR. This commit makes two changes: 1) [ISR] When an address ACK is received, if there is simply no data to send or receive, then just give up the semaphore, preventing the i2c_max32_transfer function from waiting infinitely. 2) [i2c_max32_transfer] After getting the semaphore back, if there is no data to send or receive, then avoid waiting for the BUSY flag to clear since clock stretching should not occur by definition for transactions which merely contain an address ACK. Signed-off-by: Brandon Hurst <[email protected]>
1 parent a6c76c4 commit 7ae44ec

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

drivers/i2c/i2c_max32.c

+18-4
Original file line numberDiff line numberDiff line change
@@ -532,11 +532,19 @@ static int i2c_max32_transfer(const struct device *dev, struct i2c_msg *msgs, ui
532532
ret = data->err;
533533
} else {
534534
if (data->flags & I2C_MSG_STOP) {
535-
/* Wait for busy flag to be cleared */
536-
while (i2c->status & ADI_MAX32_I2C_STATUS_MASTER_BUSY) {
535+
/* 0 length transactions are needed for I2C SCANs */
536+
if ((req->tx_len == req->rx_len) && (req->tx_len == 0)) {
537+
MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK,
538+
ADI_MAX32_I2C_INT_FL1_MASK);
539+
} else {
540+
/* Wait for busy flag to be cleared for clock stetching
541+
* use-cases
542+
*/
543+
while (i2c->status & ADI_MAX32_I2C_STATUS_MASTER_BUSY) {
544+
}
545+
MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK,
546+
ADI_MAX32_I2C_INT_FL1_MASK);
537547
}
538-
MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK,
539-
ADI_MAX32_I2C_INT_FL1_MASK);
540548
}
541549
}
542550
if (ret) {
@@ -755,6 +763,12 @@ static void i2c_max32_isr_controller(const struct device *dev, mxc_i2c_regs_t *i
755763
MXC_I2C_EnableInt(
756764
i2c, ADI_MAX32_I2C_INT_EN0_RX_THD | ADI_MAX32_I2C_INT_EN0_DONE, 0);
757765
}
766+
/* 0-length transactions are needed for I2C scans.
767+
* In these cases, just give up the semaphore.
768+
*/
769+
else if ((req->tx_len == req->rx_len) && (req->tx_len == 0)) {
770+
k_sem_give(&data->xfer);
771+
}
758772
}
759773

760774
if (req->tx_len &&

0 commit comments

Comments
 (0)