Doc for how to use external I2C and SPI devices on Linux with Raspberry Pi - Page 1
Forum section: electronics / projects

author: fanOfeeDIY
author_rank: Unknown
timestamp: March 09, 2018, 08:10:17 am
content: Hi,I wrote some documentation of how to use external I2C and SPI devices on Linux with Raspberry Pi.My initial intention was to describe how to use SPI from Linux with the tools comes with the kernel.The documentations are uploaded at the Design Spark community site. Sorry they are all in Japanese.Debugging Serial Protocol on Raspberry Pi with Oscilloscope, Why scope and Preparationhttps://www.rs-online.com/designspark/1-jp-2Debugging Serial Protocol on Raspberry Pi with Oscilloscope, UARThttps://www.rs-online.com/designspark/1-jp-1Debugging Serial Protocol on Raspberry Pi with Oscilloscope, I2Chttps://www.rs-online.com/designspark/1-jpDebugging Serial Protocol on Raspberry Pi with Oscilloscope, SPI (1)https://www.rs-online.com/designspark/4-jp-1Debugging Serial Protocol on Raspberry Pi with Oscilloscope, SPI (2) and Summaryhttps://www.rs-online.com/designspark/4-jpThere were event for Raspberry Pi last weekend and I prepared them for the talk.https://www.raspi.jp/2018/02/raspberry-jam-big-birthday-weekend-2018-in-tokyo-session/Thank you for RS components Japan and Keysight Japan for coordination and loaning me the DSOX1102G during writing the doc.

author: maginnovision
author_rank: Super Contributor
timestamp: March 09, 2018, 09:42:54 am
content: I don't know japanese but did you did mention the RasPI doesn't support clock-stretching with I2C slaves? Technically you can with a specific minimum but you should consider any clock stretching unsupported because it'll usually result in the RasPI ignoring the stretch and moving on anyway corrupting the bus in most cases.

author: fanOfeeDIY
author_rank: Unknown
timestamp: March 09, 2018, 11:33:34 am
content: Quote from: maginnovision on March 09, 2018, 09:42:54 amHi maginnovision,No, just because I did not know I2C clock-stretching for slave was not working, thanks for the inforI found the errata description about the SoC used on RasPI.https://elinux.org/BCM2835_datasheet_errata#p35_I2C_clock_stretchingI have a feeling that many SoC running Linux or Embedded Windows (e.g. WinCE) are not checking whether clock-stretching is working or not.Most of the software engineer when they encounter read or write error, they slow down the entire clock speed from master side, and if that reduce the error of reading or writing they do not contact hardware engineer.

author: Berni
author_rank: Super Contributor
timestamp: March 09, 2018, 11:56:41 am
content: There are also things to do with I2C bus restart conditions.Most chips work just fine if you send it a stop followed by a start when doing a register read. However some chips require there to be a restart condition rather than a pair of stop start. From the look on your scope you are getting a stop and start.I had some frustration when i had no idea why a chip was refusing to talk to me. I think my solution to it was to use i2c from my C code by doing ioctl calls to the linux i2c device.

author: jeremy
author_rank: Super Contributor
timestamp: March 09, 2018, 12:37:48 pm
content: Quote from: Berni on March 09, 2018, 11:56:41 amFwiw, a restart is very important if you have a multi-master bus, otherwise your device can lose arbitration during the small stopped period.Does using ioctl calls fix the clock stretching problem? I thought it was a problem with the silicon.

author: Berni
author_rank: Super Contributor
timestamp: March 09, 2018, 01:22:25 pm
content: I don't think ioctl has anything for clock stretching.The way that the restart works is that you can feed an array structure of operations to the i2c driver. When you feed it a 0 byte write followed by N byte read command you will get the two commands executed in sequence with a restart between them. It also means you need to make less OS calls so its slightly more CPU efficient.Tho for this to work you need to have combined transactions enabled. To do this temporarly you can do this in the console:Code:sudo su -echo -n 1 > /sys/module/i2c_bcm2708/parameters/combinedexitOr to do it permanently this has to be appened on the end of "/etc/modprobe.d/i2c.conf" (If it does not exist create it)Code:options i2c-bcm2708 combined=1These files might have an option to turn on clock stretching. I never needed that feature so i never looked into it, but the restart one was a big deal.EDIT:Oh and in case anyone needs it here is some code that makes it work:Code:#include <linux/i2c-dev.h>#include <linux/i2c.h>#include <linux/types.h>unsigned char ReadRegI2C(unsigned char Addr, unsigned char Reg){char bfr;int result;struct i2c_msg rdwr_msgs = {{ // Start address.addr = Addr,.flags = 0, // write.len = 1,.buf = &Reg},{ // Read buffer.addr = Addr,.flags = I2C_M_RD, // read.len = 1,.buf = (__u8*)&bfr}};struct i2c_rdwr_ioctl_data rdwr_data = {.msgs = rdwr_msgs,.nmsgs = 2};bfr = Reg;result = ioctl( Handle, I2C_RDWR, &rdwr_data );return bfr;}It also does burst reads if you try to read a length of more than 1. And obviously this code has no error checking, its just a quick and dirty example.