-
Notifications
You must be signed in to change notification settings - Fork 25
Add pull-up detection and timeout mechanisms to prevent I2C hangs #113
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
base: develop
Are you sure you want to change the base?
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.