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: sensors: stmemsc: Don't use i2c_burst_write on Nordic #34066

Conversation

richardbarlow
Copy link
Contributor

The TWIM peripheral in Nordic SoCs (nRF5{1,2,3}) cannot correctly
support the i2c_burst_write API. Using it results in a repeated start,
rather than a single I2C write transaction.

This implements the workaround noted in #20154.

Fixes #33440

Signed-off-by: Rich Barlow rich@bennellick.com

@jfischer-no
Copy link
Collaborator

Why can not you use "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" ?

@pabigot
Copy link
Collaborator

pabigot commented Apr 7, 2021

Why can not you use "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" ?

I would guess because that's a controller configuration, and it's needed only if there happens to be an ST device on the bus.

Copy link
Collaborator

@avisconti avisconti left a comment

Choose a reason for hiding this comment

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

LGTM
P.S.
I was reading the rational behind using IS_ENABLED(CONFIG_FOO) instead of #if defined(CONFIG_FOO). Moving the filter from the preprocessor to the C compiler looks cleaner as it allows generating compiler's errors/warning even if FOO is not defined.

@jfischer-no
Copy link
Collaborator

Why can not you use "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" ?

I would guess because that's a controller configuration, and it's needed only if there happens to be an ST device on the bus.

We do not do it per device and we should not. This solution here does not even distinguish which controller is used.

Copy link
Collaborator

@jfischer-no jfischer-no left a comment

Choose a reason for hiding this comment

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

"zephyr,concat-buf-size" property should be used

@jfischer-no jfischer-no requested a review from anangl April 7, 2021 09:32
@avisconti
Copy link
Collaborator

"zephyr,concat-buf-size" property should be used

I didn't know this property was even existing (I don't use nordic platforms). Now I feel that using this property is much cleaner, as it moves the proper solution inside where the issue lies. But I let you guys discuss more about it.

@anangl
Copy link
Member

anangl commented Apr 7, 2021

"zephyr,concat-buf-size" property should be used

I agree with @jfischer-no. Using this property is a better solution for the issue.

@avisconti
Copy link
Collaborator

avisconti commented Apr 7, 2021

I agree with @jfischer-no. Using this property is a better solution for the issue.

@richardbarlow
Can you possibly give this option a try instead? Just to test if it works fine at your end!

@avisconti
Copy link
Collaborator

avisconti commented Apr 7, 2021

Why can not you use "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" ?

I would guess because that's a controller configuration, and it's needed only if there happens to be an ST device on the bus.

@pabigot
Not sure I get why this issue is only when there is a ST sensor on the I2c bus. Isn't it related to Nordic I2c controller and i2c_burst_write()?

@pabigot
Copy link
Collaborator

pabigot commented Apr 7, 2021

I would guess because that's a controller configuration, and it's needed only if there happens to be an ST device on the bus.

@pabigot
Not sure I get why this issue is only when there is a ST sensor on the I2c bus. Isn't it related to Nordic I2c controller and i2c_burst_write()?

My thought was: The buffer configuration is within the TWIM devicetree node. A workaround for burst write is only necessary for a bus controlled by a Nordic TWIM peripheral. Since stmemsc uses the burst write API all sensors it supports are susceptible to failure on Nordic TWIM buses.

So if you take a Nordic-based board, attach an ST sensor to an I2C bus, and try to use it, it will fail to work correctly unless you modify the board devicetree (directly, or via an overlay for the application) to change the controller's concatenation buffer size.

Unless you do that proactively for all Nordic boards that use TWIM, any ST sensor on any of those boards may fail. Which is a painful user experience, resulting in reports that the sensor doesn't work on Nordic hardware.

While yes, every application where that occurs could be fixed by modifying the devicetree files once the problem is (re)discovered for each user, the fix here solves it globally for the Nordic/ST combination without requiring any special handling for particular board/sensor combinations.

But I may be misunderstanding what's going on, and I'm not maintaining I2C or Zephyr anymore, so feel free to do whatever y'all think is best.

@avisconti
Copy link
Collaborator

avisconti commented Apr 7, 2021

I would guess because that's a controller configuration, and it's needed only if there happens to be an ST device on the bus.

@pabigot
Not sure I get why this issue is only when there is a ST sensor on the I2c bus. Isn't it related to Nordic I2c controller and i2c_burst_write()?

