Add variable I2C clock speed support #150
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The HAL only supports Wire.setClock(#) where # must be 100000, 400000, or 1000000. Otherwise, it exists with error and sketches fail to run. This PR:
Why?
There may be instance where the user wants to operate outside of the 100/400/1000kHz slots. Mainly, running the bus more slowly minimizes bit errors when the bus capacitance gets large (ie, the user has some really long wires). Or maybe there's an exotic I2C device that only runs at 10kHz.
Min bus speed is now 1500Hz, max speed is 2MHz. Math can be verified here. Testing was done with a RedBoard Artemis and a MS8607 breakout that surprisingly (shockingly) worked at 2MHz and 1500Hz.
This PR was tested with Burst Mode and is unaffected at 96MHz. IOMs seem to run on a separate clock from internal processing.
I am a little concerned that Ambiq makes some very magical recommendations for the TOTPER and FSEL settings for the 3 main I2C speeds. Perhaps they know something about the hardware they are not sharing. So this PR maintains their recommendations, but if the user selects a non-standard I2C bus speed, the hardware will seek it. This PR does not attempt to calculate SDA/SCL end delays.
I'm not sure how many modifications we've done to the HAL in the past. What is the best way to document HAL changes so that we can implement our small changes into future SDK version changes? For this reason I've created HAL-Variances.md in the am_sdk_ap3 directory (best place?).
My only real concern with this PR is the hard coding of 48000000 in the loop. I tried to find a good define in the HAL but couldn't come up with one. And we don't want to do a am_hal_clkgen_status_get() because it would change depending on if the user was in burst mode or not.
Here's 1.5kHz:
Here's 2MHz: