1. 课程导论:SPI协议基础回顾、中断与DMA基本概念、性能瓶颈分析
各位同学好,我是你们这期课程的主讲。在嵌入式领域摸爬滚打了十几年,SPI这个接口我打交道最多。说句实话,很多工程师能把SPI调通,但真正把它调好、调出极致性能的,不多。
这一章咱们先打好基础。别急着上代码,先把SPI协议、中断、DMA这些概念理清楚。我见过太多人,上来就撸代码,结果遇到性能问题根本不知道瓶颈在哪。
1.1 SPI协议基础回顾
SPI,全称Serial Peripheral Interface,摩托罗拉在80年代推出的。到现在还在广泛使用,说明它确实经典。
核心特点:
- 全双工:同一时刻可以收发数据
- 主从架构:一个Master,多个Slave
- 四线制:SCLK、MOSI、MISO、CS
- 同步通信:时钟由Master产生
我记得刚入行那会儿,有个项目用SPI驱动ADC芯片。板子画好了,结果死活读不到数据。查了两天,最后发现是CS引脚电平极性搞反了。嗯,这种低级错误,谁还没犯过呢?
SPI的四种模式
SPI有四种工作模式,由CPOL(时钟极性)和CPHA(时钟相位)决定:
| 模式 | CPOL | CPHA | 时钟空闲电平 | 数据采样边沿 |
|---|---|---|---|---|
| 模式0 | 0 | 0 | 低电平 | 上升沿 |
| 模式1 | 0 | 1 | 低电平 | 下降沿 |
| 模式2 | 1 | 0 | 高电平 | 上升沿 |
| 模式3 | 1 | 1 | 高电平 | 下降沿 |
SPI传输时序
一个典型的SPI传输过程是这样的:
- Master拉低CS,选中Slave
- Master产生SCLK时钟
- 每个时钟周期,Master通过MOSI发送1位,Slave通过MISO返回1位
- 传输完成,Master拉高CS
说白了,SPI就是一个移位寄存器。你发一个字节,同时就收到一个字节。这个特性很重要,后面讲DMA的时候还会用到。
1.2 中断与DMA基本概念
好,接下来咱们聊聊中断和DMA。这两个东西,是嵌入式系统里实现高效数据传输的核心机制。
中断(Interrupt)
中断,就是让CPU停下当前的工作,去处理一个紧急事件。处理完再回来继续干活。
中断处理流程:
- 外设产生中断信号
- CPU保存当前上下文(压栈)
- CPU跳转到中断向量表,找到对应的ISR
- 执行ISR
- 恢复上下文(出栈)
- 返回断点继续执行
这里有个关键点:中断是有开销的。每次中断,CPU都要压栈出栈。如果数据量小,中断没问题。但如果数据量大,比如一次传几K字节,每字节都中断一次,那CPU就啥也别干了。
DMA(Direct Memory Access)
DMA,直接存储器访问。它的作用就是让外设和内存之间直接传数据,不需要CPU插手。
我打个比方:
- 没有DMA:CPU像个快递员,每件货都要自己搬
- 有DMA:CPU是老板,DMA是搬运工。老板只需要下个指令,搬运工就把活干完了
DMA传输的关键要素:
- 源地址:数据从哪来(外设数据寄存器或内存)
- 目的地址:数据到哪去(内存或外设数据寄存器)
- 传输长度:传多少字节
- 触发源:什么事件启动DMA传输(比如SPI的RXNE标志)
我个人习惯,只要数据量超过16字节,就优先考虑DMA。中断?留给那些真正需要CPU快速响应的事件吧。
1.3 性能瓶颈分析
好了,基础概念讲完了。咱们来点实际的——SPI通信的性能瓶颈到底在哪?
先看一张图,这是SPI通信中数据流动的完整路径:
常见的性能瓶颈
瓶颈1:中断开销过大
这是最常见的问题。很多工程师图省事,SPI用中断模式,每收一个字节就进一次中断。你想想看,如果SPI时钟是10MHz,每秒要传1.25M字节。每次中断就算20个CPU周期,那也是25M周期/秒。CPU啥也别干了。
瓶颈2:DMA配置不合理
- 传输粒度:DMA一次传多少?传1字节和传256字节,效率差很多
- 缓存对齐:DMA缓冲区没对齐,会导致额外的内存访问
- 中断与DMA协同:DMA传输完成中断,如果处理不当,还是会拖慢系统
瓶颈3:SPI时钟速率受限
SPI能跑多快,不只看主控,还要看从设备。我遇到过从设备手册写支持20MHz,实际只能跑到12MHz。这种坑,只能靠实测来填。
性能调优的核心思路
说白了,SPI性能调优就三件事:
- 减少CPU干预:能用DMA就别用中断,能用中断就别用轮询
- 批量处理:把零散的小传输合并成大块传输
- 消除等待:让DMA和CPU并行工作,别让CPU空等DMA完成
后面的章节,我会带着大家一步步把这些思路落地。从最简单的轮询模式开始,逐步优化到中断模式、DMA模式,最后实现中断与DMA的协同调度。