Arbitrary I2C baud rates?

207 views
Skip to first unread message

arghnews

unread,
Jun 12, 2020, 12:40:37 PM6/12/20
to bcm2835
Hi,

In the docs for bcm2835I2CClockDivider, you have a choice of 4 preset baud rates.

My setup is a raspberry pi 4, with 3 I2C peripherals connected through the GPIO pins.

Is it possible to set arbitrary baud rates? We have long wires and the signal is coming out messily, so I'd like to reduce the baud rate if possible. However judging by the docs, I'm guessing only those 4 preset baud rates are supported by the bcm2835? Searching though various forums like the raspberry pi one and stack overflow etc. you have some people claiming to have managed it, but they don't seem or even explicitly state they have no idea if the baud rate has changed.

Ie. as per this raspberry pi overlays page you can set i2c_arm_baudrate in /boot/config.txt, and indeed I have set that to 1000. However when I check on the oscilloscope, the baud rate is still 100kHz, so I suspect this is being ignored. And hence I'm posting here to ask if this is possible.

This thread from this group seems to suggest it is possible, and the person posting ends by saying changing their raspberry pi's core clock seemed to fix their problem. Does this mean the baud rate is tied to the core clock, therefore can I vary it this way? Any information here would be appreciated, I'm a noob and ignorant.

My thanks to anyone taking the time to read this, I appreciate your time.

Arjan van Vught

unread,
Jun 12, 2020, 1:10:21 PM6/12/20
to bcm...@googlegroups.com

Op 12 jun. 2020, om 18:40 heeft arghnews <argh...@gmail.com> het volgende geschreven:

Hi,

In the docs for bcm2835I2CClockDivider, you have a choice of 4 preset baud rates.

/* set I2C clock divider by means of a baudrate number */
void bcm2835_i2c_set_baudrate(uint32_t baudrate)
{
uint32_t divider;
/* use 0xFFFE mask to limit a max value and round down any odd number */
divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE;
bcm2835_i2c_setClockDivider( (uint16_t)divider );
}

where you can set any baudrate which is supported by the SoC.

In the Linux user-land, the BCM2835_CORE_CLK_HZ is a tricky define; there are Linux processes which can and/or able to change the core clock. 


My setup is a raspberry pi 4, with 3 I2C peripherals connected through the GPIO pins.

Is it possible to set arbitrary baud rates? We have long wires and the signal is coming out messily, so I'd like to reduce the baud rate if possible. However judging by the docs, I'm guessing only those 4 preset baud rates are supported by the bcm2835? Searching though various forums like the raspberry pi one and stack overflow etc. you have some people claiming to have managed it, but they don't seem or even explicitly state they have no idea if the baud rate has changed.

Ie. as per this raspberry pi overlays page you can set i2c_arm_baudrate in /boot/config.txt, and indeed I have set that to 1000. However when I check on the oscilloscope, the baud rate is still 100kHz, so I suspect this is being ignored. And hence I'm posting here to ask if this is possible.

Please note that this library does not work with Linux device drivers, hence overlays are not used. When working with this library, the must no device drivers loaded. 

- Arjan

arghnews

unread,
Jun 13, 2020, 4:42:27 PM6/13/20
to bcm2835
Hi Arjan, first my thanks for your prompt response.

Using bcm2835_i2c_set_baudrate I was able to change the i2c clock speed significantly down from 100kHz to 10,000Hz, 5,000 or 1000Hz IIRC but no lower. The signal was much cleaner and this was awesome.

If you don't mind I have a few more questions.

When you say overlays aren't used, you mean the dtoverlay style items in the raspberry pi's /boot/config.txt?
For me this library worked with dtparam=i2c_arm=on present or missing in my /boot/config.txt, is this an overlay? Are you saying this may interfere with this library's operation?
Or are you referring to things specifically called an overlay like dtoverlay=i2c1 in /boot/config.txt instead?

I'd like to be able to use multiple GPIO pins, two more pairs of them in fact, to have 2 more I2C buses.
I am ignorant in this area, however my guess as to how is as follows:
Looking through bcm2835.c, the bcm2835_init function reads /proc/device-tree/soc/ranges to find a base address and size of the peripherals block. Then it goes and mmap's this and sets all the pointers, things like bcm2835_bsc1 that is used as the address that pointers are offset from in i2c functions. Therefore, in order to use some different pins, could I alter the initial address/size read from /proc/device-tree/soc/ranges to point to other pins? If so or if not, could you point me to any documentation that describes how to do this/what these addresses should be?
Perhaps I've got it completely wrong, or it's not possible, if so please let me know.

Any advice appreciated.
Thanks for your time, I'm very grateful.

Justin
Reply all
Reply to author
Forward
0 new messages