Date: Fri, 2 Dec 2016 13:11:34 -0800 From: Oleksandr Tymoshenko <gonzo@bluezbox.com> To: Nick Hibma <Nick@ip-knowhow.com> Cc: freebsd-arm@freebsd.org Subject: Re: Questions about i2c.c (TMP102 temperature sensor) Message-ID: <58B43D61-0B46-4310-868F-D7336585731B@bluezbox.com> In-Reply-To: <9424D7FD-C4B6-43D5-A0C5-76D5BE9ED1DE@ip-knowhow.com> References: <9424D7FD-C4B6-43D5-A0C5-76D5BE9ED1DE@ip-knowhow.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Switching freebsd-embedded@ to freebsd-arm@ since the former does not = get as much attention as the latter. > On Dec 1, 2016, at 2:11 AM, Nick Hibma <Nick@ip-knowhow.com> wrote: >=20 > Gents, >=20 > I am not quite sure who to owner of i2c.c is, so perhaps some I2C = enthousiast could help me with the following problem. >=20 > I was trying to access a TMP102 I2C temperature sensor. It kind of = works with the default i2c utility. But it returns twice the high byte = instead of the high and low byte for the temperature. Probably because = it does 1 byte reads on the I2C bus, sending a stop condition after = every byte. This was verified with a logic analyser. >=20 > The device expects continuous reads and no stop/start in between the 2 = bytes. Trying all options i2c, most notably the -m mode switch, yields = the same results all the time. Looking at the code in i2c.c I get = confused as it seems to somehow fiddle with start/stop to get it right = because of the -m switch, but uses read() in the end to get the data, = not I2CREAD. >=20 > fd =3D open(dev, O_RDWR); > if (i2c_opt.width) { > error =3D ioctl(fd, I2CSTART, &cmd); > error =3D ioctl(fd, I2CWRITE, &cmd); > if (i2c_opt.mode =3D=3D I2C_MODE_STOP_START) { > error =3D ioctl(fd, I2CSTOP, &cmd); > } > } > if (i2c_opt.mode =3D=3D I2C_MODE_STOP_START) { > error =3D ioctl(fd, I2CSTART, &cmd); > } else if (i2c_opt.mode =3D=3D I2C_MODE_REPEATED_START) { > error =3D ioctl(fd, I2CRPTSTART, &cmd); > } > /******** Without i2c_opt.width set there is no START condition either = to set the slave address for the read() ****/ > /******** Why this stop? ***/ > error =3D ioctl(fd, I2CSTOP, &cmd); > for (i =3D 0; i < i2c_opt.count; i++) { > error =3D read(fd, &i2c_buf[i], 1); > } > close(fd); >=20 > I would have expected: >=20 > fd =3D open(dev, O_RDWR); > if (i2c_opt.width) { > error =3D ioctl(fd, I2CSTART, &cmd); > error =3D ioctl(fd, I2CWRITE, &cmd); > if (i2c_opt.mode =3D=3D I2C_MODE_STOP_START) { > error =3D ioctl(fd, I2CSTOP, &cmd); > error =3D ioctl(fd, I2CSTART, &cmd); > } else if (i2c_opt.mode =3D=3D I2C_MODE_REPEATED_START) { > error =3D ioctl(fd, I2CRPTSTART, &cmd); > } > } else { > /***** Use START/STOP to set the slave address for the read() below = ***/ > error =3D ioctl(fd, I2CSTART, &cmd); > error =3D ioctl(fd, I2CSTOP, &cmd); > } > error =3D ioctl(fd, I2CREAD, &cmd); // read all bytes in one go > error =3D ioctl(fd, I2CSTOP, &cmd); > close(fd); >=20 > Any opinions on where I am wrong? There is no need for I2CSTART/I2CSTOP sequence, there is I2CSADDR ioctl for that purpose. I agree that i2c tool looks broken from quick glance, but someone with more knowledge should take a look. > Second question: >=20 > Rolling my own little program with this change fails because I cannot = get I2CREAD to work. It keeps returning EIO. Some other web pages claim = that there is an implementation problem with that. Using read() on the = fd works fine, so do get a valid temperature out of the device now. I picked up TMP102 as a device to test I2C drivers for new boards and wrote C application to talk to it. I used RPi as a reference platform. The problem with I2C driver on RPi is that it does not support sending explicit START/STOP conditions. So all ioctl(I2CSTART) and ioctl(I2CSTOP). And READ/WRITE does not work without explicit START. So I ended up working around it using I2CRDWR. For some other boards it probably can be written with START/WRITE/READ/STOP, or with read/write. I=E2=80=99m going to spend some time and get this = app working on all boards I have to get a general feeling of what bits of I2C are supported on them what are not.=20 Source code: https://people.freebsd.org/~gonzo/tmp102.c=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?58B43D61-0B46-4310-868F-D7336585731B>