把大象放进冰箱,总共分三步:
下面是设备树的信息。
static const struct of_device_id dac_of_match[] = {
{.compatible = "fairchild,74hc595"},
{}
};
static struct spi_driver dac_driver = {
.driver = {
.name = "dac",
.of_match_table = dac_of_match,
},
.probe = dac_probe,
.remove = dac_remove,
//.id_table = dac_spi_ids,
};
对于SPI传输,功能无非就是写和读,在Linux内核的spi头文件中,对读写的接口函数进行了定义和说明
/**
* spi_write - SPI synchronous write
* @spi: device to which data will be written
* @buf: data buffer
* @len: data buffer size
* Context: can sleep
*
* This function writes the buffer @buf.
* Callable only from contexts that can sleep.
*
* Return: zero on success, else a negative error code.
*/
static inline int
spi_write(struct spi_device *spi, const void *buf, size_t len)//spi:写哪个设备
{
struct spi_transfer t = {
.tx_buf = buf,//需要写的数据内容
.len = len,//写数据的长度
};
return spi_sync_transfer(spi, &t, 1);//成功返回0,失败返回err code
}
函数最终返回时,调用了 spi_sync_transfer 函数。
所以大家关注的最终核心的函数是spi_sync,这是一个同步、阻塞的SPI传输函数,返回要么成功,要么失败。此外还有spi_async函数,对应的是异步的SPI传输函数,简单地说就是这个函数即刻返回,它返回后SPI传输不一定已经完成。
上面将函数读写的上下层调用关系简单说明,其中,有个重要的数据结构,就是 struct spi_message *message。spi_message中存放的transfer链表,是由多个spi_transfer结构体组成,链表通过上图中的spi_message_add_tail函数,将传输的buff放入链表尾部。
spi_message_add_tail函数:
所以spi_transfer是我们传输数据的最基本单位。
还有其他的函数实现,在这里简单罗列,读者可以根据内核源码自行查找,还包括:
/**
* spi_read - SPI synchronous read
* @spi: device from which data will be read
* @buf: data buffer
* @len: data buffer size
* Context: can sleep
*
* This function reads the buffer @buf.
* Callable only from contexts that can sleep.
*
* Return: zero on success, else a negative error code.
*/
static inline int
spi_read(struct spi_device *spi, void *buf, size_t len)//spi:读哪个设备
{
struct spi_transfer t = {
.rx_buf = buf,//读到的数据
.len = len,//数据长度
};
return spi_sync_transfer(spi, &t, 1);//成功返回0,失败返回err code
}
/* this copies txbuf and rxbuf data; for small transfers only! */
extern int spi_write_then_read(struct spi_device *spi,//读哪个设备
const void *txbuf, unsigned n_tx,//txbuf:发送buffer,n_tx:发送多少字节
void *rxbuf, unsigned n_rx);//rxbuf:接收buffer,n_tx:接收多少字节
/**
* spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read
* @spi: device with which data will be exchanged
* @cmd: command to be written before data is read back
* Context: can sleep
*
* Callable only from contexts that can sleep.
*
* Return: the (unsigned) eight bit number returned by the
* device, or else a negative error code.
*/
static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
{
ssize_t status;
u8 result;
status = spi_write_then_read(spi, &cmd, 1, &result, 1);
/* return negative errno or unsigned value */
return (status < 0) ? status : result; //返回值: 成功的话返回一个8位数据(unsigned), 负数表示失败码
}
/**
* spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read
* @spi: device with which data will be exchanged
* @cmd: command to be written before data is read back
* Context: can sleep
*
* The number is returned in wire-order, which is at least sometimes
* big-endian.
*
* Callable only from contexts that can sleep.
*
* Return: the (unsigned) sixteen bit number returned by the
* device, or else a negative error code.
*/
static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
{
ssize_t status;
u16 result;
status = spi_write_then_read(spi, &cmd, 1, &result, 2);
/* return negative errno or unsigned value */
return (status < 0) ? status : result;//返回值: 成功的话返回一个16位数据(unsigned, 被转换为本地字节序), 负数表示失败码
}