BPI-M5 with Armbian and UARTs/I2C/SPI overlays

Hello there,

I wonder if I’m the only one with this problem, or perhaps others who care about the same requirements, are just more competent on embedded linux than I am (which is not very hard, I admit).

I’m trying to get my M5 running with a maintained linux that can :

  • keep itself updated with its package manager, and ideally follow major upgrades
  • run docker
  • UARTs support (I’ll be needing two among UART_EE_A on header gpio pins 8 & 10, UART_EE_B on pins 33 & 15, UART_AO_B on pins 12 & 37)
  • I2C support (have a RTC and a Matrix orbital graphic display there)
  • SPI support (for a RFM69 radio with mysensors, but later)

The images linked on the BPi wiki are ok for short term, I tested ubuntu server 20.04 and debian buster, however I noticed that both have the kernel frozen in 4.9. Although dist upgrade to 22 for ubuntu, and bullseye for debian, did work, this broke docker as the immediately noticeable result. And it is probably only the tip of the iceberg.

Using recent binaries and libs on top of an outdated kernel looks to me like asking for trouble.

And, even with docker, containers run on the same kernel so… I’ll run into trouble with the containerized software as well.

I also tried the armbian image from BPi, but first apt upgrade replaces the kernel and kicks all overlays out. So I’d have to freeze the kernel, so back with the maintenability issue, even if I’d have more time with a 6.x kernel. That, and only one UART works.

So unless I missed something, so far, official Armbian fits the bill for the maintainable part, but it seems to lack the I/O support part.

With

# cat /boot/armbianEnv.txt
verbosity=1
console=both
overlay_prefix=meson
rootdev=UUID=b0ae2d42-5b5d-41cc-bf0c-3dad452a18d4
rootfstype=ext4
overlays=i2cA i2cB uartA uartC
user_overlays=
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u

Here are the provider overlay’s result at the debug console :

Applying kernel provided DT overlay meson-i2cA.dtbo
failed on fdt_overlay_apply(): FDT_ERR_NOTFOUND
343 bytes read in 2 ms (167 KiB/s)
Applying kernel provided DT overlay meson-i2cB.dtbo
failed on fdt_overlay_apply(): FDT_ERR_BADMAGIC
base fdt does did not have a /__symbols__ node
make sure you've compiled with -@
238 bytes read in 2 ms (116.2 KiB/s)
Applying kernel provided DT overlay meson-uartA.dtbo
failed on fdt_overlay_apply(): FDT_ERR_BADMAGIC
base fdt does did not have a /__symbols__ node
make sure you've compiled with -@
238 bytes read in 2 ms (116.2 KiB/s)
Applying kernel provided DT overlay meson-uartC.dtbo
failed on fdt_overlay_apply(): FDT_ERR_BADMAGIC
base fdt does did not have a /__symbols__ node
make sure you've compiled with -@
Error applying DT overlays, restoring original DT

This issue is mentioned in a post on the armbian forum, but so far no news.

So my question is : how difficult is it to create those overlays, and what is needed ? I keep looking at documentation about the subject, but so far it is totally esoteric to me and I don’t even know if it is possible on the stock armbian distribution, or if building a system from scratch is needed. Or perhaps someone already has dts working for armbian ?

Having to recompile them when the kernel gets updated would be a relatively little constraint. The uses of the UARTs will be monitored so if I break something with a kernel upgrade, I will know it quickly.

Thanks for reading.

I’ll keep the post updated if I find something, of course.

It seems armbian shipped overlays have incorrect addresses in target paths for bpi-m5 (probably meant for another amlogic board). You can decompile bpi-m5 dtb and needed overlay dtbos with dtc -Idtb -Odts -o file.dts file.dtb, find correct addresses in decompiled bpi-m5 dts file and fix them in decompiled overlay dts files. Then compile overlays with dtc -@ -Idts -Odtb -o file.dtbo file.dtso. You can save them under different filenames to prevent overwriting on upgrade and change armbianEnv.txt accordingly. And file a bug on armbian about the issue.

Thanks for answering. As I said I’m completely ignorant on the topic and hours (days?) of reading docs on the subject away from understanting what I’m doing. Last time I even compiled a kernel was… can’t remember. And that was on x86, already had ACPI and sundries. Only ARM boards I had before were RPi with their OS, but then this is hw and sw bundled together by the same org.

If I get it correctly, I should, for example for uartA :

  • On the official armbian, decompile the shipped dtbo :

dtc -Idtb -Odts -o ~/meson-uartA.dts /boot/dtb-6.1.11-meson64/amlogic/overlay/meson-uartA.dtbo

  • On any bpi distro (armbian or would debian do ? the bpi armbian had only the first uart working if I remember) : same with its matching uart1.dtbo

  • Pick address(es) from the second dts file and replace in the first, ~/meson-uartA.dts

  • Recompile the modified dts :

