Skip to content
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

drivers/periph: reworked I2C driver #4926

Closed
wants to merge 12 commits into from

Conversation

haukepetersen
Copy link
Contributor

Analog to #4780: This PR brings the I2C driver up-to-date with our current discussions. But as in #4780, we need to agree on this concept until it makes sense to touch the existing implementations...

As analyzed in #4758: the i2c peripheral is a shared bus allowing atomic access, implying that it needs to be acquired/released before/after usage and should be powered off when not in use.

Main changes:

  • removed read_byte and read_reg
  • moved bus speed parameter to i2c_acquire
  • made parameters overridable
  • added fixed return codes
  • added default type
  • removed (unused) slave mode (-> should go into its own interface)

TODO:

  • doxygen needs to be updated, e.g. describe that devices are powered on/off when calling acquire/release and more
  • adapt all existing implementations

@haukepetersen haukepetersen added State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Impact: major The PR changes a significant part of the code base. It should be reviewed carefully Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. labels Feb 29, 2016
@haukepetersen haukepetersen added this to the Release 2016.03 milestone Feb 29, 2016
@jnohlgard
Copy link
Member

Related: #3366

*
* @param[in] dev I2C peripheral device
* @param[in] address bus address of the target device
* @param[in] addr 7-bit device address (right-aligned)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 good clarification

@@ -140,147 +145,110 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed);
* @param[in] dev I2C device to access
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing @param[in] speed. What's the purpose of adding the speed to the i2c_acquire?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the bus is shared, we have the situation that multiple devices use the bus with different clock speeds. By moving the clock selection into the acquire function, this is now possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! good catch! 👍

@haukepetersen
Copy link
Contributor Author

So is everyone ok with these interface changes? Then I would to and adapt the existing implementations so we can test them and bring this into the release...

@gebart, @PeterKietzmann, @kYc0o, @jfischer-phytec-iot, @lebrush, @LudwigKnuepfer: ping.

@kYc0o
Copy link
Contributor

kYc0o commented Mar 3, 2016

I'm OK with the changes, it adds flexibility and the code it's really understandable. It will break all the drivers using i2c right?

@jnohlgard
Copy link
Member

I would say that moving the speed to the acquire function is even more signs that it would make sense to introduce a state struct for keeping the hardware settings between calls. Are the periph drivers expected to precompute all possible speed settings inside the init function and then use a lookup to find the right set of register values depending on the speed setting when a driver acquires the bus?

@jnohlgard
Copy link
Member

It may not be the best idea to mix speeds on the i2c bus since it does not provide a discrete Chip Select signal.. The slowest devices may undersample the bus and read the aliased signal as valid data and try to reply.

Can we keep the bus speed selection in the init function?

See: http://electronics.stackexchange.com/questions/62365/is-i2c-mixed-frequency-possible

@PeterKietzmann
Copy link
Member

I agree with @gebart that mixed bus speeds could be dangerous for i2s slaves as there's no dedicated CS lines like in SPI. Though I never tested a setup like this... Other than that, your proposal looks good to me.

@LudwigKnuepfer
Copy link
Member

I don't see the valid (!) I²C answer NACK defined as a return value. Also it's a bit vague what address/data error could mean.
Edit: "answer" as in no answer ;)

@haukepetersen
Copy link
Contributor Author

@gebart: you are completely right, using different bus speeds for different devices is not an option - I don't really know what I was thinking there...

So I have a new, even simpler proposal: why don't we just specify the speed valued in the periph_conf.h? So one as developer must just think about the devices that are used on the bus and has to specify the speed value globally for all of them. This value can easily adjusted if needed. The device drivers only need to specify there allowed speed values in their API. In their initialization we test the correct connection to a device anyway, and if chosen an invalid speed value, the init function of the device will return with an error in any case.

@haukepetersen
Copy link
Contributor Author

@LudwigKnuepfer: not sure I understand your comment, why do you want to have NACK as return value?

We can group errors in two major groups: errors during addressing and errors during the actual data transfer -> hence I2C_ERR_ADDR and I2C_ERR_DATA. For drivers using the i2c interface, these two error conditions should be enough. Also this abstraction of error conditions is needed, as different MCUs have different (internal) error conditions, and it does not makes sense to export them all through this API.

@LudwigKnuepfer
Copy link
Member

@LudwigKnuepfer: not sure I understand your comment, why do you want to have NACK as return value?

In case the slave does not reply with an ACK (replies with a NACK), this is not an error per se.
The driver might need to handle the absence of an ACK differently from "errors". Whatever they may be.

