凡亿助教-小云
凡事用心,一起进步
打开APP
公司名片
凡亿课堂 | 面试指南
当前位置: 首页 面试指南
Linux SPI驱动怎么写?spi_driver和probe怎么填?用户态怎么访问?嵌入式Linux面试
浏览量:213
2026-10-07 20:47:00
一句话答案

SPI 驱动用 spi_driver 结构体注册,of_match_table 匹配设备树;probe 里初始化硬件、创建字符设备或用 spidev;收发用 spi_sync/spi_write/spi_read(同步)或 spi_async(异步),spi_transfer 描述每段传输;用户态通过 /dev/spidevX.Y 用 ioctl 读写,或驱动创建 sysfs/cdev。

本文概述

SPI 驱动是 Linux 常见驱动类型,面试常考:spi_driver、probe、spi_sync、spidev。回答要给驱动框架和收发函数。

核心要点

  • spi_driver 注册:driver.name、probe、remove、of_match_table(设备树匹配)

  • probe:spi_setup 设置模式/速率/位宽,初始化硬件,注册 cdev/sysfs

  • 收发:spi_sync(同步阻塞)、spi_async(异步回调)、spi_write/spi_read(简单封装)

  • spi_transfer:tx_buf/rx_buf、len、speed_hz、bits_per_word、cs_change

  • 用户态:/dev/spidevX.Y(spidev 驱动,ioctl SPI_IOC_MESSAGE)或驱动自建 cdev/sysfs

终端显示 Linux SPI 驱动代码,spi_driver、probe、spidev,示波器测量 SPI 波形

面试官:写一个 SPI 设备驱动的基本结构?spi_sync 怎么用?

面试官考察点

Linux 驱动基础题。面试官看你是否写过 SPI 驱动。重点听:spi_driver、probe、spi_transfer。

回答思路

给 spi_driver 结构、probe 流程、收发函数、用户态访问。

参考回答

spi_driver 结构。