My thought was: The buffer configuration is within the TWIM devicetree node. A workaround for burst write is only necessary for a bus controlled by a Nordic TWIM peripheral. Since stmemsc uses the burst write API all sensors it supports are susceptible to failure on Nordic TWIM buses.

So, let's say that every device on the Nordic I2C bus with a driver using the burst write is susceptible of failure. Correct?
I was wondering whether ST sensors drivers have some special about it. THey are not the only one using burst write.

So if you take a Nordic-based board, attach an ST sensor to an I2C bus, and try to use it, it will fail to work correctly unless you modify the board devicetree (directly, or via an overlay for the application) to change the controller's concatenation buffer size.

That's clear.

Unless you do that proactively for all Nordic boards that use TWIM, any ST sensor on any of those boards may fail. Which is a painful user experience, resulting in reports that the sensor doesn't work on Nordic hardware.

While yes, every application where that occurs could be fixed by modifying the devicetree files once the problem is (re)discovered for each user, the fix here solves it globally for the Nordic/ST combination without requiring any special handling for particular board/sensor combinations.

Yes, I understand your rational of concentrating in only one place the change. And to be honest I'm not 100% against it. But let's face the fact that there is already a clean solution to the TWIM burst write issue (if I understand well), which is using that property which is there exactly to solve this issue. Isn't it?

So, if everyone agrees on my statements above my feeling is that we need to change all the Nordic affected boards including that property in the DT. That can be done in a single PR.

But I may be misunderstanding what's going on, and I'm not maintaining I2C or Zephyr anymore, so feel free to do whatever y'all think is best.

I have nothing against this patch, but again my feeling is that there is a cleaner solution.
@MaureenHelm any comment on that?

EDIT:
Does the use of the "zephyr,concat-buf-size" property limiting the I2C performance in any matter? Why are the ST sensor drivers the only one taken into account?

@avisconti avisconti added area: I2C bug The issue is a bug, or the PR is fixing a bug labels Apr 7, 2021
@richardbarlow
Copy link
Contributor Author

Just to chip in with my 2 cents (after uncovering a potentially contentious topic). Please note that I would class myself as a 'user' of Zephyr, rather than a Zepher developer.

A brief history

I ended up here after attempting to use one of the ST sensor drivers with an nRF53 SoC. As I'm sure will be obvious, it did not work. It took a little time to track down, but after staring at the logic analyser output for a while it occurred to me that the behaviour I was observing (repeated start) may be the cause of the issue. This led me to look for anything (Issues/Pull Requests) that may be related to what I was seeing. The outcome of this can be seen in #33440. As noted in that issue, I discovered that it was already a known problem and others had previously been bitten by it. Specifically the problem being that the TWIM peripheral makes it impossible to implement the i2c_burst_write() API correctly. Note that correctly would mean it being able to handle a potentially arbitrarily sized buffer and not issuing a repeated start.

Based on my findings, I suggested that it may be sensible to factor out the stmemsc interface routines so that all ST sensors using the stmemsc library may benefit from the fix that I am now proposing. @avisconti very kindly implemented the refactoring.

