-
Notifications
You must be signed in to change notification settings - Fork 249
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
Infinite loop in i2c example #690
Comments
It could be that your hardware setup forces the scl pin low which would prevent the controller from sending the address byte, causing this issue. |
Thanks. |
In the i2c example, gpio19 is configured as the SCL pin. What's connected to that pin in your hardware? |
Ah...I got it. I'm sorry, I didn't know I2C example need destination hardware.
|
Hi, indeed you cannot loop-back I2C as you did. It is a bit more complex than UART and requires some extra things. First of all, to avoid any confusion here's the vocabulary I'll use:
In a nutshell: To accommodate for all this but lines are expected to be pulled up, preferably externally from the rp2040. When a controller wants to read or write data it needs to generate a certain start sequence (bringing scl and sda low in a known sequence).
The peripheral is allowed to hold the clock low when data or ack is expected from it in order to get more time to process the request. When the controller is done talking to the peripheral, it either generates a The controller should listen to the bus to make sure there's no contention/conflict. On the rp2040 the block can behave as a controller or a peripheral (but not both at the same time). I cannot remember if we have an example for the peripheral mode (I'm on my phone right now), will edit this msg if I find one. |
@ithinuel Thank you for the detailed explanation. I was confused about the difference in meaning between controller/peripheral/block, so this is a great help! So, Pico has two I2C executor - "I2C0" and "I2C1". |
I2C0 and I2C1 are two independent instances of the same block. You can have one be a controller while the other is acting as a peripheral. Eg if your Pico's I2C0 is configured as a controller on the bus, another chip (like another pico) on the same bus cannot send it send it commands. To achieve this, you'd need to have your Pico's i2C0 run as a peripheral to listen and respond on the bus and if/when your Pico needs to talk to another chip's peripheral, then your firmware will need to reconfigure i2C0 from peripheral mode to controller, and revert back to peripheral once it's done. TBH it's a fairly rare usecase, it might be easier for you to have i2c0 as controller and i2c1 as peripheral (or the other way around). |
Thanks! I think I got it:) To confirm I'm in right path, let me ask one more.
the |
That is correct. Peripheral mode starts with: https://docs.rs/rp2040-hal/latest/rp2040_hal/i2c/struct.I2C.html#method.new_peripheral_event_iterator |
Thanks.
But it still stuck at the same point( |
Could you perhaps try if this change to the example helps?
It looks like since commit b087c0c ("Rework GPIO API and fix a few inconsistencies (#585)"), the internal pull-ups are no longer automatically activated when I2C is selected. At least, we should fix the example. |
Thanks @jannic ! It works!!! Though my problem has soleved, it seems like tasks remain to fix the example. |
Yes, definitely keep the ticket open. I'm not sure how the solution will look like, but at least we need to document the changed behavior and update the example. In most (if not all) cases, internal pull-ups should be enabled on i2c pins. Even though stronger external pull-ups are recommended, and with them, the internal ones are no longer needed, they wouldn't hurt either. However I'd like to have some way to enable the i2c interface without the internal pull-ups. Not because I have a particular use case, but just because I think in the embedded space in general, there are many unusual approaches where it makes sense to do something differently than usual. |
It is possible to skip this check by using `hal::I2C::i2c0_unchecked(...)` or `hal::I2C::i2c1_unchecked(...)`, but the default constructor functions now only accept pins with activated PullUp. Fixes rp-rs#690.
It is possible to skip this check by using `hal::I2C::i2c0_unchecked(...)` or `hal::I2C::i2c1_unchecked(...)`, but the default constructor functions now only accept pins with activated PullUp. Fixes rp-rs#690.
In my environment, I2C example does not reach to loop .
It stucks at
rp-hal/rp2040-hal/src/i2c/controller.rs
Line 219 in 0f5bc07
that causes infinite loop.
I simply did
git clone
andcargo run --example i2c --features="critical-section-impl"
Am I missing some hidden settings?
I'm working on Windows10, and using Raspberry Pi Pico.
The text was updated successfully, but these errors were encountered: