SPI Linux驱动程序

打开街道

我正在尝试学习如何编写基本的SPI驱动程序,下面是我编写的探针函数。

我在这里尝试做的是为fram(datasheet设置spi设备,并使用spi_sync_transfer()api描述从芯片中获取制造商的ID。

当我执行此代码时,我可以使用逻辑分析仪在SPI总线上看到数据,但无法使用rx缓冲区读取数据。我在这里想念什么吗?有人可以帮我吗?

static int fram_probe(struct spi_device *spi)
{
    int err;
    unsigned char ch16[] = {0x9F,0x00,0x00,0x00};// 0x9F => 10011111
    unsigned char rx16[] = {0x00,0x00,0x00,0x00};

    printk("[FRAM DRIVER] fram_probe called \n");

    spi->max_speed_hz = 1000000;
    spi->bits_per_word = 8;
    spi->mode = (3);

    err = spi_setup(spi);
        if (err < 0) {
            printk("[FRAM DRIVER::fram_probe spi_setup failed!\n");
            return err;
        }
    printk("[FRAM DRIVER] spi_setup ok, cs: %d\n", spi->chip_select);
    spi_element[0].tx_buf = ch16;
    spi_element[1].rx_buf = rx16;

    err = spi_sync_transfer(spi, spi_element, ARRAY_SIZE(spi_element)/2);
    printk("rx16=%x %x %x %x\n",rx16[0],rx16[1],rx16[2],rx16[3]);

    if (err < 0) {
        printk("[FRAM DRIVER]::fram_probe spi_sync_transfer failed!\n");
        return err;
    }

    return 0;
}
特伦特

spi_element在此示例中未声明。您应该显示该内容以及数组中所有元素的填充方式。但是仅仅从那里的代码中,我看到了一些错误。

您需要设置的len参数spi_transfer您已将TX或RX缓冲区分配给ch16或未rx16设置缓冲区的长度。

您应将中未使用的所有字段清零spi_transfer

如果将长度设置为4,则不会根据数据表发送正确的命令。RDID期望一个字节命令,此后将跟随四个字节的输出数据。在第一次传输中编写了一个字节命令,然后读取了四个字节的数据。第一次传输中的tx_buf应该只是一个字节。

最后,指定为最后一个参数的传输次数spi_sync_transfer()不正确。在这种情况下,它应该是2,因为您已经定义了两个spi_element[0]spi_element[1]您可以使用ARRAY_SIZE()是否为此消息声明了spi_element,并且要发送数组中的所有传输。

将此视为更好地填写的方法spi_transfers它将负责将未使用的字段清零,以易于查看的方式定义传输,并在剩余代码中自动考虑更改缓冲区大小或传输数。

const char ch16[] = { 0x8f };
char rx16[4];
struct spi_transfer rdid[] = {
    { .tx_buf = ch16, .len = sizeof(ch16) },
    { .rx_buf = rx16, .len = sizeof(rx16) },
};
spi_transfer(spi, rdid, ARRAY_SIZE(rdid));

由于您拥有示波器,因此请务必检查此操作是否在单个芯片选择脉冲下发生我发现一个以上的Linux SPI驱动程序存在一个错误,该错误会在不应该选择的时候触发芯片选择。在某些情况下,从TX切换到RX(如上所述)会触发CS脉冲。在其他情况下,将为数据的每个字(此处为8位)生成CS脉冲。

您应该更改的另一件事是使用dev_info(&spi->dev, "device version %d", id)'dev_err()打印消息。这将以标准方式插入设备名称,而不是硬编码的非标准且不一致的“ [FRAME DRIVER] ::”文本。并根据需要设置消息的级别。

另外,请考虑在驱动程序中支持设备树以读取设备属性。然后,您可以执行诸如更改此设备的SPI总线频率之类的操作,而无需重建内核驱动程序。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章