Why ioctl returns a "bad address",

I use the code below to output data from the SPI port of the onboard board (olimex imx233-micro is not a board issue). When I run the ioctl code, an " invalid address " is returned. I am changing the code to http://twilight.ponies.cz/spi-test.c , which works fine. Can someone tell me what I'm 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); } 

Thanks!

+5
source share
1 answer

The "Invalid Address" error message comes from the EFAULT error code that occurs when you pass an address to the kernel that is not a valid virtual address in the virtual address space of your process. The address of your tr structure is clearly valid, so the problem must be in one of its members.

According to the definition of struct spi_ioc_transfer , the .tx_buf and .rx_buf must be pointers to user space buffers or null. You set .tx_buf to the integer 254, which is not a valid pointer to user space, so the wrong address is coming from.

I am not familiar with this IOCTL, so I prefer that you need to process the data in binary. One way to do this would be as follows:

 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, you should use a function like snprintf(3) to convert the integer to an ASCII string, and then point the TX buffer to that string and set the length accordingly.

+12
source

All Articles