简体   繁体   English

为什么ioctl会返回“糟糕的地址”

[英]why does ioctl return “bad address”

I use the the code below to output data from SPI port of an embedded board (olimex imx233-micro -- it is not a board specific question). 我使用下面的代码从嵌入式电路板的SPI端口输出数据(olimex imx233-micro - 它不是特定于电路板的问题)。 When I run the code ioctl return " bad address ". 当我运行代码ioctl返回“ 坏地址 ”。 I am modifying the code on http://twilight.ponies.cz/spi-test.c which works fine. 我正在修改http://twilight.ponies.cz/spi-test.c上的代码,工作正常。 Could anyone tell me what am I doing wrong? 谁能告诉我我做错了什么?

root@ubuntu:/home# gcc test.c -o test
test.c:20: warning: conflicting types for ‘msg_send’
test.c:16: note: previous implicit declaration of ‘msg_send’ was here
root@ubuntu:/home# ./test
errno:Bad address - cannot send SPI message
root@ubuntu:/home# uname -a
Linux ubuntu 3.7.1 #2 Sun Mar 17 03:49:39 CET 2013 armv5tejl GNU/Linux

Code: 码:

//test.c
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <errno.h>

static uint16_t delay;

int main(int argc,char *argv[]){
     msg_send(254); //the message that I want to send decimal "254"
     return 0;
}

void msg_send(int msg){
    int fd;
    int ret = 0;
    fd = open("/dev/spidev32766.1", O_RDWR); //ls /dev outputs spidev32766.1
    if(fd < 0){
        fprintf(stderr, "errno:%s - FD could be not opened\n ", strerror(errno));  
        exit(1);
        }

    struct spi_ioc_transfer tr = {
        .len = 1,
        .delay_usecs = delay,
        .speed_hz = 500000, //500 kHz
        .bits_per_word = 8,
        .tx_buf = msg,
        .rx_buf = 0, //half duplex
    };

    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret <1 ){
        fprintf(stderr, "errno:%s - cannot send SPI message\n ", strerror(errno));
    }
    close(fd);
}

Thank you! 谢谢!

The error message "Bad address" comes from the error code EFAULT , which happens when you pass an address to the kernel which is not a valid virtual address in your process's virtual address space. 错误消息“错误地址”来自错误代码EFAULT ,当您将地址传递给内核时会发生这种情况,该内核不是进程虚拟地址空间中的有效虚拟地址。 The address to your tr structure is clearly valid, so the problem must be with one of its members. tr结构的地址显然是有效的,因此问题必须与其中一个成员有关。

According to the definition of struct spi_ioc_transfer , the .tx_buf and .rx_buf members must be pointers to userspace buffers, or null. 根据struct spi_ioc_transfer定义.tx_buf.rx_buf成员必须是指向用户空间缓冲区的指针,或者为null。 You're setting .tx_buf to the integer 254, which is not a valid userspace pointer, so that's where the bad address is coming from. 您将.tx_buf设置为整数254,它不是有效的用户空间指针,因此这是坏地址的来源。

I'm not familiar with this IOCTL, so my best guess is that you need to bass the data in binary. 我不熟悉这个IOCTL,所以我最好的猜测是你需要用二进制来对数据进行低音。 One way to do that would be this: 一种方法是这样做:

struct spi_ioc_transfer tr = {
    .len = sizeof(msg),  // Length of rx and tx buffers
     ...
    .tx_buf = (u64)&msg, // Pointer to tx buffer
    ...
};

If you need to send it as ASCII instead, then you should use a function such as snprintf(3) to convert the integer to an ASCII string, and then point the TX buffer at that string and set the length accordingly. 如果您需要将其作为ASCII发送,那么您应该使用诸如snprintf(3)类的函数将整数转换为ASCII字符串,然后将TX缓冲区指向该字符串并相应地设置长度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM