Thanks for clarifying, Will.

FYI- I have created a second PR which implements retries at the driver
level rather than the HAL.  For comparison, the two PRs are:

HAL: https://github.com/apache/mynewt-core/pull/1373 
Driver: https://github.com/apache/mynewt-core/pull/1375

I prefer the "driver" version because the required MCU changes are
minimal.

Chris

On Fri, Aug 31, 2018 at 10:21:33AM -0700, will sanfilippo wrote:
> I do not think a driver requires an os device personally. You could write a 
> driver that does not have os dev functionality in it. I do agree that it 
> seems most people implement drivers with os dev functionality but I do not 
> think it is a requirement.
> 
> 
> > On Aug 31, 2018, at 9:51 AM, Christopher Collins <ch...@runtime.io> wrote:
> > 
> > I do think that approach makes more sense than implementing retries in
> > the HAL.  By the way, I did submit a PR for performing I2C retries in
> > the HAL:
> > https://github.com/apache/mynewt-core/pull/1373#issue-212250961
> > 
> > I am happy to redo this at a higher layer, though.  If nothing else, it
> > gives us two implementations to compare.
> > 
> > I am a bit confused by the term "driver," though.  I could be wrong, but
> > my impression is that a Mynewt driver necessarily involves the use of
> > `os_dev` objects.  That is not how I would envision such an I2C layer to
> > look.  Specifically, I am thinking of a thin library that offers two
> > functions (names simplified):
> > 
> >    int i2c_read(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
> >                 uint32_t timeout, uint8_t last_op, int retries);
> > 
> >    int i2c_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
> >                  uint32_t timeout, uint8_t last_op, int retries);
> > 
> > These functions would just repeatedly call the HAL I2C functions until
> > they succeed, or until all retries are exhausted.  Is anything else
> > needed?
> > 
> > Chris
> > 
> > On Fri, Aug 31, 2018 at 05:58:39PM +0200, Sterling Hughes wrote:
> >> I agree with this as well.   For awhile now, I think  there has been a 
> >> need for an I2C driver layer, which also can manage bus arbitration.  
> >> Retries is another good one to add to that.
> >> 
> >> Sterling
> >> 
> >> On 31 Aug 2018, at 17:32, Andrzej Kaczmarek wrote:
> >> 
> >>> Hi all,
> >>> 
> >>> Seems like the majority already voted to go for retries in HAL, but
> >>> I'll add my opinion anyway: I do not think HAL is proper place to
> >>> include such logic.
> >>> I think HAL should only provide interfaces to hide differences between
> >>> underlying MCU hardware while read/write retry logic is something
> >>> driver should do (or any caller in general) since it can decide when
> >>> and if it makes sense to retry. This is what common error codes (so
> >>> #1) would allow to do. This does not however mean we can't have common
> >>> retry code. What we likely need is some bus-level driver/layer that
> >>> drivers will use instead of HAL directly so it can take care of
> >>> handling multiple devices on the same bus seamlessly (in general) and
> >>> also it would be the place where we can put extra common logic if
> >>> needed (like retries).
> >>> 
> >>> Best,
> >>> Andrzej
> >>> 
> >>> 
> >>> 
> >>> On Thu, Aug 30, 2018 at 3:59 AM Christopher Collins <ch...@runtime.io> 
> >>> wrote:
> >>>> 
> >>>> Hello all,
> >>>> 
> >>>> I noticed the HAL master I2C API does not include any retry logic.  
> >>>> As
> >>>> you probably know, in I2C, the default state of the SCL line is NACK.
> >>>> This means an unresponsive peripheral is indistinguishable from one 
> >>>> that
> >>>> is actively nacking the master's writes.  If the master's writes are
> >>>> being NACKed because the slave is simply not ready to receive data, 
> >>>> then
> >>>> retrying seems like the appropriate solution.
> >>>> 
> >>>> I can think of two ways to add I2C retries.  Each of them requires
> >>>> changes:
> >>>> 
> >>>>    (1) Delegate the retry logic to the code calling into the HAL 
> >>>> (e.g.,
> >>>>        drivers).
> >>>>    (2) Implement retry logic directly in the HAL.
> >>>> 
> >>>> The problem with (1) is that HAL implementations currently return
> >>>> MCU-specific error codes.  A generic driver cannot determine if a 
> >>>> retry
> >>>> is in order just from inspecting the error code.  If there were a 
> >>>> common
> >>>> set of error codes that all HAL I2C implementations returned, drivers
> >>>> would have the information they need.  Actually, even ignoring the
> >>>> subject of retries, I think common error codes here makes sense.
> >>>> 
> >>>> Re: (2) - I was thinking this could be implemented by adding two new
> >>>> members to the `hal_i2c_master_data` struct that gets passed to every
> >>>> master I2C function:
> >>>> 
> >>>>    /**
> >>>>     * Total number of times to attempt the I2C operation.  Certain
> >>>>     * failures get retried:
> >>>>     *     o NACK received after sending address.
> >>>>     *     o (if configured) NACK received after sending data byte.
> >>>>     */
> >>>>    uint8_t tries;
> >>>> 
> >>>>    /** Whether to retry when a data byte gets NACKed. */
> >>>>    uint8_t retry_on_dnack:1;
> >>>> 
> >>>> (I hate to complicate things with the `retry_on_dnack` member, but 
> >>>> some
> >>>> peripherals seem to become unresponsive in the middle of a 
> >>>> transaction.)
> >>>> 
> >>>> Since these additions are members of a struct, rather than new 
> >>>> function
> >>>> parameters, this change would be mostly backwards-compatible.  There 
> >>>> is
> >>>> still a problem here, though: code that doesn't zero-out the
> >>>> `hal_i2c_master_data` struct will likely get retries when it isn't
> >>>> expecting them, which could conceivably be a problem.
> >>>> 
> >>>> I am leaning towards (1).  Thoughts?
> >>>> 
> >>>> Thanks,
> >>>> Chris
> 

Reply via email to