dtc -@ -Idts -Odtb -o /boot/overlay-user/uart1.dtbo ~/meson-uartA.dts

However there’s something disturbing :

BPi Debian’s decompiled uart1.dtbo has no address

/ {

	fragment@0 {
		target = < 0xffffffff >;

		__overlay__ {
			status = "okay";
		};
	};

	__fixups__ {
		uart_A = "/fragment@0:target:0";
	};
};

but uart_A matches meson64_bananapi_m5.dtbo which contains

/ {
	...
	__symbols__ {
		...
		uart_A = "/serial@ffd24000";
		...
	};
};

BPi’s Armbian from meson-uartA.dtbo :

/ {
	compatible = "amlogic,meson-gxbb";

	fragment@0 {
		target-path = "/soc/bus@c1100000/serial@84c0";

		__overlay__ {
			status = "okay";
		};
	};
};

The addresses are completely different. This is getting me real confused.

As for filing a bug to armbian, I’ll first try to understand things a little more, because right now apart of telling them “huh ! doesn’t work !” my contribution will be next to useless :slight_smile:

I grabbed addresses from the BPi debian image’s decompiled meson-sm1-bananapi-m5.dts, which gave me :

            target-path = "/soc/bus@ffd00000/serial@24000";
            target-path = "/soc/bus@ffd00000/serial@23000";
            target-path = "/soc/bus@ffd00000/serial@22000";
            target-path = "/soc/aobus@ff800000/serial@4000";

So I tried :

dtc -Idtb -Odts -o ~/meson-uartA.dts /boot/dtb-6.1.11-meson64/amlogic/overlay/meson-uartA.dtbo
cp ~/meson-uartA.dts uart1.dts
sed -i -e 's!bus@c1100000!bus@ffd00000!' -e 's!serial@84c0!serial@24000!' uart1.dts

cat uart1.dts
/dts-v1/;

/ {
    compatible = "amlogic,meson-gxbb";

    fragment@0 {
            target-path = "/soc/bus@ffd00000/serial@24000";

            __overlay__ {
                    status = "okay";
            };
    };
};

dtc -@ -Idts -Odtb -o /boot/overlay-user/uart1.dtbo ~/uart1.dts

And so on with uart2, uart3, uart4.

Compiled overlays uart[123] load fine

Applying user provided DT overlay uart1.dtbo
238 bytes read in 2 ms (116.2 KiB/s)
Applying user provided DT overlay uart2.dtbo
238 bytes read in 2 ms (116.2 KiB/s)
Applying user provided DT overlay uart3.dtbo
232 bytes read in 3 ms (75.2 KiB/s)
Applying kernel provided DT fixup script (meson-fixup.scr)

Not uart4 though (would be UART_AO_B on pins 12&37) :

Applying user provided DT overlay uart4.dtbo
failed on fdt_overlay_apply(): FDT_ERR_NOTFOUND
Error applying DT overlays, restoring original DT

I’m dropping this one for now, I’ll figure it out later.

So, with

user_overlays=uart1 uart2 uart3

in my /boot/armbianEnv.txt I get

pi@gtlpi:~$ ls -l /dev/ttyAML*
crw--w---- 1 root tty     243, 0 21 avril 16:50 /dev/ttyAML0
crw-rw---- 1 root dialout 243, 6 21 avril 16:50 /dev/ttyAML6
crw-rw---- 1 root dialout 243, 7 21 avril 16:50 /dev/ttyAML7
crw-rw---- 1 root dialout 243, 8 21 avril 16:50 /dev/ttyAML8

I can set their baudrate/data format, open them in r/w in python or screen, all without error.

But they’re all deaf and mute : a usb/serial adapter wired on the expected pins, nothing either in or out.

Isn’t there something with missing setting up mux so the signals from the UARTs get routed to the actual SOC pins ?

I throw that guess because the SOC pins on the schematic have multiple labels that imply pins are multi-purpose, but I have no idea how this selection is done.

Got it working for the first two UARTs

uart1 on GPIO pins 8(tx),10(rx)

/dts-v1/;

/ {

    compatible = "amlogic,meson-gxbb";

    fragment@0 {
        target-path = "/aliases";

        __overlay__ {
            serial1 = "/soc/bus@ffd00000/serial@24000";
        };
    };

    fragment@1 {
        target-path = "/soc/bus@ffd00000/serial@24000";

        __overlay__ {
            pinctrl-0 = <0xdc 0xdd>;
            pinctrl-names = "default";
            status = "okay";
        };
    };
};

uart2 on GPIO pins 33(tx), 15(rx)

