3. 硬件平台选型与资源映射:ARM Cortex-A 处理器的实战选择

做工业网关,选硬件平台是第一道坎。说实话,市面上能跑 Linux 的 ARM 芯片太多了,但真正适合工控现场的,翻来覆去就那么几款。我个人习惯先看三点:外设是否齐全、供货是否稳定、社区支持是否成熟。这章我就把 i.MX6/8、AM335x、STM32MP1 这三款主流平台掰开揉碎讲清楚,再带你走一遍外设接口映射和中断控制器的配置思路。

3.1 主流 ARM Cortex-A 处理器选型对比

先看一张总览表,后面我再逐个细说。

处理器 核心架构 主频 典型 RAM 工控优势 我的评价
NXP i.MX6 Cortex-A9 单/双/四核 800MHz - 1.2GHz 512MB - 2GB DDR3 生态极好,资料多 老将,稳如磐石
NXP i.MX8 Cortex-A53/A72 异构 1.2GHz - 1.8GHz 1GB - 4GB DDR4 性能强,带 GPU/NPU 适合边缘计算
TI AM335x Cortex-A8 单核 600MHz - 1GHz 256MB - 512MB DDR3 PRU 协处理器,实时性好 工控经典,性价比高
STM32MP1 Cortex-A7 + M4 异构 650MHz - 800MHz 256MB - 1GB DDR3 双核异构,低功耗 新秀,生态在追赶

3.1.1 i.MX6 系列:工控老兵

i.MX6 是我用得最多的平台。为什么?因为它的 BSP 最成熟,Yocto 和 Buildroot 支持都非常好。我在一个电力网关项目里用过 i.MX6 Dual Lite,跑了三年没出过问题。

它的外设接口很全:6 路 UART、2 路 CAN、2 路千兆以太网。对于大多数工业协议网关来说,这个配置绰绰有余。唯一的短板是 GPU 性能一般,但工控场景不需要花哨的界面,够用。

我的建议: 如果项目预算有限,又需要稳定可靠的方案,i.MX6 系列是首选。尤其是 i.MX6ULL,性价比极高,适合做 Modbus RTU 转 TCP 的网关。

3.1.2 i.MX8 系列:边缘计算利器

i.MX8 系列是 i.MX6 的升级版。它用了 Cortex-A53 和 A72 的异构架构,性能提升明显。我记得有个客户要做机器视觉质检,需要同时跑 OpenCV 和多个协议栈,i.MX8M Plus 就非常合适。

但要注意,i.MX8 的功耗比 i.MX6 高不少,散热要做好。另外它的 BSP 相对复杂,第一次接触可能需要花点时间熟悉。

3.1.3 AM335x 系列:工控常青树

TI 的 AM335x 系列,尤其是 AM3358/AM3359,在工业领域地位很高。它的亮点是 PRU(可编程实时单元)。PRU 可以独立处理高速 I/O 任务,比如 EtherCAT 从站、高速脉冲采集等。

我曾经在一个运动控制网关里用 AM3359 的 PRU 做伺服驱动器的实时通信,效果非常好。主 CPU 跑 Linux 处理协议转换,PRU 负责实时控制,分工明确。

注意: AM335x 的 Cortex-A8 核心性能有限,主频最高 1GHz。如果网关需要处理大量加密或视频流,建议考虑 i.MX8 或更高性能的芯片。

3.1.4 STM32MP1 系列:双核异构新选择

STM32MP1 是 ST 推出的双核异构处理器,一个 Cortex-A7 跑 Linux,一个 Cortex-M4 做实时控制。它的优势是 低功耗和 STM32 生态。如果你之前用过 STM32 单片机,上手会很快。

不过它的 Linux 生态还在完善中,有些驱动需要自己移植。我建议用在中等复杂度的网关项目上,比如采集几十个传感器数据,然后通过 MQTT 上传云端。

3.2 外设接口映射:从芯片引脚到 Linux 设备

选好芯片后,下一步就是外设接口映射。说白了,就是把芯片的物理引脚和 Linux 内核里的设备驱动对应起来。这部分我踩过不少坑,下面重点说几个关键接口。

3.2.1 UART 接口映射

UART 是工控网关最常用的接口,用来接 Modbus RTU、PLC、串口屏等。Linux 下 UART 设备通常映射为 /dev/ttyS0、/dev/ttyS1 等。

以 i.MX6 为例,它的 UART 引脚复用关系如下:

// 设备树中 UART2 的配置示例
&uart2 {
    pinctrl-names = "default";
    pinctrl-0 = &pinctrl_uart2;
    status = "okay";
};

pinctrl_uart2: uart2grp {
    fsl,pins = <
        MX6QDL_PAD_EIM_D26__UART2_TX_DATA   0x1b0b1
        MX6QDL_PAD_EIM_D27__UART2_RX_DATA   0x1b0b1
    >;
};

这里要注意 电气特性。工控现场经常有长距离通信,我建议在 UART 引脚外加 RS-485 收发器,比如 SP3485。设备树里不需要改,硬件上接好就行。

避坑指南: 我曾经在 AM335x 上遇到过 UART 波特率不准的问题。原因是晶振精度不够,导致 115200bps 实际只有 114800bps。后来换了 24MHz 高精度晶振才解决。所以,晶振选型不能省。

3.2.2 SPI 与 I2C 接口映射

SPI 和 I2C 主要用于板级通信,比如接 ADC、DAC、传感器、LCD 等。

  • SPI:速度快,适合大数据量传输。Linux 下映射为 /dev/spidev0.0。注意 SPI 的片选信号(CS)要正确配置,否则设备无法选中。
  • I2C:引脚少,适合低速设备。映射为 /dev/i2c-0。I2C 地址冲突是常见问题,建议用 i2cdetect 工具扫描总线。

