i2c
Inter-Cntergrated Circuit protocol, used to communicate with a wide verity of IC devices on a single physical bus.
9front / plan9 provide I2C support in a form of kernel device abstraction, but not necessarily enabled for your specific device.
9front does not support I2C on Raspberry Pi out of the box.
installation
As of 9front release HUMANBIOLOGICS on 2023.11.22, the I2C code is part of the base system, with tweaks to deferentiate betweeen miltiple I2C busses (if they exist).
If hardware support is in for your device, just use it.
usage
When supported / enabled, I2C devices should be accessible through #J kernel device.
Example - bme680 (address 0x77) raw I2C access:
-
check if device exists in terminal
cd '#J77'
There should be a directory with I2C bus names for the device (eg. i2c1).
-
bind device to dev
bind -b '#J77' /dev
This should bind data (/dev/i2c1/i2c.77.data) and control (/dev/i2c1/i2c.77.ctl) files to /dev/BusName directory. Use those files to communicate with the device.
-
use I2C device in code
#include <u.h> #include <libc.h> int opendev(void) { /* default location for bme680 is 0x77 */ int fd = -1; if(access("/dev/i2c1/i2c.77.data", 0) != 0){ if(bind("#J77", "/dev", MBEFORE) < 0){ sysfatal("no J77 device"); } } fd = open("/dev/i2c1/i2c.77.data", ORDWR); if(fd < 0){ sysfatal("cannot open i2c.77.data file"); } return(fd); } void closedev(int fd) { close(fd); unmount("#J77", "/dev"); } int initdev(int fd) { uchar cmd[1]; uchar res[1]; cmd[0] = 0xD0; /* location of id register */ pwrite(fd, cmd, 1, 0); pread(fd, res, 1, 0); fprint(1, "device id val: %x\n", res[0]); /* value 0x61 is the id of bme680 device */ if(res[0] == 0x61){ return 1; } return 0; } void main(int, char*) { int fd; fd = opendev(); sleep(1000); initdev(fd); sleep(1000); closedev(fd); exits(nil); }
DEPRECATED Raspberry Pi 1 - (RPI 1) DEPRECATED
Enabling I2C support on Raspberry Pi 1 with 9front, by including code from plan9. Luckily, many resources can be found on this topic. Here is a cleanup and condensed summary.
references
- Richard Miller I2C code from plan9: https://9p.io/sources/contrib/miller/9/bcm/
adventuresin9 video on the subject: youtube
preparation
-
kernel code is located in /sys/src/9
-
kernel code for RPI 1 is located in /sys/src/9/bcm
-
files needed from Richard Miller I2C code:
-
i2c.c - I2C implementation for the Broadcom chip used by RPI 1
- to be copied in bcm directory
-
devi2c.c - I2C device abstraction for plan9 kernel
- to be copied in bcm directory
-
dat.h - i2C data structure to be referenced
- use as a reference to edit the file already in bcm directory
-
fns.h - I2C callback functions to be referenced
- use as a reference to edit the file already in bcm directory
-
i2c.c - I2C implementation for the Broadcom chip used by RPI 1
code installation
-
copy i2c.c to /sys/src/9/bcm
-
copy devi2c.c to /sys/src/9/bcm
-
edit dat.h in /sys/src/9/bcm
-
add the data structure:
/* * I2C */ typedef struct I2Cdev I2Cdev; struct I2Cdev { int salen; int addr; int tenbit; };
-
-
edit fsn.h in /sys/src/9/bcm
-
add the callback functions:
/* * I2C */ extern void i2csetup(int); extern long i2crecv(I2Cdev*, void*, long, ulong); extern long i2csend(I2Cdev*, void*, long, ulong);
-
-
edit pi in /sys/src/9/bcm
-
add I2C device definitions to dev section:
i2c i2c
under gpio if you have no preference where to put it
-
-
edit mkfile in /sys/src/9/bcm
- confirm/change CONF variable to to pi, to build RPI 1 kernel
compile and install new kernel
The process also requires mounting the boot partition and editing config files.
mount RPI 1 boot partition
RPI1 uses a fat/dos partition with config files that are used to boot the board.
The boot partition can be mounted with 9fs script:
9fs pidos
This will bind the boot partition to /n/pidos folder.
If you get an error that partition cannot be found (usually when using rpuc for remote access), block kernel device needs to be mounted first:
bind -b '#S' /dev
This will mount /dev/sdM0 directory with partition devices on the sd card.
compile kernel
In /sys/src/9/bcm directory run the build command:
cd /sys/src/9/bcm
mk install
This will create new kernel image 9pi in /arm directory.
Don't forget to clean up AFTER installing the kernel:
mk clean
installing the kernel
It is a good idea to keep old kernel images around in case anything goes wrong, to restore the previous working state. Either rename old images to a new name and copy new images using the old name. Or Copy new images with a new name and edit the config file, selecting the kernel image. For example, we will copy new images with a new name and edit the config file to showcase where everything is.
The mounted pidos partition in /n/pidos should contain many files. This time we're interested in 9pi and config.txt (ignore the cmdline.txt that was edited during RPI 1 setup).
-
check if boot partition is mounted to /n/pidos (check above)
-
copy new kernel image to boot partition
cp /arm/9pi /n/pidos/9pi.i2c
-
edit config file to reference new kernel image
-
edit file /n/pidos/config.txt and change:
[pi1] kernel=9pi
to
[pi1] kernel=9pi.i2c
or change all kernel variables referencing 9pi image
-
-
reboot the system
fshalt -r
-
don't forget to clean up the source directory (see above)