My observations

  1. I ended up proposing this 'fix' based on all of the information available to me on the understanding that it would be the most 'correct' thing to do
  2. Choosing to close this pull-request and the associated issue with no change to Zephyr means that others will fall into the exact same trap that I did
  3. I agree that fixing the TWIM i2c_burst_write() implementation would be the best course of action. However, I do not believe that a Zephyr user should need to know the murky details that result in them needing to set a special device tree property that is effectively working around a buggy API implementation (through no fault of Zephyr's)
  4. Any use of i2c_burst_write anywhere in Zephyr or user's code could fall foul of this issue (when using a Nordic SoC) and I understand that my proposed change here only fixes the ST sensor drivers. In reality, all calls to i2c_burst_write() must actually have a similar workaround applied. That was certainly the impression I got from marker issue for i2c burst API concerns #20154
  5. The particular failure mode that we are discussing here is very non-obvious to the user and does not naturally lead one to the existing mechanism that would workaround it (the zephyr,concat-buf-size property). Since it turns out this mechanism already existed, I got bitten by the TWIM/i2c_burst_write() issue, and I never discovered that this was an appropriate workaround indicates that it is perhaps insufficient or at least needs to be documented somewhere?
  6. Setting the zephyr,concat-buf-size property for all Nordic boards defined within Zephyr will go some way to help, however that still doesn't necessarily help with what I would of thought is going to be (if not already) the common case of people running Zephyr on their own proprietary boards in products?

Note that #12588 added documentation to warn that i2c_burst_write() may not actually work, however that isn't helpful for someone who isn't directly using that API, such as someone using the sensor API (I didn't know, and shouldn't have needed to know, that this API function was being used). It would appear to me that Zephyr shouldn't use an API function that is known to be potentially deficient in internal driver implementations, unless there is a mechanism to automatically workaround the deficiency or at least warn the user that they are about to be bitten.

@avisconti avisconti added the platform: nRF Nordic nRFx label Apr 7, 2021
@mbolivar-nordic
Copy link
Contributor

Note that #12588 added documentation to warn that i2c_burst_write() may not actually work, however that isn't helpful for someone who isn't directly using that API, such as someone using the sensor API (I didn't know, and shouldn't have needed to know, that this API function was being used). It would appear to me that Zephyr shouldn't use an API function that is known to be potentially deficient in internal driver implementations, unless there is a mechanism to automatically workaround the deficiency or at least warn the user that they are about to be bitten.

+1

Perhaps we need an i2c_supports_burst_write() API function or something like that to allow users like the stmemsc driver to fall back on something else if i2c_burst_write() is not available on a particular device?

@jfischer-no
Copy link
Collaborator

"property that is effectively working around a buggy API implementation (through no fault of Zephyr's)"

Why is it buggy, who decided it?
API does not know the capabilities of the controller and there is currently no way to obtain it.

@jfischer-no
Copy link
Collaborator

Perhaps we need an i2c_supports_burst_write() API function or something like that to allow users like the stmemsc driver to fall back on something else if i2c_burst_write() is not available on a particular device?

Not a specific driver should fall back but probably I2C API / I2C transfer manager.

* I2C master uses TWI or TWIM, so use a substitute implementation
* unconditionally on Nordic.
*/
if (IS_ENABLED(CONFIG_I2C_NRFX)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since it seems that using i2c_burst_write() is deprecated (#12588) why not calling always the i2c_write() and get rid of the i2c_burst_write()? I mean, using this piece of code not only for Nordic platform but always, following the i2c API comment from @pabigot:

  • @warning The combined write synthesized by this API may not be
  • supported on all I2C devices. Uses of this API may be made more
  • portable by replacing them with calls to i2c_write() passing a
  • buffer containing the combined address and data.

Copy link
Collaborator

@avisconti avisconti Apr 8, 2021

Choose a reason for hiding this comment

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

To be honest, as ST sensors maintainer I would like to see them working properly with all platforms. And it is not very clean to have a check of the platfrom here in this code. Better get rid of it. @richardbarlow would you kindly re-implement this PR so that I could also verify it on my platforms?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since it seems that using i2c_burst_write() is deprecated (#12588)

I think that is a rumor.

why not calling always the i2c_write() and get rid of the i2c_burst_write()

Because it is generally very useful function and many operating systems offer it?

@avisconti
Copy link
Collaborator

avisconti commented Apr 8, 2021

Perhaps we need an i2c_supports_burst_write() API function or something like that to allow users like the stmemsc driver to fall back on something else if i2c_burst_write() is not available on a particular device?

Not a specific driver should fall back but probably I2C API / I2C transfer manager.

@jfischer-no
THis is a nice proposal for a more general topic that may be probably addressed in another PR. I think that here we can simply always avoid calling the i2c_burst_write() as it has been deprecated. Would you agree in doing that?

@jfischer-no
Copy link
Collaborator

THis is a nice proposal for a more general topic that may be probably addressed in another PR.

No one was asked to do it here.

I think that here we can simply always avoid calling the i2c_burst_write() as it has been deprecated. Would you agree in doing that?

No, it is not deprecated.

@avisconti
Copy link
Collaborator

THis is a nice proposal for a more general topic that may be probably addressed in another PR.

No one was asked to do it here.

This was already clear. I was just summarizing...

I think that here we can simply always avoid calling the i2c_burst_write() as it has been deprecated. Would you agree in doing that?

No, it is not deprecated.

Still, as i2c API user, I'm evaluating to replace inside stmemsc the i2c_burst_write() API with i2c_write(), copying in a single buffer register and data, What would the advantage be of using one approach vs the other?

I guess that avoiding the copy is of course one of them, but this happens only when programming the sensors. Other advantages?

The TWIM peripheral in Nordic SoCs (nRF5{1,2,3}) cannot correctly
support the i2c_burst_write API. Using it results in a repeated start,
rather than a single I2C write transaction.

Use i2c_write instead, which will always work correctly.

Fixes zephyrproject-rtos#33440

Signed-off-by: Rich Barlow <rich@bennellick.com>
@richardbarlow
Copy link
Contributor Author

@avisconti

To be honest, as ST sensors maintainer I would like to see them working properly with all platforms. And it is not very clean to have a check of the platfrom here in this code. Better get rid of it. @richardbarlow would you kindly re-implement this PR so that I could also verify it on my platforms?

I've just updated the PR to always use i2c_write(). I've also changed to using memcpy() instead of memmove() as we know that the buffers do not overlap and memcpy() may be more efficient due to this.

@jfischer-no
Copy link
Collaborator

Still, as i2c API user, I'm evaluating to replace inside stmemsc the i2c_burst_write() API with i2c_write(), copying in a single buffer register and data, What would the advantage be of using one approach vs the other?

I guess that avoiding the copy is of course one of them, but this happens only when programming the sensors. Other advantages?

Is it not a sufficient argument? There is also counterpart i2c_burst_read() to read sensor (array) values.

@avisconti
Copy link
Collaborator

avisconti commented Apr 8, 2021

Still, as i2c API user, I'm evaluating to replace inside stmemsc the i2c_burst_write() API with i2c_write(), copying in a single buffer register and data, What would the advantage be of using one approach vs the other?
I guess that avoiding the copy is of course one of them, but this happens only when programming the sensors. Other advantages?

Is it not a sufficient argument? There is also counterpart i2c_burst_read() to read sensor (array) values.

@jfischer-no
Actually is not the memcpy overhead that is scaring me, as a sensor is strongly asymmetric regarding read and write ops balance (with read ops being more frequent). But I really don't like the fact that we have to impose a maximum size inside the stmemsc_i2c_write() API. Assuming it is 9, as this PR does, may be not always a good thing, at least considering that in the future there will be new sensors supported.

The observation above is also stated in #20154:

  • The non-burst code is generic, though it's slightly fragile in that it assumes a maximum transfer size. Changes to the driver could require changes to the generic write function.

But what I seem to understand is that also using the "zephyr,concat-buf-size" property is not satisfactory, as it is imposing the i2c_nrfx_twim driver to have a behaviour that is efficient only for a subset of I2C devices attached to the bus.

So, I'm a bit confused about how to proceed.

@avisconti
Copy link
Collaborator

avisconti commented Apr 8, 2021

@avisconti

To be honest, as ST sensors maintainer I would like to see them working properly with all platforms. And it is not very clean to have a check of the platfrom here in this code. Better get rid of it. @richardbarlow would you kindly re-implement this PR so that I could also verify it on my platforms?

I've just updated the PR to always use i2c_write(). I've also changed to using memcpy() instead of memmove() as we know that the buffers do not overlap and memcpy() may be more efficient due to this.

Thanks @richardbarlow . I still have some doubts regarding the fixed buffer size to 10 bytes. In the future there might be other ST sensors with different size requirements. So, confused a bit now...


__ASSERT((1U + len) <= sizeof(buffer), "stmemsc i2c buffer too small");
buffer[0] = reg_addr;
memcpy(buffer + 1, value, len);
Copy link
Collaborator

Choose a reason for hiding this comment

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

__ASSERTs are useless. memcpy(&buffer[1], value, MIN(len, sizeof(buffer) - 1)); ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

But here you should at least report that you are writing less than requested. Something wrong will happen somewhere in any case. Moreover, as I said earlier, I feel that imposing a maximum size (reg + 9 byte of data here) may lead to issues in the next future.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't use a literal 9 or 10; define a constant in a header that specifies the maximum data length for one of the relevant operations (e.g. maximum size of config structures, if those are the ones that are a problem), and document it needs to be updated when things change.

If you put that define in the upstream stmemsc package then everything should be good because the stmemsc maintainers should know when new sensors that have larger transfers are added.

Copy link
Collaborator

@avisconti avisconti Apr 8, 2021

Choose a reason for hiding this comment

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

@pabigot
I am the stmemsc maintainer (sigh!).
The issue here is that things may get more complex in the future, with sensor that has the capability to drive external sensors (the shub feature is already there in some of the current sensor drivers) and maybe other things. Calculating the maximum size and adapting the macro evrytime a new sensor (or a new feature in a sensor) is added can lead to trivial errors.
Frankly speaking I would rather keep the i2c_burst_write() for the SoC that have I2C scatter-gather capability and the i2c_write implementation for the others. If we want to avoid the NFRX platform test, maybe we can add in stmemsc a new property that provides the burst-skipping info (and maybe another with the max buffer size).
In this way, we confine the work to stmemsc w/o affecting the I2C TWIM driver behaviour. Of course the default of that property will be "use-burst". The NFRx platforms will have to indicate the alternative usage.
What do you all think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Something like "stmemsc,buf-size". When is 0 (the default) means go with i2c_burst_write. The property must be included in stmemsc based sensors when they are on a NFRx platform.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Responding only because I was directly asked for this: I don't have a horse in this race because I've given up on Zephyr being useful to me personally, so my patience with wicked issues like this is exhausted.

There are so many ways this could be resolved; each has different trade-offs of (a) amount of cooperation required from reviewers and other maintainers to get the solution merged, and (b) impact on Zephyr maintainability and usability.

I don't see where stmemsc,buf-size could be provided or how its value could be determined by most users, so I would do this:

#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_twim)
  /* The underlying I2C driver might be nordic,nrf-twim, and if so it might
   * not have a zephyr,concat-buf-size large enough to correctly implement
   * i2c_burst_write of len bytes.  Since we can't verify that easily at
   * either build or run time, pack the write payload locally.
   */
  uint8_t buf[1 + len];
  
  buf[0] = reg_addr;
  memcpy(buf+1, value, len);
  return i2c_write(...);
#else
  return i2c_burst_write(...);
#endif

This is conservative in that on Nordic platforms it sometimes uses non-burst write in cases where burst-write would have worked, but checking for that at build time (or even at runtime) is IMO not feasible or doesn't solve the problem of clearly indicating to the user that there's a knob that could be set to make the code work.

But depending on Zephyr coding guidelines the use of a VLA might be rejected, in which case the alternative is a constant that comes from a header file or Kconfig and a runtime check against length. But that still wouldn't solve the problem of a novice user wondering why their sensor doesn't work.

Copy link
Collaborator

@avisconti avisconti Apr 13, 2021

Choose a reason for hiding this comment

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

Responding only because I was directly asked for this: I don't have a horse in this race because I've given up on Zephyr being useful to me personally, so my patience with wicked issues like this is exhausted.

Sorry for that.

There are so many ways this could be resolved; each has different trade-offs of (a) amount of cooperation required from reviewers and other maintainers to get the solution merged, and (b) impact on Zephyr maintainability and usability.

I don't see where stmemsc,buf-size could be provided or how its value could be determined by most users, so I would do this:

#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_twim)

I think you need a DT_DRV_COMPAT to do that, but we do not have in stmemsc as this is more like a library used by many drivers. I would prefer the original check as before (i.e. IS_ENABLED(CONFIG_I2C_NRFX)

/* The underlying I2C driver might be nordic,nrf-twim, and if so it might

  • not have a zephyr,concat-buf-size large enough to correctly implement
  • i2c_burst_write of len bytes. Since we can't verify that easily at
  • either build or run time, pack the write payload locally.
    */
    uint8_t buf[1 + len];

I think we should avoid arrays with variable length, and accept the fact that, in case of nfrx TWIM platforms, we will handle the normal 9axis case (9 + 1 byte) as it was before.

More complex sensor features will not be handled here.

buf[0] = reg_addr;
memcpy(buf+1, value, len);
return i2c_write(...);
#else
return i2c_burst_write(...);
#endif


This is conservative in that on Nordic platforms it sometimes uses non-burst write in cases where burst-write would have worked, but checking for that at build time (or even at runtime) is IMO not feasible or doesn't solve the problem of clearly indicating to the user that there's a knob that could be set to make the code work.

But depending on Zephyr coding guidelines the use of a VLA might be rejected, in which case the alternative is a constant that comes from a header file or Kconfig and a runtime check against length. But that still wouldn't solve the problem of a novice user wondering why their sensor doesn't work.

In my opinion it would be better to avoid VLAs.

@avisconti
Copy link
Collaborator

avisconti commented Apr 15, 2021

@richardbarlow
Thanks for your patience. I was waiting for other comments, but seems that nobody has the time nor the motivation to see this PR coming to a conclusion. Currently it is not possible to have lsm6dso sensor (and similarly other sensors with driver using i2c_write_burst) working on some NRFx platform. In my opinion the best way to address this, even if there are limitations in doing that, is to come back to original idea, i.e. something like that:

if (IS_ENABLED(CONFIG_I2C_NRFX)) {
    u8_t buffer[8];
 
    /* Largest num_bytes used is 6 */ 
       __ASSERT((1U + num_bytes) <= sizeof(buffer), "burst buffer too small");
        buffer[0] = start_addr | LIS2DH_AUTOINCREMENT_ADDR;
        memmove(bufferffer + 1, buf, num_bytes);
        return i2c_write(lis2dh->bus, buffer, 1 + num_bytes, LIS2DH_BUS_ADDRESS);
  } 

In this we should be able to make th standard 9 axis (or less) in the usual "flavor" working fine.
@MaureenHelm any comment here?

@jfischer-no
Copy link
Collaborator

Currently it is not possible to have lsm6dso sensor (and similarly other sensors with driver using i2c_write_burst) working on some NRFx platform.

That is not correct, again, there is "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" to resolve this.
IMO, this PR should be closed. If the solution for TWIM controller is non-obvious (it is not), an issue should be opened regarding this.

@avisconti
Copy link
Collaborator

Currently it is not possible to have lsm6dso sensor (and similarly other sensors with driver using i2c_write_burst) working on some NRFx platform.

That is not correct, again, there is "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" to resolve this.
IMO, this PR should be closed. If the solution for TWIM controller is non-obvious (it is not), an issue should be opened regarding this.

@jfischer-no
I tend to moderately agree with you. I have some points not clear though:

  • I do not have a NRFx platform to test it. I kindly asked @richardbarlow to test it in this PR itself. I'm not sure he confirmed it is passing, even though I agree there are no reasons it shouldn't. So, pls, Richard, can you confirm it?
  • Is the zephyr,concat-buf-size affecting all the slaves on the I2C bus? I'm wondering if setting it to make lsm6dso working would break other I2C slaves...
  • If other slaves are not affected, why not setting it by default in the yaml binding to some value?

@pabigot
Copy link
Collaborator

pabigot commented Apr 15, 2021

That is not correct, again, there is "zephyr,concat-buf-size" property for compatible = "nordic,nrf-twim" to resolve this.

  • Is the zephyr,concat-buf-size affecting all the slaves on the I2C bus? I'm wondering if setting it to make lsm6dso working would break other I2C slaves...

It's a property in the controller devicetree node (parent of the "slave"s); the driver instance reserves memory to use as a buffer.

The weakness of that approach is that anybody using a Nordic-based board with ST sensors on it must somehow be aware that for the sensor to work they have to override their devicetree bindings: they must set that property in the parent controller(s) to an undocumented value (being the maximum of the undocumented maximum buffer length required over all attached sensors).

Or:

  • If other slaves are not affected, why not setting it by default in the yaml binding to some value?

What value would that be? Should all instances of Nordic TWIM pay the cost of supporting ST sensors that are only rarely present?

@richardbarlow
Copy link
Contributor Author

Sorry for the silence at my end. I've had to move on to other parts of the firmware that I am currently writing.

@avisconti I have switched to using the zephyr,concat-buf-size property and it appears to work beautifully. So far I only have one other I2C device and that still works correctly too. Eventually this product will have 5 I2C devices, but I am yet to get around to implementing the others yet. I suspect that worst-case I will have to set zephyr,concat-buf-size to be large enough for the largest write used across all I2C devices.

@jfischer-no I also mildly agree that the fix that I am proposing here isn't the best solution to the problem. Now that I know of the existence of the zephyr,concat-buf-size property, I can see how that is a better workaround. My main concern is that Zephyr's 'out of the box' experience right now isn't fantastic and that the workaround for this issue is not obvious to the end user. Ideally this could be somehow 'fixed' once and for all (although I suspect that is impossible), but as a minimum I think it would help if the end user could be warned if they have a possibly susceptible situation. However, this PR isn't the right place to discuss how this might be achieved.

  • If other slaves are not affected, why not setting it by default in the yaml binding to some value?

What value would that be? Should all instances of Nordic TWIM pay the cost of supporting ST sensors that are only rarely present?

@pabigot While the focus of this PR has been ST sensors, surely any I2C device that expects a single write transaction is susceptible? (without extensive research, we don't know if/how many devices that may be). Anywhere where a device driver author has used i2c_burst_write on the understanding that it results in a single transaction is at risk. Since the i2c_burst_write documentation doesn't explicitly state how it behaves (at least historically, before the warning was added), it is impossible to know what each device driver author's intent was when they wrote the driver.

@avisconti
Copy link
Collaborator

@avisconti I have switched to using the zephyr,concat-buf-size property and it appears to work beautifully. So far I only have one other I2C device and that still works correctly too. Eventually this product will have 5 I2C devices, but I am yet to get around to implementing the others yet. I suspect that worst-case I will have to set zephyr,concat-buf-size to be large enough for the largest write used across all I2C devices.

OK, thanks for confirming it.

  • If other slaves are not affected, why not setting it by default in the yaml binding to some value?

What value would that be? Should all instances of Nordic TWIM pay the cost of supporting ST sensors that are only rarely present?

@pabigot While the focus of this PR has been ST sensors, surely any I2C device that expects a single write transaction is susceptible? (without extensive research, we don't know if/how many devices that may be). Anywhere where a device driver author has used i2c_burst_write on the understanding that it results in a single transaction is at risk. Since the i2c_burst_write documentation doesn't explicitly state how it behaves (at least historically, before the warning was added), it is impossible to know what each device driver author's intent was when they wrote the driver.

That was exactly my point: every driver using i2c_burst_write will fall into the same scenario.

@richardbarlow
Copy link
Contributor Author

That was exactly my point: every driver using i2c_burst_write will fall into the same scenario.

@avisconti to be even more technically correct, every driver using i2c_burst_write might fall into the same scenario, and we have no way of knowing without lots of tedious datasheet reading. The harsh reality is that different people may have made different assumptions when using i2c_burst_write and those assumptions are not documented ☹️

@carlescufi
Copy link
Member

@anangl could you please comment on this one?

@MaureenHelm
Copy link
Member

This issue is not unique to scenarios that combine an nRF I2C controller with an STM sensor; NXP I2C drivers also generate a repeated start and NXP sensors cannot tolerate it. I handled this in the NXP sensor drivers (e.g., fxos8700) by using a series of i2c_reg_write_byte transactions rather than one i2c_burst_write. The Zephyr I2C API doesn't explicitly state whether a repeated start can or cannot happen in a burst write, so unless we clear that up then I think users of the I2C API, in this case sensor drivers, need to avoid using the burst write if the slave device cannot tolerate repeated starts.

@carlescufi
Copy link
Member

API meeting 2021.06.01:

Steps proposed:

  1. Document what the transaction(s) on the bus is expected to be like for each API call (read/write/transfer)
    1.a Implement tests for the behavior defined above
  2. Analyze whether the current implementations adhere to the description in 1.
  3. Decide on the fate of the *burst* functions based on the outcome

@Tubbles
Copy link

Tubbles commented Jul 20, 2021

  1. Decide on the fate of the *burst* functions based on the outcome

Any news on this?

@cfriedt
Copy link
Member

cfriedt commented Aug 6, 2021

@carlescufi - just checking in - is this one still moving forward?

@carlescufi
Copy link
Member

@carlescufi - just checking in - is this one still moving forward?

No, agreement is to take a different approach. We will follow-up in the coming days.

@github-actions
Copy link

github-actions bot commented Nov 8, 2021

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Nov 8, 2021
@github-actions github-actions bot closed this Nov 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: I2C area: Sensors Sensors bug The issue is a bug, or the PR is fixing a bug platform: nRF Nordic nRFx Stale
Projects
None yet
Development

Successfully merging this pull request may close these issues.

lsm6dso sensor driver not working on nRF5340