From owner-freebsd-arm@freebsd.org Fri Dec 2 21:12:12 2016 Return-Path: Delivered-To: freebsd-arm@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B9E76C63084 for ; Fri, 2 Dec 2016 21:12:12 +0000 (UTC) (envelope-from gonzo@id.bluezbox.com) Received: from id.bluezbox.com (id.bluezbox.com [45.55.20.155]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8D3F710D2 for ; Fri, 2 Dec 2016 21:12:12 +0000 (UTC) (envelope-from gonzo@id.bluezbox.com) Received: from [208.184.220.60] (helo=[10.112.202.219]) by id.bluezbox.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.87 (FreeBSD)) (envelope-from ) id 1cCv7l-00033L-8Z; Fri, 02 Dec 2016 13:12:06 -0800 Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 10.1 \(3251\)) Subject: Re: Questions about i2c.c (TMP102 temperature sensor) From: Oleksandr Tymoshenko In-Reply-To: <9424D7FD-C4B6-43D5-A0C5-76D5BE9ED1DE@ip-knowhow.com> Date: Fri, 2 Dec 2016 13:11:34 -0800 Cc: freebsd-arm@freebsd.org Content-Transfer-Encoding: quoted-printable Message-Id: <58B43D61-0B46-4310-868F-D7336585731B@bluezbox.com> References: <9424D7FD-C4B6-43D5-A0C5-76D5BE9ED1DE@ip-knowhow.com> To: Nick Hibma X-Mailer: Apple Mail (2.3251) Sender: gonzo@id.bluezbox.com X-Spam-Level: -- X-Spam-Report: Spam detection software, running on the system "id.bluezbox.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see The administrator of that system for details. Content preview: 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 wrote: > > Gents, > > I am not quite sure who to owner of i2c.c is, so perhaps some I2C enthousiast could help me with the following problem. > > 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. > > 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. > > fd = open(dev, O_RDWR); > if (i2c_opt.width) { > error = ioctl(fd, I2CSTART, &cmd); > error = ioctl(fd, I2CWRITE, &cmd); > if (i2c_opt.mode == I2C_MODE_STOP_START) { > error = ioctl(fd, I2CSTOP, &cmd); > } > } > if (i2c_opt.mode == I2C_MODE_STOP_START) { > error = ioctl(fd, I2CSTART, &cmd); > } else if (i2c_opt.mode == I2C_MODE_REPEATED_START) { > error = 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 = ioctl(fd, I2CSTOP, &cmd); > for (i = 0; i < i2c_opt.count; i++) { > error = read(fd, &i2c_buf[i], 1); > } > close(fd); > > I would have expected: > > fd = open(dev, O_RDWR); > if (i2c_opt.width) { > error = ioctl(fd, I2CSTART, &cmd); > error = ioctl(fd, I2CWRITE, &cmd); > if (i2c_opt.mode == I2C_MODE_STOP_START) { > error = ioctl(fd, I2CSTOP, &cmd); > error = ioctl(fd, I2CSTART, &cmd); > } else if (i2c_opt.mode == I2C_MODE_REPEATED_START) { > error = ioctl(fd, I2CRPTSTART, &cmd); > } > } else { > /***** Use START/STOP to set the slave address for the read() below ***/ > error = [...] Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: ip-knowhow.com] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Porting FreeBSD to ARM processors." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Dec 2016 21:12:12 -0000 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 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=