为什么ioctl返回“坏地址"? [英] why does ioctl return "bad address"

查看:918
本文介绍了为什么ioctl返回“坏地址"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用下面的代码从嵌入式板的SPI端口输出数据(olimex imx233-micro-这不是板特定的问题).当我运行代码ioctl时,返回"错误的地址".我正在修改 http://twilight.ponies.cz/spi-test.c,这很好.有人可以告诉我我在做什么错吗?

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). When I run the code ioctl return "bad address". I am modifying the code on http://twilight.ponies.cz/spi-test.c which works fine. 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

代码:

//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);
}

谢谢!

推荐答案

错误消息错误的地址"来自错误代码EFAULT,当您将地址传递给无效的虚拟地址的内核时会发生此错误消息在您进程的虚拟地址空间中. tr结构的地址显然是有效的,因此问题必须出在其成员之一.

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. The address to your tr structure is clearly valid, so the problem must be with one of its members.

根据struct spi_ioc_transfer 的定义中,.tx_buf.rx_buf成员必须是指向用户空间缓冲区的指针,或者为null.您要将.tx_buf设置为整数254,这不是有效的用户空间指针,因此这就是错误地址的出处.

According to the definition of struct spi_ioc_transfer, the .tx_buf and .rx_buf members must be pointers to userspace buffers, or 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.

我对这个IOCTL不熟悉,所以我最好的猜测是您需要对二进制数据进行低音处理.一种方法是:

I'm not familiar with this IOCTL, so my best guess is that you need to bass the data in binary. 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
    ...
};

如果您需要将其发送为ASCII,则应该使用诸如 snprintf(3) 将整数转换为ASCII字符串,然后将TX缓冲区指向该字符串并相应地设置长度.

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.

这篇关于为什么ioctl返回“坏地址"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