/dts-v1/;

/ {
    compatible = "amlogic,meson-gxbb";

    fragment@0 {
        target-path = "/aliases";

        __overlay__ {
            serial2 = "/soc/bus@ffd00000/serial@23000";
        };

    };

    fragment@1 {
        target-path = "/soc/bus@ffd00000/serial@23000";

        __overlay__ {
            pinctrl-0 = <0xde>;
            pinctrl-names = "default";
            status = "okay";
        };
    };
};

Some things that helped when I understood them :

  • that pinctrl-0 refer to phandles of nodes already defined in /boot/dtb-6.1.11-meson64/amlogic/meson-sm1-bananapi-m5.dtb that ships with the official Armbian
  • target-path = “/aliases” fragment maps the peripheral to the correct /dev/ttyAMLx number

And uart4 on GPIO pins 12(tx), 37 (rx)

/dts- v1/;

/ {
    compatible = "amlogic,meson-gxbb";

    fragment@0 {
        target-path = "/aliases";

        __overlay__ {
            serial4 = "/soc/bus@ff800000/serial@4000";
        };
    };

    fragment@1 {
        target-path = "/soc/bus@ff800000/serial@4000";

        __overlay__ {
            pinctrl-0 = <0x103>;
            pinctrl-names = "default";
            status = "okay";
        };
    };
};

I2C on pins 5(scl), 3(sda)

/dts-v 1/;

/ {
    compatible = "amlogic,meson-gxbb";

    fragment@0 {
        target-path = "/aliases";

        __overlay__ {
            i2c0 = "/soc/bus@ffd00000/i2c@1d000";
        };
    };

    fragment@1 {
        target-path = "/soc/bus@ffd00000/i2c@1d000";

        __overlay__ {
            pinctrl-0 = <0x6f 0x70>;
            pinctrl-names = "default";
            status = "okay";
        };
    };
}

I don’t know how this will survive a kernel upgrade though, if the pinctrl phandles change. But this will be easy to fix then.

This is an old thread now.

The main reason why people buy SBC’s is to be able to drive projects through the GPIO pins in the spirit of the original RPI project.

Therefore the proper resolution of issues such as the above should be resolved especially by the experts at BPI who promote their products.

Where are you?

Although we wish we are, we cannot be expected to be experts at resolving such intricate issues. Where are you SINOVOIP?

O, my undead thread.

To be honest, I’ve reverted that board to a usage where GPIO and its buses are not needed, a simple light compute node, and not bought boards of the line since, I simply spent way too long at this, in hope to make my money worth it. It turned out to be a case of succumbing to sunk cost fallacy.

I don’t know if sinovoip are still distributing frozen kernel images on google drive (without even the post install scripts when I used it, like you had to renew the ssh host key manually) as sole OS, in which case Armbian seems to remain the only viable and relatively easy to set up linux to run here. Maybe its support of the board has improved since but I’ve switched to other matters.

What I have tinkered above was merely a workaround, not worth the effort if you aim to use your boards in applications and therefore focus your time and efforts on the application, not to having the base system work. I don’t even know if I did it correctly for that matter, of it is just a timebomb that will explode during an update, when you forgot all about it.

That’s my take on it.

Others, who have either sufficient skill with linux kernel and low level processes, or interest and time to hone it, will of course see this differently.

Why on earth would anybody pay for an SBC which can only be used for light computer work?

For the same money , even less, you can get a tv box in a proper box, with wifi/bluetooth chip, same processors ,same size EMMC + power supply.

It is actually a lot easier to replace the given Android OS with Armbian. Easier still to shift from sdcard to EMMC.

For me the main purpose of buying the M5 was the possibility of driving the the 40 GPIO pins as originally intended by by the RPI project.

It is a real pity that the M5 is not supported with updated software a better wiki.

In my case I would not have, knowing this beforehand.

But it turns out some vendors simply don’t know, or don’t care. In my case, I signalled this to my vendor and they did not see the problem in using a linux OS with a frozen kernel, that therefore can’t go without a dist upgrade without breaking apart.

I bought this to stand in the place of a RPi, where I needed 2 UARTs, and using USB serial converters would have been awkward, with a usb cable sticking out of the enclosure back into the RPi.

Well. I ended with an RPi with USB cable sticking out of the enclosure, back into the RPi. But it works with the unmodified distro, that can take updates/dist upgrades without blowing up.

@PikaBZH,

I have been purchasing from China for quite some time now and I realise that most vendors do not have a clue of what it is they are selling. Therefore I don’t expect vendors to go into such technical details.

However I do expect BPI to notice and act.

There is a saying in the West which goes:

“Give a man a fish and he will have one good meal. Teach the man how to fish and he will eat for the rest of his life.”