Author Topic: Doc for how to use external I2C and SPI devices on Linux with Raspberry Pi  (Read 1540 times)

0 Members and 1 Guest are viewing this topic.

Offline fanOfeeDIYTopic starter

  • Supporter
  • ****
  • Posts: 412
  • Country: jp
    • YouTube Channel
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 Preparation
  https://www.rs-online.com/designspark/1-jp-2
Debugging Serial Protocol on Raspberry Pi with Oscilloscope, UART
  https://www.rs-online.com/designspark/1-jp-1
Debugging Serial Protocol on Raspberry Pi with Oscilloscope, I2C
  https://www.rs-online.com/designspark/1-jp
Debugging Serial Protocol on Raspberry Pi with Oscilloscope, SPI (1)
  https://www.rs-online.com/designspark/4-jp-1
Debugging Serial Protocol on Raspberry Pi with Oscilloscope, SPI (2) and Summary
  https://www.rs-online.com/designspark/4-jp

There 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.
 

Offline maginnovision

  • Super Contributor
  • ***
  • Posts: 1966
  • Country: us
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.
 

Offline fanOfeeDIYTopic starter

  • Supporter
  • ****
  • Posts: 412
  • Country: jp
    • YouTube Channel
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.

Hi maginnovision,

No, just because I did not know I2C clock-stretching for slave was not working, thanks for the infor :)
I found the errata description about the SoC used on RasPI.
https://elinux.org/BCM2835_datasheet_errata#p35_I2C_clock_stretching

I 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. :(
 

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5028
  • Country: si
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.
 

Offline jeremy

  • Super Contributor
  • ***
  • Posts: 1079
  • Country: au
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.

Fwiw, 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.
 

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5028
  • Country: si
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: [Select]
sudo su -
echo -n 1 > /sys/module/i2c_bcm2708/parameters/combined
exit
Or 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: [Select]
options i2c-bcm2708 combined=1

These 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: [Select]
#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[2] = {
{  // 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.
« Last Edit: March 09, 2018, 01:28:52 pm by Berni »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf