Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

4.3 中断方式实现 spi 驱动

SPI 驱动的中断实现原理

飞腾派(Phytium Pi)的 SPI 驱动中断实现基于 SPI 控制器(基址 0x2803A000),利用中断机制处理数据传输事件,优化高吞吐量场景下的性能。SPI 控制器支持主从模式、四种时序模式(CPOL/CPHA 组合)和中断模式,相较于轮询模式可减少 CPU 占用。中断事件包括发送 FIFO 阈值触发(SPITXFTLR)、接收 FIFO 阈值触发(SPIRXFTLR)、传输完成和错误(如溢出)。中断通过 SPIIMR(中断屏蔽寄存器,偏移 0x02C)使能,SPIISR(中断状态寄存器,偏移 0x030)反映状态,SPIDR(数据寄存器,偏移 0x060)用于数据读写。当发送或接收 FIFO 达到设定阈值,或传输完成时,控制器触发中断,信号通过 GIC(Generic Interrupt Controller)路由到 CPU。驱动在初始化时通过 FMioFuncGetIrqNum 获取 MIO 中断号,并注册中断处理程序(如 master_evt_handlers)。中断模式支持高效传输,适用于流数据设备(如 LCD 屏幕、AD 转换器),文档中提到测试模式(MISO/MOSI 短接)可用于验证。

飞腾派 SPI 驱动的中断设备

飞腾派的 SPI 控制器集成在 MIO(Multi-Function Input/Output)模块中,基址 0x2803A000,引脚通过 PAD(基址 0x32B30000)配置(如 MISO/MOSI/SCK/CS)。中断设备支持以下事件:

  • 发送 FIFO 阈值中断(SPIIMR bit[2]=TXEI):发送 FIFO 数据量低于 SPITXFTLR 阈值时触发。
  • 接收 FIFO 阈值中断(SPIIMR bit[4]=RXFI):接收 FIFO 数据量达到 SPIRXFTLR 阈值时触发。
  • 传输错误中断(SPIIMR bit[3]=TXOI, bit[5]=RXOI):发送或接收 FIFO 溢出/下溢。 中断号通过 FMioFuncGetIrqNum 获取(类似 UART IRQ 24),由 GIC(基址 0xFF84_1000)路由。SPICTRL0(偏移 0x000)配置模式和数据位宽,SPIEN(偏移 0x008)控制使能,SPIBAUDR(偏移 0x014)设置波特率(基于 100MHz 时钟)。中断处理程序在 master_evt_handlers 中注册,处理数据传输和错误恢复,SPIICR(偏移 0x048)用于清除中断状态。

飞腾派 SPI 驱动的中断时序图

SPI 中断处理时序以接收 FIFO 阈值中断(SPIISR bit[4]=1)为例,涉及 SPI 控制器(0x2803A000)、MIO(中断号)、GIC(0xFF84_1000)和 CPU 核心。当接收 FIFO 达到 SPIRXFTLR 阈值,控制器触发中断信号,发送到 MIO 和 GIC。GIC 检查使能(GICD_ISENABLER)、优先级(GICD_IPRIORITYR,如 0xA0)和目标(GICD_ITARGETSR,CPU 0),转发到 CPU 接口(GICC)。CPU 读取 GICC_IAR 获取中断 ID,调用注册的 master_evt_handlers 处理接收数据(从 SPIDR 读取),完成后写 SPIICR 清除中断,通知 GIC 结束(GICC_EOIR)。总延迟约 20~50 ns(100MHz 时钟)。

sequenceDiagram
    participant SPI as SPI 控制器 (0x2803A000)
    participant MIO as MIO (中断号)
    participant GIC as GIC (0xFF84_1000)
    participant CPU as E2000 CPU Core 0

    SPI->>SPI: 接收 FIFO 达阈值 (SPIISR bit[4]=1)
    SPI->>MIO: 触发中断信号
    MIO->>GIC: 发送 IRQ
    GIC->>GIC: Check GICD_ISENABLER (IRQ enabled)
    GIC->>GIC: Read GICD_IPRIORITYR (Priority 0xA0)
    GIC->>GIC: Read GICD_ITARGETSR (Target CPU 0)
    GIC->>CPU: Forward IRQ (GICC_IAR)
    CPU->>CPU: Handle interrupt (master_evt_handlers, read SPIDR)
    CPU->>SPI: Write SPIICR (clear interrupt)
    CPU->>GIC: Write GICC_EOIR (IRQ complete)
    GIC->>GIC: Update status