Can't write to IIC by I2CRDWR with two records 'struct iic_msg'

Warner Losh imp at bsdimp.com
Sun Nov 10 17:22:33 UTC 2019


On Sun, Nov 10, 2019 at 8:22 AM Emmanuel Vadot <manu at bidouilliste.com>
wrote:

> On Sun, 10 Nov 2019 08:16:03 -0700
> Ian Lepore <ian at freebsd.org> wrote:
>
> > On Sun, 2019-11-10 at 16:55 +0400, mishin at mh.san.ru wrote:
> > > About a system:
> > > 1. FreeBSD betta 12.1-STABLE FreeBSD 12.1-STABLE r354236
> > > OPI_ZERO  arm
> > > 2. Allwinner H2+
> > > 3.
> > > iichb0: <Allwinner Integrated I2C Bus Controller> mem
> > > 0x1c2ac00-0x1c2afff irq 35 on simplebus0
> > > iicbus0: <OFW I2C bus> on iichb0
> > > iic0: <I2C generic I/O> on iicbus0
> > >
> > >
> > > I trying to send a data array following a register value to a
> > > SSD1306
> > > display
> > > from 'Allwinner H2+' by a following method (according to `i2c.c`):
> > >
> > > char SSD1306::iic_write(uint8_t offset, uint8_t data[], uint16_t
> > > size)
> > > const {
> > >    struct iic_msg msgs[2] =
> > >    {
> > >      {slave_addr, IIC_M_WR | IIC_M_NOSTOP, sizeof(offset), &offset},
> > >      {slave_addr, IIC_M_WR | IIC_M_NOSTART, size, data}
> > >    };
> >
> > Some i2c hardware controller drivers don't properly support the NOSTOP
> > and NOSTART flags.  Sometimes it's a bug, and sometimes it's because
> > hardware limitations prevent it.  In the allwinner case, I think it's a
> > bug, but manu would know for sure.
> >
> > -- Ian
>
>  TWSI supports NOSTOP but I could never find the right incantation to
> support NOSTART.
>

In the past I've had good luck "simulating" it with a single transfer that
did the entire thing for picky hardware that doesn't like to 'interrupt'
transactions. It's less convenient, to be sure, but works well when you
have no other choice... It's clearly used here as a means to scatter/gather
the data...

Warner

>
> > >    struct iic_rdwr_data xfer = {msgs, 2};
> > >
> > >    if ( ioctl(iic_handle, I2CRDWR, &xfer) == -1 )  {
> > >      perror("ioctl(I2CRDWR)");
> > >      return(-1);
> > >    };
> > >    return(0);
> > > };
> > >
> > > iic_write(0x40, buffer, buffer_size);
> > >
> > > But something goes wrong and the display stills blank (no errors,
> > > though). But when I use an 'one record' struct
> > > with combined 'register+data' array (see below) or read by that 'two
> > > records' scheme (see below), all is ok.
> > >
> > > Have I made a mistake is flags or it is a feature or a bug?
> > >
> > > Thanks
> > >
> > >
> > >
> > >
> > > ---
> > > Next two methods works ok
> > >
> > > Read following write:
> > > char TEA5767::iic_read(uint8_t offset, uint8_t *data, uint16_t size)
> > > const {
> > >    struct iic_msg msgs[2] =
> > >    {
> > >      {slave_addr, IIC_M_WR | IIC_M_NOSTOP, sizeof(offset), &offset},
> > >      {slave_addr, IIC_M_RD, size, data}
> > >    };
> > >    struct iic_rdwr_data xfer = {msgs, 2};
> > >
> > >    if ( ioctl(iic_handle, I2CRDWR, &xfer) == -1)  {
> > >      perror("ioctl(I2CRDWR)");
> > >      return(-1);
> > >    };
> > >    return(0);
> > > };
> > >
> > > and write a combined 'register+data' array works too:
> > >
> > > char SSD1306::iic_write(uint8_t data[], uint16_t size) const
> > > {
> > >    struct iic_msg msgs[1] =
> > >    {
> > >      {slave_addr, IIC_M_WR, size, data}
> > >    };
> > >    struct iic_rdwr_data xfer = {msgs, 1};
> > >
> > >    if ( ioctl(iic_handle, I2CRDWR, &xfer) == -1)  {
> > >      perror("ioctl(I2CRDWR)");
> > >      return(-1);
> > >    };
> > >    return(0);
> > > }
> > > _______________________________________________
> > > freebsd-arm at freebsd.org mailing list
> > > https://lists.freebsd.org/mailman/listinfo/freebsd-arm
> > > To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org
> > > "
> >
> > _______________________________________________
> > freebsd-arm at freebsd.org mailing list
> > https://lists.freebsd.org/mailman/listinfo/freebsd-arm
> > To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org"
>
>
> --
> Emmanuel Vadot <manu at bidouilliste.com>
> _______________________________________________
> freebsd-arm at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-arm
> To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org"
>


More information about the freebsd-arm mailing list