3

I've built a Pi1541 HAT, just for fun, and am now playing with the device-tree autoconfiguration in Raspbian. I've made an overlay that autoloads during boot, based on the EEPROM contents, and that overlay defines the five buttons, the LED and the I2C OLED display. I set the LED to trigger on "mmc0" so I can see that this activates very early on during boot. The buttons and LEDs work whether the overlay is autoloaded or manually loaded.

If I load the overlay manually using dtoverlay, the display usually works (produces a framebuffer) after one failed attempt, but if I let it load the overlay automatically at boot, the display never loads. When it fails, the kernel logs an i2c error: "ssd1307fb 1-003c: Couldn't send I2C command." (the ssd1306 overlay is based on the ssd1307fb driver).

To me it looks like the i2c_arm/i2c1 bus is available at this point, but it's unable to talk to i2c devices. Does anyone have any clues to why this happens?

Here an excerpt from the dts - this is basically verbatim from the standard ssd1306 overlay:

    fragment@0 {
        target = <&i2c_arm>;
        __overlay__ {
            status = "okay";

            #address-cells = <1>;
            #size-cells = <0>;

            ssd1306: oled@3c{
                compatible = "solomon,ssd1306fb-i2c";
                reg = <0x3c>;
                solomon,width = <128>;
                solomon,height = <64>;
                solomon,page-offset = <0>;
            };
        };
    };

    __overrides__ {
        address = <&ssd1306>,"reg:0";
        width = <&ssd1306>,"solomon,width:0";
        height = <&ssd1306>,"solomon,height:0";
        offset = <&ssd1306>,"solomon,page-offset:0";
        normal = <&ssd1306>,"solomon,segment-no-remap?";
        sequential = <&ssd1306>,"solomon,com-seq?";
        remapped = <&ssd1306>,"solomon,com-lrremap?";
        inverted = <&ssd1306>,"solomon,com-invdir?";
    };

I've searched for ideas for a long time now, and the only vague hints I've found is that there may be something wrong with the i2c mux, or with the pin assignments for the bus.

Addendum: I'm wondering if the vc debug log provides a hint. I removed the i2c display from the overlay and instead loaded the regular ssd1306 overlay from /boot/config.txt, and the log shows that the HAT overlay loads before the i2c configuration, and the ssd1306 overlay loads last:

002568.102: Loaded overlay 'pi1541'
002568.113: Loaded HAT overlay
002568.129: dtparam: i2c_arm=on
002577.255: dtparam: i2c_baudrate=1000000
002586.490: dtparam: audio=on
002768.678: brfs: File read: 3073 bytes
002789.439: brfs: File read: /mfs/sd/overlays/ssd1306.dtbo
002797.757: Loaded overlay 'ssd1306'
002797.774: dtparam: inverted=true
002798.226: dtparam: sequential=true

If I change the order of the statements in /boot/config.txt, there's no change, however. It still works.

0

2 Answers 2

2

I don't know whether it's more confusing or annoying, but I just did a regular "apt-get upgrade", and after that it works. I didn't do a firmware upgrade or anything like that, and it hasn't replaced the kernel, so I have no idea why it suddenly works.

1

I don't know the exact reason for your problem but what catches my eye is the speed of the I2c bus. If I look to your dmesg output then I see the I2c baudrate (bits/sec) is 1MHz! Not sure if the I2c HW on the RPi can even handle this. IIRC, the max. I2c speed of the RPi is 400kHz. And indeed, if I look to the datasheet of the BCM2837 then I see the following in chapter 3.1:

The Broadcom Serial Controller (BSC) controller is a master, fast-mode (400Kb/s) BSC controller. The Broadcom Serial Control bus is a proprietary bus compliant with the Philips® I2C bus/interface version 2.1 January 2000.

This means one SCL period on the I2c bus can only be as fast as 2.5us (1/400000). I assume that this is also valid for the other BCM processors used in other RPi versions.

In your situation at an I2c speed of 1000000Hz that would mean a clock period of 1us...

By default, the RPi I2c speed is set to 100kHz, unless you add the following 2 lines to your /boot/config.txt line:

core_freq=250
dtparam=i2c_baudrate=400000

This would give you an I2c speed of exact 400kHz.

Regarding your other point about the I2c mux: I assume you're talking about a PCA9548 (or derivative)? If so, then I can confirm you that the RPi is handling all the mux communication in a perfect way. I'm using it in a system that runs 24/7 and never had problems so far.

FYI: to have that functionality, I added the following line to my /boot/config.txt file:

dtoverlay=i2c-mux,pca9548,addr=0x70

Just my 2 ct.

1
  • Well spotted, and of course it's risky to run the bus that fast. The speed of the bus was of course one of the things I experimented with during the many iterations I tried. It's been stable ever since the problem in this Question was resolved, so clearly the bus is pretty reliable at 1MHz. I haven't checked whether the bus is actually running at 1MHz, however. Maybe it maxes out at 400KHz anyway.
    – Hans Liss
    Commented Dec 17, 2022 at 12:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.