Add pull-up detection and timeout mechanisms to prevent I2C hangs#113
Add pull-up detection and timeout mechanisms to prevent I2C hangs#113
Conversation
…C master Co-authored-by: xross <642910+xross@users.noreply.github.com>
…aster Co-authored-by: xross <642910+xross@users.noreply.github.com>
Co-authored-by: xross <642910+xross@users.noreply.github.com>
xross
left a comment
There was a problem hiding this comment.
Rather than checking for pull up present on every usage of p_scl and p_sda simply check at startup and set some error variale
Then check this error viable on write() and read() and dont perform the read/write operations but return the error condition
Co-authored-by: xross <642910+xross@users.noreply.github.com>
Implemented your suggestion in commit f7a37fa. Changed approach to:
This is much simpler and more efficient than the previous approach. Thank you for the guidance! |
xross
left a comment
There was a problem hiding this comment.
check_pullups_two_port should only be implemented once in a shared file
Co-authored-by: xross <642910+xross@users.noreply.github.com>
Implemented in commit 0e14baf. Created |
| * \param p_scl SCL port | ||
| * \param p_sda SDA port | ||
| * | ||
| * \returns I2C_ACK if both pull-ups are present, |
There was a problem hiding this comment.
I2C_ACK used to signify something else - an I2S ACK. Its confusing to reuse it for something else here.
| * I2C_SCL_PULLUP_MISSING if SCL pull-up is missing, | ||
| * I2C_SDA_PULLUP_MISSING if SDA pull-up is missing | ||
| */ | ||
| i2c_res_t check_pullups_single_port( |
There was a problem hiding this comment.
a single function check_pullups() that takes an array of ports would be better than two whole functions for two and single port.
| tmr when timerafter(fall_time + compute_low_period_ticks(kbits_per_second)) :> void; | ||
| p_i2c <: SCL_HIGH | sdaValue | other_bits_mask; | ||
| // TODO: This call may hang if no pull-up present - to be addressed in future update | ||
| wait_for_clock_high(p_i2c, scl_bit_position, fall_time, (bit_time * 3) / 4, kbits_per_second); |
There was a problem hiding this comment.
Dont need this comment since we're checking pull ups are present before we call this function
| p_i2c <: SCL_LOW | SDA_HIGH | other_bits_mask; | ||
| tmr when timerafter(fall_time + compute_low_period_ticks(kbits_per_second)) :> void; | ||
| p_i2c <: SCL_HIGH | SDA_HIGH | other_bits_mask; | ||
| // TODO: This call may hang if no pull-up present - to be addressed in future update |
There was a problem hiding this comment.
Dont need this comment since we're checking pull ups are present before we call this function
| p_i2c <: SCL_HIGH | SDA_HIGH | other_bits_mask; | ||
|
|
||
| // Check for pull-up resistors at startup | ||
| i2c_res_t bus_error = check_pullups_single_port(p_i2c, scl_bit_position, sda_bit_position, other_bits_mask); |
There was a problem hiding this comment.
check both pull ups at start up
Problem
The I2C library could hang forever if pull-up resistors were not present on the SCL and SDA lines. This occurred in functions like
wait_for_clock_high()which contained infinite polling loops:Similarly, the async implementation used
p_scl when pinseq(1) :> void;which would block indefinitely.Solution
Implemented comprehensive pull-up detection and timeout mechanisms across all I2C master implementations:
1. Extended Error Codes
Added new error codes to help developers identify missing pull-ups:
2. Pull-up Detection at Startup
Each implementation now tests for pull-ups before operations begin:
3. Timeout Mechanisms
Single-port: Added timeout to
wait_for_clock_high():Two-port: Added timeout to
release_clock_and_wait():Async: Added clock timeout state machine:
4. Usage Example
Applications can now detect and handle missing pull-ups:
Benefits
This transforms a previously fatal hanging condition into a diagnosable error, significantly improving developer experience and system reliability.
Fixes #97.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.