Still struggling with Xilinx GPIO...
Guillaume Dargaud
dargaud at lpsc.in2p3.fr
Tue May 27 01:43:38 EST 2008
I still haven't managed to figure out how to use the Xilinx GPIO from
usermode.
The program gpio_test found at
http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/archive/2004/05/msg00004.html
and slightly modified as this:
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#include <xgpio_ioctl.h>
#define GPIO_DEV "/dev/xgpio"
void usage(int argc, char *argv[])
{
fprintf(stderr,"usage: %s hexval\n\n", argv[0]);
fprintf(stderr,"\n");
fprintf(stderr,"Puts the input hexval onto the LEDs, and\n");
fprintf(stderr,"displays the current value on the DIP switches\n");
fprintf(stderr,"\n");
fprintf(stderr,"try gpio_test FC\n\n");
}
void dump_dipsw(int val)
{
int i;
val = (val & 0x000000FF);
printf("DIP SW: ");
for(i=0;i<8;i++)
{
printf("%i",val & 0x01);
val >>= 1;
}
printf("\n");
}
/* Turn 4 LSB of X into 8 bit LED segment code */
unsigned char nyb_hex2led(int x)
{
unsigned char led_tab[] = {
0xFC, 0x60, 0xDA, 0xF2,
0x66, 0xB6, 0xBE, 0xE0,
0xFE, 0xF6, 0xEE, 0x3E,
0x9C, 0x7A, 0x9E, 0x8E};
return led_tab[x & 0xF];
}
/* Turn 8 LSB of x into 2 times 8 bit LED segment codes */
unsigned short hex2led(int x)
{
return (nyb_hex2led(x & 0xF) << 8) | (nyb_hex2led((x >> 4) & 0xF));
}
int main(int argc, char *argv[])
{
/* Open the device */
int fd = open(GPIO_DEV, O_RDWR);
struct xgpio_ioctl_data gpio_ioctl;
// struct ibm_gpio_ioctl_data gpio_ioctl;
// int result;
// int command;
if(fd==-1) {
fprintf(stderr,"Unable to open %s\n", GPIO_DEV);
return -1;
}
/*
if(argc!=2)
{
usage();
exit(1);
}
*/
gpio_ioctl.chan=0;
/* Set the tristates */
gpio_ioctl.mask=0x000000FF;
ioctl(fd, XGPIO_TRISTATE,(void *)&gpio_ioctl);
/* Get output data from command line if provided */
if(argc==2)
sscanf(argv[1],"%x",&(gpio_ioctl.data));
else
gpio_ioctl.data=time(NULL);
/* Convert binary (16 LSB) into LED segment codes and shift into
position on gpio */
gpio_ioctl.data=hex2led(gpio_ioctl.data & 0xFF)<<8;
ioctl(fd, XGPIO_OUT,(void *)&gpio_ioctl);
/* Read some data */
ioctl(fd, XGPIO_IN,(void *)&gpio_ioctl);
dump_dipsw(gpio_ioctl.data);
return 0;
}
...crashes in flames when run:
# gpio_test FC
[ 1366.864955] Oops: kernel access of bad area, sig: 11 [#5]
[ 1366.867560] NIP: c0108d50 LR: c00e68c4 CTR: 00000000
[ 1366.867560] REGS: c752fde0 TRAP: 0300 Tainted: G D (2.6.25-rc9)
[ 1366.867560] MSR: 00029030 <EE,ME,IR,DR> CR: 93000033 XER: e000007f
[ 1366.867560] DEAR: c8fffffc, ESR: 00000000
[ 1366.867560] TASK = c7c37030[202] 'gpio_test' THREAD: c752e000
[ 1366.867560] GPR00: 00000000 c752fe90 c7c37030 c8fffffc 00000056 0000000c
c752feb0 00000000
[ 1366.867560] GPR08: 00000000 11111111 ffffffe7 c7c5866c 00000000 10018dec
ffff8432 ffdf1d0f
[ 1366.867560] GPR16: ffffffff ffffffff ffffffff ffffffff ffffffff 00000000
100af244 10000858
[ 1366.867560] GPR24: 10000c00 00000002 10000478 800c5a03 c7c58000 c7c5866c
800c5a03 c0200000
[ 1366.867560] NIP [c0108d50] XIo_In32+0x4/0xc
[ 1366.867560] LR [c00e68c4] XGpio_GetDataDirection+0x84/0xac
[ 1366.867560] Call Trace:
[ 1366.867560] [c752fe90] [c00e66a8] xgpio_getinst+0x48/0xb0 (unreliable)
[ 1366.867560] [c752fea0] [c00e6a8c] xgpio_ioctl+0x1a0/0x1fc
[ 1366.867560] [c752fed0] [c006740c] vfs_ioctl+0x6c/0x84
[ 1366.867560] [c752fee0] [c006778c] do_vfs_ioctl+0x368/0x39c
[ 1366.867560] [c752ff10] [c0067800] sys_ioctl+0x40/0x70
[ 1366.867560] [c752ff40] [c0002770] ret_from_syscall+0x0/0x3c
[ 1366.867560] Instruction dump:
[ 1366.867560] 7c634b78 7c031b78 4e800020 7c0006ac 88630000 5463063e
4e800020 7c0006ac
[ 1366.867560] a0630000 5463043e 4e800020 7c0006ac <80630000> 4e800020
7c0006ac 7c601e2c
Segmentation fault
# dmesg | grep gpio
[ 0.120666] Registering device xilinx_gpio:0
[ 0.121672] Registering device xilinx_gpio:1
[ 0.122682] Registering device xilinx_gpio:2
[ 0.292352] xgpio0 #0 at 0x81400000 mapped to 0xC9000000 device: 10,185
using IRQ#7
[ 0.293805] xgpio1 #1 at 0x81420000 mapped to 0xC9020000 device: 10,186
using IRQ#6
[ 0.295062] xgpio2 #2 at 0x81440000 mapped to 0xC9040000 device: 10,187
using IRQ#5
[ 1366.867560] TASK = c7c37030[202] 'gpio_test' THREAD: c752e000
[ 1366.867560] [c752fe90] [c00e66a8] xgpio_getinst+0x48/0xb0 (unreliable)
[ 1366.867560] [c752fea0] [c00e6a8c] xgpio_ioctl+0x1a0/0x1fc
Another program using a different strategy also fails:
#include <fcntl.h>
#include <stdio.h>
int main (int argc, char *argv[]) {
if (argc==2 || argc==3) {
int fd = open(argv[1], O_RDWR | O_NDELAY );
if (fd < 0) {
fprintf(stderr, "GPIO OPEN FAIL\n");
return -1;
}
unsigned long buff = 0;
if (argc==2) {
if (read(fd, &buff, 4) != 4)
fprintf(stderr, "GPIO READ ERROR\n");
else printf( "%x\n", buff);
} else {
buff=atoi(argv[2]);
if (write(fd, &buff, 4) != 4)
fprintf(stderr, "GPIO WRITE ERROR value %x\n", buff);
else printf( "Written %x successfully\n", buff);
}
close(fd);
} else {
fprintf(stderr, "Usage: %s device [value] to read or write data to gpio
device\n", argv[0]);
return 1;
}
return 0;
}
# GpioReadWrite /dev/xgpio
GPIO READ ERROR
# GpioReadWrite /dev/xgpio 7
GPIO WRITE ERROR value 0
I wanted to avoid writing a kernel module, but apparently I've ran out of
options...
--
Guillaume Dargaud
http://www.gdargaud.net/
More information about the Linuxppc-dev
mailing list