We can group errors in two major groups: errors during addressing and errors during the actual data transfer -> hence I2C_ERR_ADDR and I2C_ERR_DATA. For drivers using the i2c interface, these two error conditions should be enough. Also this abstraction of error conditions is needed, as different MCUs have different (internal) error conditions, and it does not makes sense to export them all through this API.

I still don't know what qualifies as a data/address error.

For example:
If no slave acknowledges the address given during START - is that an address error?
Or is it only an error if a hardware problem is detected?

In my understanding of I2C a NACK is a valid communication pattern, not an error.

@haukepetersen
Copy link
Contributor Author

If no slave acknowledges the address given during START - is that an address error?

this would be an I2C_ERR_ADDR. Naming this an error depends on how we define error in this context, we might also name it exception if that suits you better - I absolutely dont care.

@LudwigKnuepfer
Copy link
Member

IC, thank you for the clarification. As a NACK is a well-defined and named part of regular communication I would not call it error or an exception, but a NACK.

@haukepetersen
Copy link
Contributor Author

The problem I see with NACK is, that it is very specific, but there could be, dependent on the hardware, also other error cases. Having a more generic return value would make the interface easier to implement.

i2c_speed_t speed; /**< I2C bus speed */
uint8_t rcc_bit; /**< bit in the rcc register */
uint8_t irqn; /**< IRQ channel */
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete code ;)

} i2c_conf_t;
/** @} */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know :-) Will fix as soon as we decide for the interface changes

@DipSwitch DipSwitch mentioned this pull request Mar 11, 2016
@LudwigKnuepfer
Copy link
Member

dependent on the hardware, also other error cases

That's what I thought - so define ACK, NACK and a generic other error case.

@haukepetersen
Copy link
Contributor Author

Ok, again: just returning NACK makes no sense, was the NACK on address, on data byte. I say that one exception return value for the address byte and one for data bytes fully sufficient for device drivers that build on top of the interface.

@LudwigKnuepfer
Copy link
Member

I agree that the two types of NACK should be differentiated.

@haukepetersen
Copy link
Contributor Author

@LudwigKnuepfer: how does this look now?

@ant9000
Copy link
Contributor

ant9000 commented Dec 13, 2016

@haukepetersen , thanks for your feedback.

I've published a PR with my code as #6205 - the code should merge cleanly, but needs to be reviewed.

In the future, I would happily participate in remodeling the implementation - even if my contribution is indeed minimal.

@haukepetersen
Copy link
Contributor Author

@ant9000 great! Can't promise anything but I will try to test your PR this week. And just keep a watch on this PR so you can jump in when we move on - your help is much appreciated!

@ant9000
Copy link
Contributor

ant9000 commented Dec 14, 2016

@haukepetersen, glad to be of help - count me in for the future.

Hope that my PR can be useful, waiting for a tip from you when you get the time for it.

Antonio

@smlng
Copy link
Member

smlng commented Jan 12, 2018

postponed, due to high impact changes

@miri64
Copy link
Member

miri64 commented Feb 15, 2018

No significant progress for over a year and it seems @haukepetersen gave up on this task. Closing as memo for now.

@miri64 miri64 closed this Feb 15, 2018
@miri64 miri64 added the State: archived State: The PR has been archived for possible future re-adaptation label Feb 15, 2018
@PeterKietzmann
Copy link
Member

@miri64 I tend to reopen this one. Even though @haukepetersen might have "given up on this task" it is still on our TODO list. This PR acts as place to showcase and discuss the actual API proposal. Objections?

@miri64
Copy link
Member

miri64 commented Feb 15, 2018

@miri64 I tend to reopen this one. Even though @haukepetersen might have "given up on this task" it is still on our TODO list. This PR acts as place to showcase and discuss the actual API proposal. Objections?

Mh.. I'd rather prefer that you open an issue for that. Having an open (and stale) PR that serves as a show-case seems like a bad idea.

@haukepetersen
Copy link
Contributor Author

I know this has been stale for too long, but IMHO the proposed interface changes are still valid and the base for the (at some time) coming remodeling. So in this case I disagree with closing this PR!

@haukepetersen haukepetersen reopened this Feb 26, 2018
@haukepetersen
Copy link
Contributor Author

sorry, I mixed up PR numbers. #6576 is the one that should remain open, so I agree with closing this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Impact: major The PR changes a significant part of the code base. It should be reviewed carefully Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. State: archived State: The PR has been archived for possible future re-adaptation State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.