Beaglebone black的spi模块问题

问题描述 投票:1回答:1

我有以下怪异问题。我已经设置了BBB来激活spi1模块。该模块连接到F-RAM芯片(FM25CL64B)。我已经完成了所有必要的配置。存在/dev/spidev1.0,我打开/dev/spidev1.0并通过SPI_IOC_MESSAGE宏命令使用ioctl,编写了一个写入和读取芯片的小程序。

使用该程序,我成功地将32个字节的文本写入F-RAM芯片。阅读似乎也很成功……我怎么知道他们俩都成功了?我使用了一个激活了SPI解码器的逻辑分析仪,以实际查看所有这四个SPI线路的情况。监视所有SPI线,我可以看到写入和读取操作会以正确的时序生成正确的信号,并且所有信号都是同步的。 CS在事务期间启用芯片,CLK以8位字(配置)为每个字节提供时钟,数据线显示正确的值,这要归功于SPI解码器,该解码器在每个8位上方显示字节值。 MOSI和MISO线的位信号序列。

问题是,即使我看到在读取操作期间通过MISO线发送了正确的信息,我提供给ioctl的缓冲区(iSPIR,SPI_IOC_MESSAGE(2),xfer)也填充了零。

我有意用其他值初始化了该缓冲区,因此我可以查看ioctl是否将其写入其中。确实如此。零。

现在,我可以看到在读取操作期间通过MISO线发送的所有字节的事实,证明了写入操作不仅在分析器中看起来正确,而且实际上在先前的写入操作期间写入了预期的数据。

我多次检查dts文件中的MISO行是否配置正确(我可以根据需要重建并重新安装)。我检查了它是否是正确的引脚,以及是否已将其配置为输入。一切似乎都已正确配置。

如果存在权限问题,我将以超级用户身份运行该程序-没什么区别。

我还以GPIO模式实现了spi通信。即禁用了spi模块,所有线路均配置为GPIO。 CE,CLK,MOSI配置为otuputs,MISO配置为输入。这样,我可以在软件中实现整个通信,因此可以完全控制线路。这样做,这次,我能够用F-RAM芯片中的正确数据成功填充缓冲区。即从F-RAM芯片一直到用户空间缓冲区,顺序读取操作都很好。我能够将数据打印到控制台中。但是,这种方法太慢了。另外,当有可用模块使用时,我发现仅使用SPI com的纯软件实现效率低下。

为了编写示例程序,我使用了在线提供的spi_test.c开源示例。我还构建并运行了spi_test.c本身,未做任何修改,结果相同。

这里是我的程序清单(相关片段):

// SPI config ...

int InitSPIReadMode(const char* pstrDeviceF)
{
        int file;
        __u8  wr_mode = SPI_MODE_0, rd_mode = SPI_MODE_0, lsb = 0, bits = 8;
        __u32 speed = CLOCK_FREQ_HZ; // 500kHz

        if((file = open(pstrDeviceF, O_RDWR)) < 0)
        {
                printf("Failed to open the bus.");
                /* ERROR HANDLING; you can check errno to see what went wrong */
                exit(1);
        }
        if(ioctl(file, SPI_IOC_RD_MODE, &rd_mode) < 0)
        {
                printf("SPI rd_mode\n");
                return -1;
        }
        if(ioctl(file, SPI_IOC_RD_LSB_FIRST, &lsb) < 0)
        {
                printf("SPI rd_lsb_fist\n");
                return -1;
        }
        if(ioctl(file, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0)
        {
                printf("SPI bits_per_word\n");
                return -1;
        }
        if(ioctl(file, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
        {
                printf("SPI max_speed_hz\n");
                return -1;
        }
        printf("%s: spi wr-mode=%d, spi rd-mode=%d, %d bits per word, %s, %d Hz max\n", pstrDeviceF, wr_mode, rd_mode, bits, lsb ? "(lsb first) " : "(msb first)", speed);

        xfer[0].cs_change = 0; /* Keep CS activated */
        xfer[0].delay_usecs = 0; //delay in us
        xfer[0].speed_hz = CLOCK_FREQ_HZ; //speed
        xfer[0].bits_per_word = 8; // bites per word 8

        xfer[1].cs_change = 0; /* Keep CS activated */
        xfer[1].delay_usecs = 0;
        xfer[1].speed_hz = CLOCK_FREQ_HZ;
        xfer[1].bits_per_word = 8;

        return file;
}

在主要功能中:(因为逻辑分析仪显示此代码正确发送了命令,地址并随后为32个字节的数据提供时钟)


                int iSPIR = InitSPIReadMode("/dev/spidev1.0"); //open("/dev/spidev1.0", O_RDWR | O_SYNC);

                char arrInstruct[3] = { OPCO_READ, 0x00, 0x00 };
                char arrFRamData[512];

                for(int pos = 0; pos < 512; pos++) arrFRamData[pos] = pos;

                xfer[0].tx_buf = (unsigned long)arrInstruct;
                xfer[0].len = 3;

                xfer[1].rx_buf = (unsigned long)arrFRamData;
                xfer[1].len = 32;

                if(ioctl(iSPIR, SPI_IOC_MESSAGE(2), xfer) < 0) printf("ioctl write error %s.\n", strerror(errno));

// hex dumping of the arrFRamData buffer.

xfer是一个全局变量,定义为:

struct spi_ioc_transfer xfer[2];

非常感谢! :)

c linux-kernel embedded beagleboneblack spi
1个回答
1
投票

我发现我的设置出现了问题。但是,即使整个事情现在都可以解决,但我应用的解决方案提出的问题多于答案。

所以我在beaglebone Wiki上的一篇文章(https://elinux.org/BeagleBone_Black_Enable_SPIDEV)中找到了此解决方案。

我注意到,在设备树覆盖中,他们将CLK设置为输入。阅读整篇文章并没有发现为什么必须将BBB侧的CLOCK作为输入。即使它是主文件...本文仅说明了如何构建和安装新的DTBO以激活SPI1模块。

因此,即使对我来说没有任何意义,但尝试将DTBO文件格式输出中的CLK行更改为输入以查看会发生什么,我也不会受到任何伤害……而且有效! :O

现在,为什么如此设置如此奇怪? BBB应该是SPI主设备,因此其时钟线应该是Output,以驱动此同步通信。这意味着FM25CL64B芯片必须充当SPI从设备。我只是检查了数据手册,是的,芯片侧的CLK是输入。因此,BBB上的CLK必须是输出。这就是我在BBB上配置CLK引脚的方式。作为输出。而且它没有用。

这就是为什么我如此困惑。即使CLK线的两端都是输入,它也可以工作吗?查看逻辑分析仪的输出,可以清楚地看到CLK线正在正确驱动。但是,如果主机和从机都在该线路上有输入,那么应该不会产生任何脉冲吗?那条线没有其他连接。...

© www.soinside.com 2019 - 2024. All rights reserved.