Android SPI DMA驱动开发与HAL联调 - 第1节

1.1 SPI 协议概述

SPI(Serial Peripheral Interface,串行外设接口)是一种由 Motorola 公司提出的全双工、同步、主从式串行通信总线。在嵌入式系统中,SPI 因其高速、简单、硬件开销低的特点,被广泛用于连接传感器、ADC/DAC、LCD 控制器、Flash 存储器、RF 模块等外设。

1.1.1 SPI 总线物理层与信号线

SPI 总线使用四根信号线实现主从设备之间的通信:

信号线 全称 方向(主→从) 功能描述
SCLK Serial Clock 主→从 由主设备产生的同步时钟,决定数据传输速率
MOSI Master Out Slave In 主→从 主设备发送数据至从设备的数据线
MISO Master In Slave Out 从→主 从设备发送数据至主设备的数据线
CS/SS Chip Select / Slave Select 主→从 片选信号,低电平有效,用于选中目标从设备
关键概念:SPI 是全双工协议——在每个时钟周期内,主设备通过 MOSI 发送一位数据,同时从设备通过 MISO 返回一位数据。这意味着 SPI 的每一次传输都同时完成发送和接收。

1.1.2 SPI 四种工作模式(CPOL & CPHA)

SPI 协议通过时钟极性(CPOL)和时钟相位(CPHA)的组合定义四种模式,决定了数据采样和切换的时序边界:

模式 CPOL CPHA 时钟空闲电平 数据采样边沿 典型应用
模式 0 0 0 低电平 上升沿采样 多数 SPI Flash、SD 卡
模式 1 0 1 低电平 下降沿采样 某些 ADC 器件
模式 2 1 0 高电平 下降沿采样 部分 LCD 控制器
模式 3 1 1 高电平 上升沿采样 某些 RF 模块
联调要点:在 Android 驱动开发中,SPI 设备树节点必须正确配置 spi-cpol 和 spi-cpha 属性。模式不匹配将导致数据错位或通信失败,这是联调中最常见的低级错误之一。
SPI 主从连接与数据流示意图 主设备 (SoC / AP) SPI 控制器 从设备 (外设) 传感器 / Flash SCLK MOSI MISO CS (片选) 全双工:每个时钟同时收发 1 bit

1.2 DMA 传输优势

DMA(Direct Memory Access,直接存储器访问)是一种允许外设与内存之间直接传输数据的硬件机制,无需 CPU 逐字节干预。在 SPI 驱动中引入 DMA,可以显著降低 CPU 占用率并提升吞吐量。

1.2.1 PIO 模式 vs DMA 模式对比

对比维度 PIO(Programmed I/O) DMA(Direct Memory Access)
CPU 参与度 每个字节/字都需要 CPU 读写 FIFO CPU 仅初始化传输,之后由 DMA 控制器接管
吞吐量 受限于 CPU 频率和中断响应延迟 接近总线带宽,适合高速外设
CPU 占用率 高(传输期间 CPU 被占用) 极低(CPU 可执行其他任务)
适用场景 小数据量(< 64 字节)、低频率 大数据块(≥ 256 字节)、高频率
实时性 受中断延迟影响 硬件级传输,延迟可预测
联调陷阱:在 Android 系统中,如果 SPI 传输使用 PIO 模式处理大块数据(如摄像头 RAW 数据或 LCD 帧缓冲),会导致 CPU 长时间处于忙等状态,引发系统卡顿、音频断流甚至 ANR(Application Not Responding)。DMA 是解决此类问题的关键手段。

1.2.2 DMA 传输的典型流程

  1. 配置阶段:CPU 设置 DMA 源地址、目的地址、传输宽度(8/16/32 位)、传输计数和触发源(SPI 的 DMA 请求信号)。
  2. 启动阶段:CPU 使能 DMA 通道,DMA 控制器进入等待触发状态。
  3. 传输阶段:SPI 外设发出 DMA 请求,DMA 控制器从内存读取数据写入 SPI 发送 FIFO,同时从 SPI 接收 FIFO 读取数据写入内存。整个过程无需 CPU 介入。
  4. 完成阶段:传输计数归零后,DMA 控制器产生完成中断,通知 CPU 数据已就绪。