我习惯在设备树里把 SPI 和 I2C 的引脚功能固定下来,避免和其他外设冲突。比如:

// SPI1 设备树配置
&ecspi1 {
    pinctrl-names = "default";
    pinctrl-0 = &pinctrl_ecspi1;
    status = "okay";

    spidev@0 {
        compatible = "spidev";
        reg = <0>;
        spi-max-frequency = <20000000>;
    };
};

3.2.3 CAN 接口映射

CAN 总线在工业现场非常普遍,尤其是汽车和工厂自动化。Linux 下 CAN 设备映射为 can0、can1,通过 SocketCAN 接口操作。

以 STM32MP1 为例,它的 CAN 控制器需要外接 CAN 收发器,比如 TJA1050。设备树配置如下:

// CAN1 设备树配置
&can1 {
    pinctrl-names = "default";
    pinctrl-0 = &pinctrl_can1;
    status = "okay";
};

pinctrl_can1: can1grp {
    pins1 {
        pinmux = <STM32_PINMUX('A', 11, AF9)>; // CAN1_RX
        bias-pull-up;
    };
    pins2 {
        pinmux = <STM32_PINMUX('A', 12, AF9)>; // CAN1_TX
        drive-open-drain;
    };
};
小技巧: 调试 CAN 总线时,可以用 candump can0 抓包,用 cansend can0 123#DEADBEEF 发送测试帧。如果收不到数据,先检查终端电阻(120Ω)是否接好。

3.2.4 Ethernet 接口映射

千兆以太网是工业网关的标配。Linux 下映射为 eth0、eth1。i.MX6 和 AM335x 都内置了 MAC 控制器,需要外接 PHY 芯片,比如 KSZ9031。

设备树里要指定 PHY 的地址和复位引脚:

// 以太网设备树配置
&fec1 {
    pinctrl-names = "default";
    pinctrl-0 = &pinctrl_enet1;
    phy-mode = "rgmii";
    phy-handle = &phy0;
    status = "okay";

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

        phy0: ethernet-phy@0 {
            reg = <0>;
            reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
        };
    };
};

嗯,这里要注意 PHY 的复位时序。有些 PHY 芯片复位后需要等待一段时间才能正常工作,我一般加一个 50ms 的延时。

3.3 GPIO 与中断控制器

GPIO 是工控网关的“手脚”,用来控制继电器、读取按钮状态、驱动 LED 等。Linux 下 GPIO 通过 /sys/class/gpio 或 libgpiod 操作。

中断控制器(GIC)负责把外设的中断信号路由到 CPU。ARM Cortex-A 系列通常使用 GIC-400 或 GIC-500。

3.3.1 GPIO 映射与操作

以 i.MX6 为例,GPIO 的编号计算方式:gpio_number = bank * 32 + pin。比如 GPIO1_IO16 就是 1 * 32 + 16 = 48。

设备树里配置 GPIO 为输出:

// GPIO 输出配置
gpio-leds {
    compatible = "gpio-leds";
    status = "okay";

    led-red {
        label = "red-led";
        gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
        linux,default-trigger = "heartbeat";
    };
};

用户空间操作:

# 导出 GPIO48
echo 48 > /sys/class/gpio/export
# 设置为输出
echo out > /sys/class/gpio/gpio48/direction
# 输出高电平
echo 1 > /sys/class/gpio/gpio48/value
注意: 工控现场有强电磁干扰,GPIO 引脚一定要加光耦隔离。我曾经在一个变频器附近的项目里,没加隔离导致 GPIO 误触发,继电器乱跳。后来加了 TLP185 光耦,问题解决。

3.3.2 中断控制器配置

中断控制器负责管理所有外设的中断。Linux 设备树里需要指定中断类型和触发方式。

以按键中断为例:

// 按键中断配置
gpio-keys {
    compatible = "gpio-keys";
    status = "okay";

    button-reset {
        label = "reset-button";
        gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
        linux,code = <KEY_RESTART>;
        gpio-key,wakeup;
        interrupt-parent = <&intc>;
        interrupts = <0 67 IRQ_TYPE_EDGE_FALLING>;
    };
};

这里 interrupt-parent 指向中断控制器节点,interrupts 指定中断号和触发方式。IRQ_TYPE_EDGE_FALLING 表示下降沿触发,适合按键消抖。

3.4 知识结构图:硬件平台选型与资源映射

下面这张图总结了本章的核心知识点,从处理器选型到外设映射,再到中断管理,一目了然。

硬件平台选型与资源映射知识结构图 硬件平台选型与资源映射知识结构 ARM Cortex-A 处理器选型 i.MX6 系列 i.MX8 系列 AM335x 系列 STM32MP1 系列 外设接口映射 UART (ttyS0) SPI / I2C CAN (SocketCAN) Ethernet (eth0) GPIO 与中断控制器 (GIC) GPIO 映射与操作 中断控制器配置 核心原则:根据工控场景选择处理器,外设映射要关注电气特性和设备树配置 GPIO 和中断配置需考虑抗干扰和实时性要求

3.5 本章小结

硬件平台选型没有绝对的好坏,关键看项目需求。我个人总结了几条经验:

  • 追求稳定:选 i.MX6 或 AM335x,生态成熟,资料多。
  • 追求性能:选 i.MX8,适合边缘计算和视频处理。
  • 追求低功耗:选 STM32MP1,双核异构灵活。
  • 外设映射:设备树是核心,一定要仔细核对引脚复用。
  • GPIO 和中断:工控现场必须加隔离,中断触发方式要选对。