I have a problem with I2C clock in Raspbian Buster (using either SMbus or i2c-dev). It defaults to 50 kHz on RPi 4B and to 62.5 kHz on RPi 3B and Zero W. However, if I set the speed i2c_arm_baudrate=200000 > /boot/config.txt on RPi 4B, then speed is 100 kHz.
But the strange thing that for the first few seconds it is actually 200 kHz, so I2C slave devices that have some kind of initialization only work if I initialize them again after waiting for a couple of seconds in the program. The clock mismatch happens no matter what i2c devices I use, in fact it happens even if there are no devices on the bus (writing 0 to address 9):
Python, SMbus:
import smbus
from time import sleep
bus = smbus.SMBus(1)
while True:
try:
bus.write_byte(9, 0)
sleep(.1)
except OSError:
pass
C, i2c-dev:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#define delay(A) usleep(A*1000)
char *i2cbus = "/dev/i2c-1";
int addr = 9;
int data[1] = {0};
void loop(void)
{
int i2cfile = open(i2cbus, O_RDWR);
ioctl(i2cfile, I2C_SLAVE, addr);
write(i2cfile, data, 1);
}
int main()
{
for(;;) {
loop();
delay(100);
}
}
So, my question is: how to access BCM i2c speed registers? Datasheet says that the register is at offset 0x7e804000, but when I try inline assembly like so:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint32_t reg = 0;
__asm(
"push {r0}\n\t"
"ldr r0, =0x7e804000\n\t"
"ldr %[result], [r0]\n\t"
"pop {r0}\n\t"
: [result] "=r" (reg)
);
printf("%x\n", reg);
}
I get segmentation fault. (my knowledge in ARM assembly is lacking)