如何将树莓派HAT的概念扩展为一个可堆叠的系统
单个树莓派HAT功能实用,但许多有趣的应用需要同时使用多个接口板。一旦将多个HAT组合在一起,就可能出现资源冲突:GPIO引脚、SPI片选、I²C地址、中断线以及设备树覆盖层可能会发生重叠。
本项目的目标是让多个树莓派HAT在同一个堆叠中协同工作,而无需手动解决冲突。
我为什么决定这么做?
我最初的想法是为有趣的界面技术设计树莓派HAT。但在开发这个概念的过程中,一个疑问一直萦绕在我心头:
为什么树莓派只需使用一个HAT?
当多个功能可以组合使用时,树莓派的实用性会大大提高。例如,一个堆栈可以包含CAN FD、RS-485、10BASE-T1S、10BASE-T1L、UART或以太网接口。
这促使我想到将常规的HAT概念扩展,加入一个简单的堆叠层。结果就是我称之为HAT++的东西。
基于这一概念的首批电路板现已以BE-IIS-HPP的名称开发完成。
它是如何工作的?
基本思想是为堆栈中的每个HAT分配一个定义好的实例。
每个实例都分配了硬件资源,例如SPI芯片选中、中断线、I²C地址以及板级控制信号。这可以避免多个树莓派HAT同时使用时可能出现的典型资源冲突。
以下示例展示了如何将不同的HAT组合成一个堆叠。每个板支持实例I以及另外两个可选的实例位置。一个堆叠需要一个配置为实例I的板,并可选择性地使用额外配置为实例II至V的板。
硬件资源分配
实例模式不仅仅是一个标签,它还定义了板卡所使用的硬件资源。
某些资源是独占的,例如SPI片选信号和中断信号;其他资源则由堆栈中的所有板卡共享,或由一组特定的实例共享。
按实例模式提供的专属资源
实例 I 使用:
•CSN0 在 GP8 上
•IRQ0 是 GP6
实例II使用:
•CSN1在GP
•IRQ1 是 GP5
实例III使用:
•CSN2 在 GP16 上
•IRQ2 是 GP12
实例 IV 使用:
•IRQ3 是 GP14
实例 V 使用:
•IRQ4 是 GP25
共享硬件资源
SPI总线信号由实例I、II和III共享:
•GP11上的SCLK
•MISO 是 GP9
•MOSI 是 GP10
复位信号由所有实例模式共享:
•RESET 位于 GP13
第一个I²C总线由所有实例模式共享:
•SCL0 是 GP1
•SDA0 是 GP0
第二个I²C总线由实例I、IV和V共享:
•SCL1 在 G
•SDA1 是 GP2
通过此任务,可以实现混合堆叠。例如,堆叠可由三个基于SPI的板和两个基于I²C的板组成,或由两个基于SPI的板和三个基于I²C的板组成。
每个板子都清楚在所选的实例模式中可以使用哪些信号。这使得堆栈具有可预测性,并避免了芯片选择、中断和控制信号的重叠。
默认实例与HAT+兼容性
实例 I 是默认配置。
在此模式下,该板遵循标准的树莓派HAT+概念,可在树莓派启动时被检测到。为此,该板在树莓派HAT识别总线上提供了I²C EEPROM。
这使得堆栈中的第一个板子像一个普通的树莓派HAT一样工作。当向堆栈中添加更多板子时,会使用额外的实例模式。
有关HAT EEPROM的底层细节和识别过程,请参阅官方Raspberry Pi HAT+规格说明。
选择实例模式
额外的可堆叠 Raspberry Pi HATATAT 需要移至另一个实例模式。
为此,每个板上都配有按钮和状态指示灯。指示灯显示当前选定的实例模式。同一堆栈中的每块板必须使用不同的实例模式,并且堆栈中至少有一块板需配置为实例I。
重要的是,HAT识别存储器并非以简单的固定地址I²C EEPROM形式实现,而是由电路板上的小型微控制器来处理这一功能。
按下按钮时,微控制器会更改所选的实例模式。这也会改变用于HAT识别数据的I²C地址。只有实例I使用标准的Raspberry Pi HAT EEPROM地址。
实例地址如下:
•实例 I:0x50
•实例 II:0x60
•实例 III:0x70
•实例 IV:0x74
•实例 V:0x76
除了识别地址外,微控制器还控制着板级的配置信号。根据所选的实例模式,它会为板上的控制器IC选择所需的SPI片选、中断线或I²C地址配置。
这使得相同的电路板设计可以在不同堆叠位置使用,而无需更改焊桥或手动重新布线硬件。
加载附加堆栈覆盖层
树莓派引导程序通过标准的HAT识别地址检测到堆栈中的第一个板。
附加的板使用不同的识别地址,因此在正常启动流程之后,由一个小型 systemd 服务来处理它们。
该服务在启动后运行一次,会遍历额外的HAT识别地址(例如0x60、0x70、0x74和0x76),并使用树莓派HAT EEPROM工具读取存储的HAT数据。
如果找到有效的HAT数据,服务将从EEPROM内容中提取覆盖层名称,并使用dtoverlay加载所需的设备树覆盖层。
这会保持第一块板的正常树莓派HAT行为,而额外的堆叠板将在系统启动时自动添加。
叠加要求
要实现这一功能,设备树叠加层也必须为堆叠操作做好准备。
每个板卡叠加层都对应支持的实例模式。这一点很重要,因为所选的实例模式会影响板卡所使用的硬件资源。
一个重要的规则是,在加载堆栈覆盖层之前,资源不能被其他 Linux Linux Linux 驱动程序占用。如果 SPI SPI SPI 芯片选通已被 spidevv 占用,则后续的其他驱动程序无法干净地重复使用该资源。
因此,Instance I I I 嵌套层会禁用未使用的 spidev 设备,这些设备否则会阻塞堆栈所需的片选线:
实例I叠加层还会在树莓派HAT识别总线上使额外的HAT识别记忆可见。这些与EEPROM兼容的设备由启动服务用于检测堆栈中的其他板卡。
通过此准备,第一个板仍然遵循正常的树莓派HAT启动流程。启动后,堆栈集成服务可以访问额外的识别存储器,读取其中的叠加字符串,并为堆栈中的其他板加载匹配的叠加内容。
这是硬件实例选择、与EEPROM兼容的识别存储器以及Linux叠加层处理协同工作的环节。
安装与系统集成
基本机制很简单:
•模拟一个兼容 HAT 的 I²C EEPROM
•将所需的叠加信息存储其中
•启动后扫描附加的EEPROM地址
•使用树莓派工具加载检测到的设备树覆盖层
但完整的系统需要的不仅仅是EEPROM逻辑。
树莓派必须安装所需的内核模块,systemd 服务必须配置好,udevudev 规则必须可用,并且必须包含必要的内核模块或驱动设置步骤。
为了使此过程可重复,我使用了一个安装脚本。该安装程序可在从 Raspberry Pi 11 到 Raspberry Pi 5 的所有支持系统上运行。
成功的安装如下所示:
重启后,堆栈集成服务即可使用。它能够扫描额外的HAT识别地址,读取存储的叠加字符串,并自动应用匹配的叠加内容。
HAT++系统Linux集成所需的全部源文件均开放,可在安装程序的代码仓库中获取。
这包括用于不同板型的安装脚本、systemd 服务、udevudev 规则以及设备树覆盖层。
目标是保持系统的透明性和可复现性。任何对实现细节感兴趣的人都可以查看源代码,重用集成概念的部分内容,或根据自己的实验需求进行调整。
本文编译自hackster.io