DMA 传输架构与数据通路 CPU 初始化 & 处理 DMA 控制器 硬件搬运数据 内存 Buffer / 队列 SPI 外设 配置通道 读写数据 DMA 请求 / 应答 CPU 只需配置 DMA 通道和传输参数,数据搬运完全由 DMA 控制器硬件完成

1.3 Android 驱动架构简介

Android 基于 Linux 内核,其驱动架构在标准 Linux 驱动模型之上增加了 Android 特有的 HAL(Hardware Abstraction Layer)和 HIDL(HAL Interface Definition Language)层,以实现硬件抽象、权限隔离和框架兼容。

1.3.1 Android 驱动分层模型

层级 组件 运行空间 职责
应用层 App / Framework Java 空间 调用 Android API 访问硬件功能
框架层 System Server / Service Java 空间 管理硬件服务,如 SensorService
HAL 层 HAL Module / HIDL Server Native (C++) 封装内核驱动接口,提供稳定 ABI
内核层 Linux Kernel Driver 内核空间 直接操作硬件寄存器,实现 SPI/DMA
联调核心:SPI 驱动联调主要涉及内核层(SPI 控制器驱动、DMA 引擎驱动)和HAL 层(封装 SPI 传输接口、处理数据格式转换)。HAL 层是 Android 特有的关键环节,它决定了上层应用能否稳定访问 SPI 外设。

1.3.2 SPI 在 Android 内核中的驱动栈

  • SPI 核心层(spi.c):提供通用的 SPI 总线注册、设备匹配、消息队列管理。
  • SPI 控制器驱动:实现具体 SoC 的 SPI 控制器操作,如配置时钟、模式、FIFO、DMA 触发。
  • SPI 设备驱动:挂载在 SPI 总线上的具体外设驱动,如 spi-sensor.c、spi-flash.c。
  • DMA 引擎驱动:提供 dmaengine API,用于 SPI 控制器与内存之间的 DMA 传输。
Android SPI 驱动软件架构分层图 应用层 (App / Java Framework) HAL 层 (HIDL Server / .so) Linux Kernel 内核空间 SPI 核心层 SPI 控制器驱动 DMA 引擎驱动 SPI 设备驱动 (spi-sensor / spi-flash) 联调范围:SPI 控制器驱动 + DMA 引擎驱动 + SPI 设备驱动 + HAL 封装

1.4 联调目标与课程安排

1.4.1 联调核心目标

本课程围绕“SPI 协议 + DMA 传输 + Android 驱动”三条主线,旨在帮助学员掌握以下实战能力:

  • 目标一:理解 SPI 协议时序与模式配置,能够在设备树中正确描述 SPI 从设备。
  • 目标二:掌握 Linux DMA 引擎框架(dmaengine),实现 SPI 控制器驱动的 DMA 传输路径。
  • 目标三:编写 Android HAL 模块,封装 SPI 传输接口,实现内核与框架的解耦。
  • 目标四:完成从内核驱动到 HAL 层的全链路联调,使用逻辑分析仪和 trace 工具验证数据正确性。

1.4.2 课程章节总览

章节 主题 核心内容
第 1 章 课程导论 SPI 协议、DMA 优势、Android 驱动架构、联调目标
第 2-4 章 SPI 协议深入 时序分析、设备树配置、SPI 控制器驱动框架
第 5-7 章 DMA 传输技术 dmaengine API、SG 模式、环形缓冲区
第 8-10 章 Android HAL 开发 HIDL 接口定义、HAL 实现、权限管理
第 11-13 章 联调实战 环境搭建、调试技巧、性能优化、案例分析
学习建议:本课程采用“理论 + 代码 + 实验”三合一模式。建议学员在阅读每章正文后,同步在开发板上完成对应的驱动编译、加载和测试步骤,以加深对 SPI 和 DMA 硬件行为的理解。
课程知识图谱与联调主线 SPI 协议 时序 / 模式 / 设备树 DMA 传输 dmaengine / SG / 环形缓冲 Android HAL HIDL / 封装 / 权限 全链路联调实战 驱动 → HAL → 应用 → 验证 三大知识域在联调阶段交汇,形成完整的 SPI + DMA + Android 驱动解决方案