在 SPI 传输函数中返回 -1 EINVAL 的 ioctl 错误
ioctl bug returning -1 EINVAL in SPI transfer function
不确定这是否与 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;
}
}
它 returns 正确(有效)。但是如果我像这样注释掉 2 个数组
//uint8_t arr[4] = {0x02, 0x03, 0x04, 0x05};
//uint8_t arrr[4] = {0x03, 0x04, 0x05, 0x06};
函数 returns false(无效),strace
输出包含:
ioctl(4, 0x40206b00, 0xbe899b80) = -1 EINVAL (Invalid argument)
这会导致我的代码出现问题,因为如果我对其他链接库甚至我自己的代码进行一些更改,就会导致此 SPI 传输函数停止工作。
这超出了我对 C/C++ 代码如何与 linux OS 交互的了解,因此非常感谢您的帮助。
已解决。 C/C++ 不保证 arrays/structs 的所有元素都被初始化为 0,如果你不将它们初始化为任何东西的话。使用 memset
和 memcpy
可能也不能保证这一点。因此 ioctl
调用返回错误,因为 package
结构在某些成员中包含不正确的值。
我必须像这样将 spi_ioc_transfer 结构 package
和 tempReadBuffer
初始化为零,以确保我没有遇到任何令人讨厌的意外:
spi_ioc_transfer package = {};
uint8_t tempReadBuffer[ bufferSize ] = {};
不确定这是否与 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;
}
}
它 returns 正确(有效)。但是如果我像这样注释掉 2 个数组
//uint8_t arr[4] = {0x02, 0x03, 0x04, 0x05};
//uint8_t arrr[4] = {0x03, 0x04, 0x05, 0x06};
函数 returns false(无效),strace
输出包含:
ioctl(4, 0x40206b00, 0xbe899b80) = -1 EINVAL (Invalid argument)
这会导致我的代码出现问题,因为如果我对其他链接库甚至我自己的代码进行一些更改,就会导致此 SPI 传输函数停止工作。
这超出了我对 C/C++ 代码如何与 linux OS 交互的了解,因此非常感谢您的帮助。
已解决。 C/C++ 不保证 arrays/structs 的所有元素都被初始化为 0,如果你不将它们初始化为任何东西的话。使用 memset
和 memcpy
可能也不能保证这一点。因此 ioctl
调用返回错误,因为 package
结构在某些成员中包含不正确的值。
我必须像这样将 spi_ioc_transfer 结构 package
和 tempReadBuffer
初始化为零,以确保我没有遇到任何令人讨厌的意外:
spi_ioc_transfer package = {};
uint8_t tempReadBuffer[ bufferSize ] = {};