树莓派 4B 添加多个 SPI 设备

根据 BCM2711 引脚图[1][2]的设置,树莓派 4B 默认引出的 40Pin 可以添加多组 SPI 总线控制器:SPI3、SPI4、SPI0、SPI5 和 SPI1。默认情况下, SPI4 的 SCLK 和 SPI1 的 CE1_N 存在冲突。如果要启用多个 SPI,需要在内核启动时,加载对应的 Device Tree Overlay,仿照默认的 spi0-cs-overlay.dts[3],我们可以设置对应的多个 SPI 控制器。

我们首先修改默认的 SPI0,使得其只保留一条片选线,并用 dtc 命令编译:

/dts-v1/;
/plugin/;


/ {
        compatible = "brcm,bcm2835";

        fragment@0 {
                target = <&amp;spi0_cs_pins>;
                frag0: __overlay__ {
                        brcm,pins = <8>;
                };
        };

        fragment@1 {
                target = <&amp;spi0>;
                frag1: __overlay__ {
                        cs-gpios = <&amp;gpio 8 1>;
                        status = "okay";
                };
        };

        __overrides__ {
                cs0_pin  = <&amp;frag0>,"brcm,pins:0",
                           <&amp;frag1>,"cs-gpios:4";
        };
};
# compile
dtc -I dts -O dtb -o spi0-1cs.dtbo spi0-1cs.dts
# copy to boot partition
sudo cp spi0-1cs.dtbo /boot/overlays

树莓派的官方镜像已经提供了 SPI3,SPI4,SPI5 和 SPI1,我们只需修改 /boot/config.txt,注意,我们要取消注释默认的 spi=on

#dtparam=spi=on
dtoverlay=spi0-1cs
dtoverlay=spi3-1cs
dtoverlay=spi4-1cs
dtoverlay=spi1-1cs

同样,我们可以参考树莓派的默认 dts 编译多个 SPI 从设备描述,比如我根据位于 spi0.0 的 MCP2515 [4] 编译了 spi3.0spi4.0spi1.0 的 3个 CAN控制器,并同样修改 /boot/config.txt

dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=24
dtoverlay=mcp2515-can3,oscillator=8000000,interrupt=25
dtoverlay=mcp2515-can4,oscillator=8000000,interrupt=26
dtoverlay=mcp2515-can1,oscillator=8000000,interrupt=27

查看 dmesg 日志,可以看到 4 个 MCP2515 控制器已经正常工作:

pi@raspberrypi:~$ dmesg | grep spi
[    4.387592] spi-bcm2835 fe204600.spi: no tx-dma configuration found - not using dma mode
[    4.391881] spi-bcm2835 fe204600.spi: chipselect 0 already in use
[    4.391898] spi_master spi3: spi_device register error /soc/spi@7e204600/spidev@0
[    4.391915] spi_master spi3: Failed to create SPI device for /soc/spi@7e204600/spidev@0
[    4.392332] spi-bcm2835 fe204800.spi: no tx-dma configuration found - not using dma mode
[    4.394967] spi-bcm2835 fe204800.spi: chipselect 0 already in use
[    4.394982] spi_master spi4: spi_device register error /soc/spi@7e204800/spidev@0
[    4.394999] spi_master spi4: Failed to create SPI device for /soc/spi@7e204800/spidev@0
[    4.419969] spi-bcm2835aux fe215080.spi: chipselect 0 already in use
[    4.419986] spi_master spi1: spi_device register error /soc/spi@7e215080/spidev@0
[    4.420005] spi_master spi1: Failed to create SPI device for /soc/spi@7e215080/spidev@0
[    5.351820] mcp251x spi0.0 can0: MCP2515 successfully initialized.
[    5.368085] mcp251x spi3.0 can1: MCP2515 successfully initialized.
[    5.379651] mcp251x spi4.0 can2: MCP2515 successfully initialized.
[    5.390782] mcp251x spi1.0 can3: MCP2515 successfully initialized.

[1] https://elinux.org/RPi_BCM2711_GPIOs
[2] https://www.raspberrypi.org/documentation/usage/gpio/
[3] https://github.com/raspberrypi/linux/blob/rpi-5.4.y/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts
[4] https://github.com/raspberrypi/linux/blob/rpi-5.4.y/arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts