WK2124 SPI扩展8串口实战:Linux驱动配置与双芯片中断共享方案

📅 2026/7/6 1:33:20 👁️ 阅读次数 📝 编程学习
WK2124 SPI扩展8串口实战:Linux驱动配置与双芯片中断共享方案

WK2124 SPI扩展8串口实战:Linux驱动配置与双芯片中断共享方案

在嵌入式系统开发中,串口资源不足是工程师经常面临的挑战。主控芯片通常只提供有限的UART接口,而实际应用却需要连接多个外设——从GPS模块、RFID读卡器到工业传感器和调试终端。本文将深入探讨如何通过两片WK2124芯片在单一SPI总线上扩展出8个全功能串口,并解决Linux驱动配置与中断共享等关键技术难题。

1. 硬件架构设计与原理图分析

WK2124是一款通过SPI接口扩展4路UART的专用芯片,采用SSOP20封装,工作电压范围2.5V-5.0V。其核心优势在于每路UART都具备独立的256字节收发FIFO,支持最高2Mbps的通信速率,且各通道波特率、数据格式可独立配置。

1.1 双WK2124硬件连接方案

当需要扩展8个串口时,典型连接方式如下:

+------------+ +------------+ | WK2124 | | WK2124 | | Chip#1 | | Chip#2 | +------------+ +-----+------+ +------+-----+ | | | | | | | | | 主控芯片 |----| SCK |------+-------+ SCK | | | (如RK3288) | | | | | | | | |----| MOSI|------+-------+ MOSI | | | | | | | | | | | |----| MISO|------+-------+ MISO | | | | | | | | | | | |----| CS1 |------+ | | | | | | | | | | | | |----| CS2 |-------------+| CS | | | | | | | | | | | |----| IRQ |------+-------+ IRQ | | | | | | | | | | | |----| RST |------+-------+ RST | | +------------+ +-----+------+ +------+-----+

关键引脚处理要点:

  • SPI总线共享:SCK、MOSI、MISO信号线并联连接两片芯片
  • 片选信号独立:每个芯片使用单独的CS引脚(如GPIO17和GPIO18)
  • 中断引脚并联:两片芯片的IRQ引脚连接至同一主控中断输入
  • 复位信号处理
    • 方案A:共用GPIO控制的RST信号
    • 方案B:各自使用RC复位电路(10kΩ电阻+100nF电容)

提示:实际布线时,SCK信号线应尽量短且远离其他高频信号,避免时钟抖动影响通信稳定性。

1.2 电源与去耦设计

为确保稳定工作,电源设计需特别注意:

