Skip to content

drivers: i2c: i2c_max32.c: Fix handling of 0-length I2C scan transactions #88729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

Brandon-Hurst
Copy link
Contributor

Fix drivers/i2c/i2c_max32.c to allow for 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. This is due to 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.
if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_ACK) {
        MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0);
        if (written < req->tx_len) {
	        MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0);
        } else if (readb < req->rx_len) {
	        MXC_I2C_EnableInt(
		        i2c, ADI_MAX32_I2C_INT_EN0_RX_THD | ADI_MAX32_I2C_INT_EN0_DONE, 0);
        }
        /* 	0-length transactions are needed for I2C scans.  
	        In these cases, just give up the semaphore. */
        else if ((req->tx_len == req->rx_len) && (req->tx_len == 0)) {
	        k_sem_give(&data->xfer);
        }
}
  1. [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.
if (data->flags & I2C_MSG_STOP) {
        /* 0 length transactions are needed for I2C SCANs */
        if ( (req->tx_len == req->rx_len) && (req->tx_len == 0) ) {
	        MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK,
		        ADI_MAX32_I2C_INT_FL1_MASK);
        }
        /* Wait for busy flag to be cleared for clock stetching
	        use-cases */
        else {
	        while (i2c->status & ADI_MAX32_I2C_STATUS_MASTER_BUSY) {
	        }
	        MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK,
		        ADI_MAX32_I2C_INT_FL1_MASK);
        }
}

…ions

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]>
Copy link

Hello @Brandon-Hurst, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

@kartben kartben merged commit 7ae44ec into zephyrproject-rtos:main Apr 22, 2025
25 checks passed
Copy link

Hi @Brandon-Hurst!
Congratulations on getting your very first Zephyr pull request merged 🎉🥳. This is a fantastic achievement, and we're thrilled to have you as part of our community!

To celebrate this milestone and showcase your contribution, we'd love to award you the Zephyr Technical Contributor badge. If you're interested, please claim your badge by filling out this form: Claim Your Zephyr Badge.

Thank you for your valuable input, and we look forward to seeing more of your contributions in the future! 🪁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: I2C platform: ADI Analog Devices, Inc.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants