【问题标题】:ioctl bug returning -1 EINVAL in SPI transfer function在 SPI 传输函数中返回 -1 EINVAL 的 ioctl 错误
【发布时间】:2019-11-19 03:26:06
【问题描述】:

不确定这是否与 C 相关或与 linux 内核有关。我正在为 Beaglebone 使用一个名为 BlackLib 的 SPI 库,它具有 SPI 传输功能。

由于某种原因,当我第一次尝试它时它不起作用。我玩了几天,当我在 function 本身中声明了两个随机数组时,它意外地工作了,即使它的效果为零。如果我删除它们,该函数会在 ioctl 行再次中断。

例如,如果我打电话:

uint8_t writeBuffer[2] = {0x00, 0x01};
uint8_t readBuffer[2] = {0,0};
transfer(writeBuffer, readBuffer, sizeof(readBuffer), 10, 0)

关于功能

bool   BlackSPI::transfer(uint8_t *writeBuffer, uint8_t *readBuffer, size_t bufferSize, uint16_t wait_us, uint16_t pad)
{  
    uint8_t tempReadBuffer[ bufferSize ];
    memset( tempReadBuffer, 0, bufferSize);

    spi_ioc_transfer package;

    package.tx_buf          = (unsigned long)writeBuffer;
    package.rx_buf          = (unsigned long)tempReadBuffer;
    package.len             = bufferSize;
    package.delay_usecs     = wait_us;
    package.speed_hz        = 5000000; //uint32_t
    package.bits_per_word   = 8; //uint8_t
    package.pad             = pad;

    // IF I DELETE THESE TWO DECLARATIONS, SPI transfer will fail. 
    // I have no idea why.. maybe causing a specific delay in the code that lets spi work, or overwriting old memory addresses that c++ attemps to access?
    uint8_t arr[4] = {0x02, 0x03, 0x04, 0x05};
    uint8_t arrr[4] = {0x03, 0x04, 0x05, 0x06};

    //ioctl call
    if( ::ioctl(this->spiFD, SPI_IOC_MESSAGE(1), &package) >= 0){
        memcpy(readBuffer, tempReadBuffer, bufferSize+pad);
        return true;
    } else {
        return false;
    }
}

它返回 true(有效)。但是如果我像这样注释掉 2 个数组

//uint8_t arr[4] = {0x02, 0x03, 0x04, 0x05};
//uint8_t arrr[4] = {0x03, 0x04, 0x05, 0x06};

函数返回 false(无效),strace 输出包含:

ioctl(4, 0x40206b00, 0xbe899b80)        = -1 EINVAL (Invalid argument)

这会导致我的代码出现问题,因为如果我对其他链接库甚至我自己的代码进行一些更改,它会导致此 SPI 传输函数停止工作。

这超出了我对 C/C++ 代码如何与 linux 操作系统交互的了解,因此感谢任何帮助。

【问题讨论】:

  • 您描述的症状是未定义行为的典型结果。这可能是由许多事情引起的,例如内存损坏、使用未初始化的变量等。在这种情况下,除非提供minimal reproducible example,否则我们不太可能发现问题 - 根本原因甚至可能不在代码 sn 中-p 你已经显示了。
  • 比如我们不知道bufferSize的值是多少。它可能太大以至于堆栈溢出。这只是一个示例,说明通常无法诊断不完整代码的问题。
  • @kaylum 我已经为函数添加了一个示例调用。我也愿意尝试调试建议。
  • @AlexF 嗨,对不起,伙计,我已经更正了。
  • 这仍然不是一个最小的可重现示例。请阅读链接以了解那是什么。您可能认为这并不重要,但正如我所解释的,问题可能不在您认为的地方,提供选择性的 sn-ps 代码是不够的,可能只会浪费人们的时间。您需要提供重现问题的完整代码。理想情况下,其他人可以编译的代码,但即使不是,也必须是您编译并重现问题的完整代码。

标签: c++ c linux spi ioctl


【解决方案1】:

解决了。如果您不将数组/结构的所有元素初始化为任何内容,C/C++ 不保证将它们初始化为 0。使用 memsetmemcpy 也可能无法保证这一点。因此,ioctl 调用返回错误,因为 package 结构在某些成员中包含不正确的值。

我必须像这样将 spi_ioc_transfer struct packagetempReadBuffer 初始化为零,以确保我没有遇到任何令人讨厌的意外:

spi_ioc_transfer package = {};
uint8_t tempReadBuffer[ bufferSize ] = {};

【讨论】:

    猜你喜欢
    • 2017-02-05
    • 2016-08-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2013-01-10
    相关资源
    最近更新 更多