static const struct of_device_id my_spi_of_match[] = {
  { .compatible = "vendor,myspichip" },
  { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, my_spi_of_match);

static struct spi_driver my_spi_driver = {
  .driver = {
    .name = "my_spi_chip",
    .of_match_table = my_spi_of_match,
  },
  .probe = my_spi_probe,
  .remove = my_spi_remove,
};
module_spi_driver(my_spi_driver);

probe 函数流程。

  1. 设置 SPI 模式:spi->mode = SPI_MODE_0(CPOL=0,CPHA=0);

  2. 设置最大速率:spi->max_speed_hz = 10000000(10MHz);

  3. 设置位宽:spi->bits_per_word = 8;

  4. 调用 spi_setup(spi) 生效;

  5. 读设备 ID 确认硬件存在;

  6. 分配私有数据,注册字符设备或 sysfs;

  7. spi_set_drvdata(spi, data) 保存。

static int my_spi_probe(struct spi_device *spi){
  struct my_data *data;
  spi->mode = SPI_MODE_0;
  spi->max_speed_hz = 10000000;
  spi->bits_per_word = 8;
  spi_setup(spi);
  data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
  data->spi = spi;
  spi_set_drvdata(spi, data);
  // 注册 cdev/sysfs
  return 0;
}

SPI 收发函数。

函数用途
spi_write(spi, buf, len)只写(半双工,MOSI)
spi_read(spi, buf, len)只读(发 dummy 字节,读 MISO)
spi_sync(spi, &msg)通用同步传输,支持多 transfer
spi_async(spi, &msg, callback)异步传输,完成后回调
spi_write_then_read(spi, tx, txlen, rx, rxlen)先写后读(常用,读寄存器)

// 读寄存器 reg:先发 reg 地址,再读数据
u8 tx[2] = {reg | 0x80, 0}; // 读标志位
u8 rx[2];
struct spi_transfer t = {
  .tx_buf = tx, .rx_buf = rx,
  .len = 2, .speed_hz = 10000000,
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
// rx[1] 是读到的数据

用户态访问。

  • spidev:内核配置 CONFIG_SPI_SPIDEV,设备树里 compatible="spidev",生成 /dev/spidevX.Y;用户态 open + ioctl(SPI_IOC_MESSAGE) 收发;

  • 自建字符设备:驱动注册 cdev,用户态 read/write/ioctl,适合复杂协议;

  • sysfs:驱动在 /sys/bus/spi/devices/ 下创建属性,cat/echo 读写,适合简单配置;

  • spidev_test:内核工具 tools/spi/spidev_test.c,测试 SPI 通信。

注意。

  • SPI 是全双工,spi_sync 收发同时进行,tx_buf 和 rx_buf 可以不同;

  • 多设备共享总线时,CS 由内核管理(spi_transfer.cs_change);

  • SPI 没有 ACK,出错不重传,靠校验或重试;

  • 高速 SPI(>10MHz)注意 PCB 走线和信号完整性,可能需要用 DMA。

面试官可能追问

追问 1:spi_sync 和 spi_async 区别?
spi_sync 同步阻塞,调用后等待传输完成,简单常用;spi_async 异步,提交后立即返回,传输完成后调用回调,适合高并发或不允许阻塞的场景(如中断上下文不能用同步)。
追问 2:SPI 模式 0~3 怎么选?
看器件手册。Mode0(CPOL=0,CPHA=0)最常用,空闲低电平、上升沿采样;Mode3(CPOL=1,CPHA=1)也常用,空闲高电平、上升沿采样。Mode0 和 Mode3 都是上升沿采样,只是空闲电平不同。
追问 3:spidev 和自建驱动怎么选?
简单设备、调试、用户态协议用 spidev(不用写内核驱动);复杂设备(如传感器连续采样、需要中断、性能要求高)写专用驱动。spidev 适合快速验证和通用 SPI 设备。
追问 4:SPI 和 I2C 驱动框架区别?
结构类似(spi_driver vs i2c_driver,spi_device vs i2c_client),但 SPI 收发用 spi_message/spi_transfer(支持多段、全双工),I2C 用 i2c_transfer/i2c_smbus_*。SPI 没有地址(CS 选设备),I2C 有 7 位地址。
追问 5:SPI 传输中 cs_change 作用?
cs_change=1 表示这段 transfer 结束后 CS 不释放(保持选中),下一段继续传输。用于需要连续多段传输但不释放 CS 的场景(如写地址+读数据)。默认 cs_change=0,传输结束释放 CS。

常见失分表达

✗ probe 不调用 spi_setup — 模式/速率不生效,通信失败。
✗ SPI 只读不发 dummy — SPI 全双工,读必须同时发 dummy 字节提供时钟。
✗ 高速 SPI 不考虑信号完整性 — 信号反射、串扰,数据错误。

准备动作

1
写过一个简单 SPI 驱动(传感器/Flash)
2
了解 spi_sync 和 spi_transfer
3
用过 spidev 或 spidev_test 调试

核心关键词

Linux SPI驱动spi_driverspi_syncspi_transferspidevprobeSPI_MODE0


声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。仅供学习交流使用,不构成商业目的。版权归原作者所有,如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时删除。 侵权投诉

相关文章

负压电源怎么产生?电荷泵与反压电路怎么选?电源工程师面试

2026-09-03 13:53:06

Linux文件权限755、644怎么理解?脚本报Permission denied怎么排查?

2026-10-31 15:43:20

嵌入式Linux面试:DMA传完数据CPU却读到旧值?Cache一致性要这样排

2026-10-17 15:37:27

PCB差分对走线设计要点与等长绕线方法 - PCB设计面试题详解

2026-08-18 21:06:22

FPGA时序约束怎么写?create_clock、set_input_delay、setup/hold怎么分析?FPGA面试

2026-10-07 10:02:54