Set I2C speed on nano with C++

Hi,
Is there a way to change the ic2-1 speed bus on nano which is set by default to 100KHz ? I would like to change this speed in C++.
I dont find many topics on this subject in the forum except by changing the Device Tree.

Hi bf1,
There is a sysfs node mentioned below where you can write required speed directly from target.
Ex to write 400khz in I2C-1
$ echo 400000 > /sys/bus/i2c/devices/i2c-1/bus_clk_rate
This will change I2C bus speed.
You can use C++ commands to open above file path and read/write the contents.

Thanks,
Shubhi

Hi Shubhi,
OK to change the speed opening “bus_clk_rate” file.
2 questions :

  • This modification has to be done at each boot? (I think so)
  • Are there restrictions to open/close this kind of files in ubuntu (I’m new in the linux/nano world) ?

You would need to do this each boot, but it shouldn’t be difficult to make this as a default in C++. Possibly you could use the device tree for a new default, but then you wouldn’t know for sure the change is in place without checking…in which case you might as well just set the speed in C++ anyway.

Files in “/sys” are not real files, and are really in RAM, provided by a driver. If the driver is not yet loaded, then you cannot access this.

Files in “/sys” require user “root” to access them. Your program would probably have to run as root (or sudo).

The method with sysfs is fine - you can put it in your code using system(" ") or in a startup script.

Or when you open the i2c device, you can use the handle and an IOCTL call to change the clock speed. Doc on the linux driver for i2c is here - https://www.kernel.org/doc/Documentation/i2c/dev-interface

You should also hunt around for a C++ linux i2c wrapper - there are several around. Avoid the fancy ones that use streams and or overloading operators - those are getting a bit to removed from reality for me.

I cannot run in root mode my program (because of remote dev. , I cannot do that). When I try to acces the file with system((char *)“echo 400000 > /sys/bus/i2c/devices/i2c-1/bus_clk_rate”); an error is returned. I guess I cannot access to this file because of privileges.
I read the Doc on the linux driver for i2c but it never speaks about i2c bus speed. Do you get an idea how to change i2c speed with the an ioctl () call ?

To make changes to those settings you must use root. However, did you know that your program can have permissions changed to “SUID root”? If you limit access to a certain person or a certain group, then that person or group would be required to run the program. When the program does run, then it would run as if root were running it. Of course you have to use sudo to make those permission changes, but once that is done, then you no longer need to enter credentials.

A longer explanation, but detailed:
https://en.wikipedia.org/wiki/Setuid

A longer explanation of chmod (used for setting permissions):
https://en.wikipedia.org/wiki/Chmod

Most likely you would want the file to be owned and writeable only by root. Updates would need sudo. You’d set the group to be either a specific user’s group, or to some new group which you’d add your user(s) to. If not done correctly this can be a security issue. Note that “sudo” itself is an SUID root file. See:

ls -l `which sudo`

You’ll see something like this:
-rwsr-xr-x 1 root root 136616 Jan 31 2020 /usr/bin/sudo*

See that “s” in the permissions for the owner? That is “suid root” since the file is owned by root. See the “r-x” of the group? If the “s” was there instead, then this would be “sgid root”. Note that a regular user can read or execute this, but cannot write to the file. The “sudo” command itself is what asks for a password, but if you did not program your file to ask for a password, then it should “just work as root” for those who have permission to execute. You could remove all read/write/execute of “other” (the last of the permissions), but change group to your group or user (instead of having group root). That group would not have write authority, but it would have read and execute for your user.

Here’s a nice article on the topic:
https://linuxconfig.org/how-to-use-special-permissions-the-setuid-setgid-and-sticky-bits

You can ignore anything on the topic of “sticky bits”. You’d be interested in either suid or sgid. There are different ways to do this, so it is hard to answer specifically. However, it does give you a way to use this directly with remote ssh access without extra steps.