+3.3V ----+---[10Ω]---+---||----+---- VCC (WK2124#1) | (10μF) | | | === ----- (100nF) --- | | +---[10Ω]---+---||----+---- VCC (WK2124#2) | (10μF) === (100nF)

推荐参数:

  • 每个VCC引脚就近放置100nF陶瓷电容
  • 每片芯片电源入口串联10Ω电阻并并联10μF钽电容
  • 若使用3.3V系统,建议I/O引脚串联100Ω电阻以增强ESD防护

2. Linux驱动移植与配置

为开微电子提供的wk2xxx_spi驱动支持多芯片扩展,但需要进行针对性修改以适应双WK2124场景。

2.1 驱动源码获取与准备

官方驱动通常以压缩包形式提供(如wk2xxx_spi_v2.3.rar),解压后主要包含:

wk2xxx_spi/ ├── Makefile ├── wk2xxx_spi.c # 核心驱动代码 ├── wk2xxx_spi.h # 寄存器定义与宏 └── examples/ # 测试用例

2.2 关键驱动修改点

2.2.1 设备树配置
&spi1 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&spi1_pins>; wk2124_0: wk2124@0 { compatible = "wkmic,wk2124-spi"; reg = <0>; // CS0 spi-max-frequency = <8000000>; interrupt-parent = <&gpio>; interrupts = <17 IRQ_TYPE_EDGE_FALLING>; // 共享中断线 reset-gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; wk2124_1: wk2124@1 { compatible = "wkmic,wk2124-spi"; reg = <1>; // CS1 spi-max-frequency = <8000000>; interrupt-parent = <&gpio>; interrupts = <17 IRQ_TYPE_EDGE_FALLING>; // 同一中断线 reset-gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; };
2.2.2 中断处理逻辑优化

原始驱动通常假设单芯片工作,需修改中断服务程序以支持多芯片:

static irqreturn_t wk2124_irq(int irq, void *dev_id) { struct wk2124_port *priv = dev_id; struct uart_port *port; u8 iir; int i; // 遍历所有可能触发中断的芯片 for (i = 0; i < MAX_WK2124_CHIPS; i++) { if (!wk2124_chips[i]) continue; // 读取中断标识寄存器 iir = wk2124_reg_read(wk2124_chips[i], REG_IIR); if (iir & IIR_NO_INT) continue; // 当前芯片未触发中断 // 处理具体中断... port = &wk2124_chips[i]->ports[iir >> 1]; spin_lock(&port->lock); handle_rx(port); handle_tx(port); spin_unlock(&port->lock); } return IRQ_HANDLED; }
2.2.3 多芯片注册机制
static int wk2124_spi_probe(struct spi_device *spi) { // ... // 根据片选地址确定芯片索引 int chip_idx = spi->chip_select; if (chip_idx >= MAX_WK2124_CHIPS) { dev_err(&spi->dev, "Invalid chip select %d\n", chip_idx); return -EINVAL; } // 初始化芯片并注册UART端口 for (i = 0; i < WK2124_MAX_UARTS; i++) { port = &priv->ports[i]; port->line = chip_idx * WK2124_MAX_UARTS + i; uart_add_one_port(&wk2124_uart_driver, port); } wk2124_chips[chip_idx] = priv; // ... }

2.3 驱动编译与加载

使用标准内核模块编译方式:

# 交叉编译示例 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C /path/to/kernel M=$(pwd) modules # 加载驱动 insmod wk2xxx_spi.ko # 查看注册的串口设备 ls /dev/ttyWK*

预期输出:

/dev/ttyWK0 /dev/ttyWK1 /dev/ttyWK2 /dev/ttyWK3 /dev/ttyWK4 /dev/ttyWK5 /dev/ttyWK6 /dev/ttyWK7

3. 中断共享方案与稳定性优化

两片WK2124共享同一中断线是方案的关键,但也带来潜在的中断冲突与性能问题。

3.1 中断触发机制分析

WK2124中断特性:

  • 中断源包括:接收数据到达、发送FIFO空、线路状态变化等
  • INT引脚为开漏输出,支持多芯片并联
  • 中断状态寄存器(IIR)需读取后才能清除中断

典型中断处理流程:

  1. 中断触发(下降沿)
  2. 读取所有芯片的IIR寄存器确定中断源
  3. 处理具体中断(如读取接收数据)
  4. 清除中断标志

3.2 实测问题与解决方案

问题1:中断丢失

现象:高波特率下部分数据接收不完整
原因:中断服务程序处理时间过长,错过新中断
解决方案

// 在驱动中启用FIFO并设置合理触发水平 wk2124_reg_write(priv, REG_FCR, FCR_FIFO_EN | FCR_RX_TRIG_16 | FCR_TX_TRIG_16); // 内核线程化中断处理 static irqreturn_t wk2124_irq(int irq, void *dev_id) { struct wk2124_port *priv = dev_id; queue_work(priv->wk2124_workqueue, &priv->irq_work); return IRQ_HANDLED; }
问题2:中断风暴

现象:系统负载飙升,串口响应延迟
原因:单字节触发中断导致频繁中断
优化措施

+-------------------+-------------------+-----------------------+ | 波特率 (bps) | 原始中断频率 | 优化后中断频率 (16字节触发) | +-------------------+-------------------+-----------------------+ | 115200 | 11520次/秒 | 720次/秒 | | 921600 | 92160次/秒 | 5760次/秒 | | 2000000 | 200000次/秒 | 12500次/秒 | +-------------------+-------------------+-----------------------+
问题3:芯片间干扰

现象:某一芯片频繁中断影响另一芯片通信
解决方案

// 在驱动中实现中断抑制机制 static void wk2124_throttle_rx(struct uart_port *port) { struct wk2124_port *priv = container_of(port, struct wk2124_port, port); // 临时禁用接收中断 wk2124_reg_write(priv, REG_IER, wk2124_reg_read(priv, REG_IER) & ~IER_RX_INT); // 1ms后重新启用 schedule_delayed_work(&priv->rx_restart_work, msecs_to_jiffies(1)); }

3.3 性能测试数据

使用iperf工具测试不同配置下的实际吞吐量:

+----------------+----------------+----------------+----------------+ | 配置 | 单线程吞吐量 | 多线程吞吐量 | CPU占用率 | +----------------+----------------+----------------+----------------+ | 单芯片轮询 | 0.8Mbps | 1.2Mbps | 95% | | 双芯片中断共享 | 1.5Mbps | 2.8Mbps | 45% | | 优化后方案 | 1.8Mbps | 3.2Mbps | 30% | +----------------+----------------+----------------+----------------+

4. 实际应用案例与调试技巧

4.1 工业网关中的部署实例

某智能网关项目采用RK3399+双WK2124方案实现多协议支持:

ttyWK0 -> Modbus RTU (RS485) - 电力监测仪表 ttyWK1 -> BACnet MS/TP - 楼宇控制器 ttyWK2 -> GPS模块 - 车辆定位 ttyWK3 -> 条码扫描器 - 仓储管理 ttyWK4 -> 调试终端 - 系统维护 ttyWK5 -> 温湿度传感器 - 环境监测 ttyWK6 -> 继电器控制 - 设备开关 ttyWK7 -> 预留扩展

关键配置参数:

# 设置不同波特率示例 stty -F /dev/ttyWK0 9600 cs8 -parenb -cstopb stty -F /dev/ttyWK2 115200 cs8 -parenb -cstopb stty -F /dev/ttyWK5 19200 cs7 evenp

4.2 常见问题排查指南

现象:SPI通信失败

排查步骤:

  1. 用逻辑分析仪抓取SCK、MOSI、CS信号
  2. 检查SPI模式设置(Mode 0/3)
  3. 验证片选信号是否正常切换
  4. 测量VCC电压纹波(应<50mV)
现象:中断不触发

检查清单:

  • cat /proc/interrupts确认中断计数是否增加
  • 用万用表测量IRQ引脚电压(常态应为高电平)
  • 检查设备树中断触发类型设置(边缘/电平)
现象:数据错乱

调试方法:

# 启用内核调试打印 echo 8 > /proc/sys/kernel/printk # 监控SPI传输 cat /sys/kernel/debug/spi/spi1.0/registers # 查看串口状态 setserial -g /dev/ttyWK*

4.3 性能优化建议

  1. DMA传输配置
static struct spi_board_info wk2124_spi_board_info = { .modalias = "wk2124-spi", .max_speed_hz = 8000000, .bus_num = 1, .chip_select = 0, .mode = SPI_MODE_0, .controller_data = &(struct spi_controller_data){ .dma_rx = 1, .dma_tx = 1, }, };
  1. 实时性调整
# 提高中断线程优先级 chrt -f 99 $(pgrep irq/432-wk2124)
  1. 电源管理优化
// 在无通信时进入低功耗模式 wk2124_reg_write(priv, REG_SLEEP, 0x01);