* Still struggling with Xilinx GPIO...
@ 2008-05-26 15:43 Guillaume Dargaud
2008-05-27 16:42 ` John Bonesio
0 siblings, 1 reply; 4+ messages in thread
From: Guillaume Dargaud @ 2008-05-26 15:43 UTC (permalink / raw)
To: linuxppc-dev
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/
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: Still struggling with Xilinx GPIO...
2008-05-26 15:43 Still struggling with Xilinx GPIO Guillaume Dargaud
@ 2008-05-27 16:42 ` John Bonesio
2008-05-28 9:51 ` Guillaume Dargaud
0 siblings, 1 reply; 4+ messages in thread
From: John Bonesio @ 2008-05-27 16:42 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 6898 bytes --]
Hi Guillaume,
Try using channel 1. It may be set up where the first channel is 1 and
not 0.
- John
On Mon, 2008-05-26 at 17:43 +0200, Guillaume Dargaud wrote:
> 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...
________________________________________________________________________
John Bonesio
Commercial Linux Solutions
john.bonesio@xilinx.com
(408) 879-5569
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
[-- Attachment #2: Type: text/html, Size: 12054 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: Still struggling with Xilinx GPIO...
2008-05-27 16:42 ` John Bonesio
@ 2008-05-28 9:51 ` Guillaume Dargaud
2008-05-28 16:09 ` John Bonesio
0 siblings, 1 reply; 4+ messages in thread
From: Guillaume Dargaud @ 2008-05-28 9:51 UTC (permalink / raw)
To: John Bonesio; +Cc: linuxppc-dev
Hi John,
> Try using channel 1. It may be set up where the first channel is 1 and not
> 0.
Not sure what you mean...
I'm actually not clear how many devices I should have:
$ grep "GPIO.*BASEADDR"
arch/ppc/platforms/4xx/xparameters/xparameters_ml405.h
#define XPAR_GPIO_0_BASEADDR XPAR_LEDS_4BIT_BASEADDR
#define XPAR_GPIO_1_BASEADDR XPAR_LEDS_POSITIONS_BASEADDR
#define XPAR_GPIO_2_BASEADDR XPAR_PUSH_BUTTONS_POSITION_BASEADDR
But depending on the examples I look at, they define either:
crw-rw-rw- 1 root root 10, 185 May 26 13:49 xgpio
or:
crw-rw-rw- 1 root root 10, 185 May 26 13:18 xgpio0
crw-rw-rw- 1 root root 10, 186 May 26 13:18 xgpio1
crw-rw-rw- 1 root root 10, 187 May 26 13:18 xgpio2
If that is the former, I see the code uses:
gpio_ioctl.chan=0;
And I guess that's what you are refering to, right ?
Putting 1 gives me a working program, but no LED lights up and the buttons
are always shown at 0.
Putting 0 gives a nice core dump as in my previous msg.
Putting 2 locks up the system.
And... I don't see how the code manages to read/wite all 3 GPIOs with only
two IOCTL calls. Shouldn't they be 3 different calls using different
addresses ?!? Argh, this complete lack of documentation in maddening. Not
everything can be understood from reading the source.
Thanks.
--
Guillaume Dargaud
http://www.gdargaud.net/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Still struggling with Xilinx GPIO...
2008-05-28 9:51 ` Guillaume Dargaud
@ 2008-05-28 16:09 ` John Bonesio
0 siblings, 0 replies; 4+ messages in thread
From: John Bonesio @ 2008-05-28 16:09 UTC (permalink / raw)
To: Guillaume Dargaud; +Cc: linuxppc-dev
Hi Guillaume,
gpio_ioctl.chan = x;
That's what determines which gpio device gets used. Since using 1 at
least doesn't give you a core dump, I would guess that 1 is the correct
value to use there.
So the next thing to check is to make sure that the ioctl command codes
being used are right.
The only way I know how to do this is to look in the linux kernel source
for the gpio device. Try looking here:
linux/drivers/char/xilinx_gpio
Then you find the routine that is handling the ioctl commands. It'll
probably be called xgpio_ioctl. In this routine you'll see something
like:
switch(cmd) {
case XGPIO_IN:
...
The value for XGPIO_IN is defined in a header file (probably). The
header file might be called xgpio_ioctl.h.
So here's the key:
Make sure the value for XGPIO_IN used in the user application is the
same as the one used in the kernel.
At one point I had see a case where the values in the kernel had
changed, but the user application was still trying to use the old
values.
Hope this helps,
- John
On Wed, 2008-05-28 at 11:51 +0200, Guillaume Dargaud wrote:
> Hi John,
>
> > Try using channel 1. It may be set up where the first channel is 1 and not
> > 0.
>
> Not sure what you mean...
>
> I'm actually not clear how many devices I should have:
>
> $ grep "GPIO.*BASEADDR"
> arch/ppc/platforms/4xx/xparameters/xparameters_ml405.h
> #define XPAR_GPIO_0_BASEADDR XPAR_LEDS_4BIT_BASEADDR
> #define XPAR_GPIO_1_BASEADDR XPAR_LEDS_POSITIONS_BASEADDR
> #define XPAR_GPIO_2_BASEADDR XPAR_PUSH_BUTTONS_POSITION_BASEADDR
>
> But depending on the examples I look at, they define either:
>
> crw-rw-rw- 1 root root 10, 185 May 26 13:49 xgpio
> or:
> crw-rw-rw- 1 root root 10, 185 May 26 13:18 xgpio0
> crw-rw-rw- 1 root root 10, 186 May 26 13:18 xgpio1
> crw-rw-rw- 1 root root 10, 187 May 26 13:18 xgpio2
>
> If that is the former, I see the code uses:
> gpio_ioctl.chan=0;
> And I guess that's what you are refering to, right ?
>
> Putting 1 gives me a working program, but no LED lights up and the buttons
> are always shown at 0.
> Putting 0 gives a nice core dump as in my previous msg.
> Putting 2 locks up the system.
>
> And... I don't see how the code manages to read/wite all 3 GPIOs with only
> two IOCTL calls. Shouldn't they be 3 different calls using different
> addresses ?!? Argh, this complete lack of documentation in maddening. Not
> everything can be understood from reading the source.
>
> Thanks.
________________________________________________________________________
John Bonesio
Commercial Linux Solutions
john.bonesio@xilinx.com
(408) 879-5569
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-05-28 16:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-26 15:43 Still struggling with Xilinx GPIO Guillaume Dargaud
2008-05-27 16:42 ` John Bonesio
2008-05-28 9:51 ` Guillaume Dargaud
2008-05-28 16:09 ` John Bonesio
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).