SPI设备驱动程序
四线总线:
- 主输入从输出MISO
- 主输出从输入MOSI
- 串行时钟SCK
- 片选CS
SPI设备结构
struct spi_device {
struct spi_devicedev;
struct spi_master*master;
u32 max_speed_hz;
u8 chip_select;
u8 bits_per_word;
u16 mode;
int irq;
[...]
int cs_gpio;
}
- matser:设备所连接的SPI控制器
- max_speed_hz:该芯片使用的最大时钟频率
- chip_select:用于启用哪个芯片与主芯片通信,默认低电平有效
- mode:数据传输方式,默认最高位优先
spi模式
- CPOL
- 如果为0,初始时钟状态为低电平,第一个边沿是上升沿
- 如果为1,初始时钟状态为高电平,第一个边沿是下降沿
- CPHA
- 如果为0,表示在第一个边沿采样
- 如果为1,表示在第二个边沿采样
spi模式一共有四种:
mode0:CPOL=0,CPHA=0
mode1:CPOL=0,CPHA=1
mode2:CPOL=1,CPHA=0
mode3:CPOL=1,CPHA=1
spi_driver结构
struct spi_driver {
const struct spi_device_id *id_table;
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
void (*shutdown)(struct spi_device *spi);
struct device_driver driver;
};
步骤:
- 声明驱动程序支持的设备ID
- 调用MODULE_DEVICE_TABLE(spi,my_id_table),向SPI内核注册设备列表
- 编写probe函数和remove函数
- 声明并填充struct spi_driver结构
- 调用module_spi_driver函数,向内核注册驱动程序
SPI消息结构
struct spi_message {
struct list_head transfers;
struct spi_device *spi;
unsigned is_dma_mapped:1;
void (*complete)(void *context);
void *contect;
unsigned frame_length;
unsigned actual_length;
int status;
};
SPI消息传输
struct spi_transfer {
const void *tx_buf;
void *rx_buf;
unsigned len;
dma_addr_t tx_dma;
dma_addr_t rx_dma;
unsigned cs_change:1;
unsigned tx_nbits:1;
unsigned rx_nbits:1;
#define SPI_NBITS_SINGLE 0x01 //1bit传输
#define SPI_NBITS_DUAL 0x02 //2bit传输
#define SPI_NBITS_QUAD 0x04 //4bit传输
u8 bits_per_word;
u16 delay_usecs;
u32 speed_hz;
};