-
Notifications
You must be signed in to change notification settings - Fork 7.9k
drivers: i2c: i2c_stm32_v2: stability improvements #89501
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: main
Are you sure you want to change the base?
drivers: i2c: i2c_stm32_v2: stability improvements #89501
Conversation
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.
First of all, thanks @erian747 for the work on this driver and the time you're taking to share your improvements.
Before starting the review, a quick note from my part:
while I do believe this definitely brings important improvements to the current driver, we should also make sure this doesn't bring regression to others (not a surprise to you I guess).
Then, despite the issues you faced, this driver is used w/o trouble in number of applications, which tells that driver behavior depends on the use cases and also that it's difficult to reproduce all conditions in test environment.
So, on the hypothesis that everything can't be verified by testing, we should take special care in the review.
In order to make this PR progress at a reasonable speed, here are few things that will help us I the review
Is there a possibility to split this PR into smaller chunks that would be easier to swallow in reviews ?
If not, further splitting the PR in more single purpose commits would greatly help in the review process. You made efforts on that already but I had a quick look and it's still not easy to track changes. I know by experience that this is a tedious task, but this is really efficient (this usually also helps to find bugs).
Finally, would you be able to provide more indications on the tests that were made on this change, like the targets used, kind of tests (Zephyr tests/drivers ones for instance), ... ?
Last preliminary note on the change:
Drop of LL usage, even though they are justified, imply potential issue in further maintenance, as we lose the thin hw portability it brings.
This concern depends on IPs, some are more or less stable across series. Fortunately, I2C seems relatively stable in that regard, but yet...
So when possible, let's try to minimize removal of LL.
Thanks for the comment What i have tested is master mode with irq on real hardware: STM32F071 and STM32H747 platforms with various types of sensors ranging from small messages with single byte data to messages with up to 1536 bytes and it seems solid Regarding splitting commits in to smaller chunks, i understand what you mean but the complicated commit "Rework interrupt handler" which required deep insight into how the I2C IP works im not sure it helps splitting it, because the changes are tightly coupled together. What i know would really be helpful during a review is a specification in form of a state diagram, activity diagram etc describing how things suppose to work, i will look into that... For LL usage, i saw there is a function LL_I2C_HandleTransfer() that can help removing a few direct register writes without having any impact on code, and also some writes to CR1 can be replaced by LL functions I will update the PR as soon as i have time |
Heads up: You'll probably be (badly) hit by #87731... |
Thanks for mentioning it, seems like its mostly renaming done in i2c_ll_stm32_v2.c so shouldn't be hard to manage |
3bf5c8a
to
8699f7e
Compare
4f76a7d
to
8699f7e
Compare
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.
The changes look sane to me.
Some minor comments.
Since there are now quite common few common functions between the irq and non-irq implementation, I wonder if it would help to have 3 source files. Well, maybe in a later change.
@erwango, with this change, there are a few raw manipulations of the I2C registers content (interrupt bits, CR1/CR2 fields loading, ...). I'm pretty fine with that but maybe you prefer we stick at most to the LL API? Since we're in a STM32 I2C v2 controller driver, all related SoCs have common fields/macros naming in the LL. It seems reliable to me (from a maintenance perspective).
8699f7e
to
e1ee156
Compare
I also think it would be a good idea to split up the file, right now it is a bit to big to be readable |
I think most of the comments have been addressed in most recent push |
90b62af
to
50d7ede
Compare
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.
More Most of the review comments below are related to coding style issues like
s/if (foo & mask)
/if ((foo & mask) != 0U)
/.
Commit "drivers: i2c_stm32_v2: Remove obsolete functions" claims to only remove obsolete functions but it does more. I think it could only do that, the other change could be move in other related commits, already present in this commit series.
That said, those changes look good to me and address some corner cases as they claim to.
50d7ede
to
70aaf4a
Compare
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.
Commit "drivers: i2c_stm32_v2: DMA fixup" fixes an regression introduced by a former commit in the series. It could be better all commits are consistent and add no regression (build and run) when possible. That helps a lot when digging for a regression using git bisect
or like.
I would suggest to add insert a preparatory commit at the beginning of your patch series to introduce dma_xfert_start()
and dma_finish()
local helper functions and have msg_init()
calling them.
70aaf4a
to
a072e61
Compare
Was a bit hard to move DMA changes to an initial commit, lots of conflicts with commits following |
a072e61
to
4640a24
Compare
New push again |
ab8c21d
to
23b048b
Compare
|
Is there any problem with this not being updated? |
I am waiting for approval from reviewers, noting more planned for me to change |
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
struct i2c_stm32_data *data = dev->data; | ||
const struct i2c_stm32_config *cfg = dev->config; | ||
I2C_TypeDef *i2c = cfg->i2c; |
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.
Nitpick: those declarations should go at the beginning of the new block
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.
Fixed
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.
Some minor comments. I'm still looking at the overall changes.
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
} | ||
} | ||
|
||
static inline void dma_finish(const struct device *dev, struct i2c_msg *msg) |
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.
I don't think inline
helps a lot here. I would remove it and rely on compiler and project directives to get the expected optimized embedded code.
That's said, it not a blocking issue.
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
if (data->current.len != 0U) { | ||
/* Configure TX DMA */ | ||
data->dma_blk_cfg.source_address = | ||
(uint32_t)data->current.buf; |
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.
(uint32_t)data->current.buf; | |
data->dma_blk_cfg.source_address = (uint32_t)data->current.buf; |
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
if ((msg->flags & I2C_MSG_READ) != 0U) { | ||
dma_stop(cfg->rx_dma.dev_dma, cfg->rx_dma.dma_channel); | ||
LL_I2C_DisableDMAReq_RX(cfg->i2c); | ||
#if defined(CONFIG_DCACHE) |
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.
You can remove this guard. It's already handled in stm32_cache.h.
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
LL_I2C_DisableDMAReq_RX(cfg->i2c); | ||
#if defined(CONFIG_DCACHE) | ||
if (!stm32_buf_in_nocache((uintptr_t)msg->buf, msg->len)) { | ||
sys_cache_data_invd_range((void *)msg->buf, msg->len); |
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.
Despite many calls to sys_cache_data_invd_range()
do cast the 1st pointer arg to (void *)
, it is not needed.
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.
Fixed
} | ||
data->current.len -= xfer_len; | ||
data->current.buf += xfer_len; | ||
#endif |
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.
Please add an empty line below.
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
goto end; | ||
} | ||
|
||
/* |
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.
Could you preserve the empty line above.
By the way, to conform with Zephyr multi-line inline comment coding style, prefer below (and elsewhere):
- /*
- * Blablabla...
+ /* Blablabla...
* blablabla
*/
This is not a block 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.
Empty line fixed and multi-line comment at this location
#ifdef CONFIG_I2C_STM32_V2_DMA | ||
/* Stop DMA and invalidate cache if needed */ | ||
dma_finish(dev, msg); | ||
#endif |
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.
An empty line below is welcome.
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
data->master_active = false; | ||
} | ||
/* Don't disable I2C if a slave is attached */ | ||
keep_enabled |= data->slave_attached; |
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.
Prefer avoid numerical OR operations on boolean variables.
if (data->slave_attached) { keep_enabled = true; }
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
return stm32_i2c_irq_msg_finish(dev, msg); | ||
|
||
#ifdef CONFIG_I2C_STM32_V2_DMA | ||
dma_error: |
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.
Since this is called from only 1 place, would you be ok to move that code to line 807?
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.
Fixed
drivers/i2c/i2c_ll_stm32_v2.c
Outdated
if (!stm32_buf_in_nocache((uintptr_t)msg->buf, msg->len) && | ||
((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE)) { |
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.
if (!stm32_buf_in_nocache((uintptr_t)msg->buf, msg->len) && | |
((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE)) { | |
if (!stm32_buf_in_nocache((uintptr_t)msg->buf, msg->len) && | |
((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE)) { |
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.
Fixed
To prepare for further patches and separation of interrupt/DMA modes from polled, this commit introduces two helpers for starting and stopping DMA transfers Signed-off-by: Erik Andersson <erian747@gmail.com>
23b048b
to
c60e056
Compare
- Rework transaction flow to better match reference manual and errata sheet for STM32 I2Cv2 peripheral - Handle message transactions larger than 255 bytes in isr - Combine stm32_i2c_msg_write and stm32_i2c_msg_read into one common function stm32_i2c_irq_xfer when using interrupts Signed-off-by: Erik Andersson <erian747@gmail.com>
stm32_i2c_msg_read and stm32_i2c_msg_write for interrupt mode is replaced by a common function: stm32_i2c_irq_xfer Signed-off-by: Erik Andersson <erian747@gmail.com>
Adapt DMA implementation to match changes introduced by new interrupt handler Signed-off-by: Erik Andersson <erian747@gmail.com>
Don't abort transaction on bus error in master mode according to errata sheet Signed-off-by: Erik Andersson <erian747@gmail.com>
The stm32_i2c_master_mode_end function can be replaced with a simple irq disable and giving to the device sync semaphore Signed-off-by: Erik Andersson <erian747@gmail.com>
If configuration of DMA is unsuccessful then abort transaction and return with an error code Signed-off-by: Erik Andersson <erian747@gmail.com>
c60e056
to
3d24ec2
Compare
|
Due to various reported stability issues with the STM32 I2C V2 driver in interrupt mode, the controller part is rewritten in an attempt to closely follow documentation found in reference manual and errata sheets.
See #70077
A side effect should also be increased performance
This PR replaces the old draft at #82940