[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