[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [microblaze-uclinux] Is gpio_test source available?
Hi Steven,
Merrifield, Steven (GE Infrastructure) wrote:
> Is the source to gpio_test available? I couldn't see it in the distribution or in CVS.
I've never put it into the main uClinux-dist because it's microblaze
specific (and not particularly interesting! ) But anyway, the source
and Makefile are attached.
> On my V2MB1000 (rev 1) board, only the RHS LED is being used - it seems to show the 2nd LSB only. eg, gpio_test A7 displays <blank><A>. Likewise, gpio_test ABCD displays <blank><C>. I know both LEDs work, because I've tried other programs.
> Also, the DIP switches always read as 00000000, regardless of their position.
Yep - this is because of a change in how platgen handled bit vectors
(busses) from EDK3.2 -> 6.1. I expect it's still the same in 6.2. To
get the GPIO working as expected under 6.1, you have to make some tiny
changes in the kernel source. It's messy, but anyway... The better fix
would be to isolate the changes in the MHS file, using the bus_split
macro and so on, but...
in linux-2.4.x/include/asm-microblaze/mbvanilla.h, edit the line (abt
line 50 i think)
#define MICROBLAZE_GPIO_DIR 0x0000FF00
to
#define MICROBLAZE_GPIO_DIR 0x000000FF
That gets the tristate directions "lined up" with the GPIO data lines.
I think the attached version of gpio_test should work directly after
that, you might need to similarly "shift" everything 8 bit to the right.
Regards,
John
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/ibm_ocp_gpio.h>
#define GPIO_DEV "/dev/gpio"
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("/dev/gpio", O_RDWR);
struct ibm_gpio_ioctl_data gpio_ioctl;
int result;
int command;
if(fd==-1) {
fprintf(stderr,"Unable to open /dev/gpio\n");
exit(1);
}
/*
if(argc!=2)
{
usage();
exit(1);
}
*/
gpio_ioctl.device=0;
/* Set the tristates */
gpio_ioctl.mask=0x000000FF;
ioctl(fd,IBMGPIO_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,IBMGPIO_OUT,(void *)&gpio_ioctl);
/* Read some data */
ioctl(fd,IBMGPIO_IN,(void *)&gpio_ioctl);
dump_dipsw(gpio_ioctl.data);
return 0;
}
EXEC1 = gpio_test
OBJS1 = gpio_test.o
all: $(EXEC1)
$(EXEC1): $(OBJS1)
$(CC) $(LDFLAGS) -o $@ $(OBJS1) $(LIBCRYPT) $(LDLIBS$(LDLIBS_$@))
romfs:
$(ROMFSINST) /bin/$(EXEC1)
clean:
rm -f $(EXEC1) *.elf *.gdb *.o