Documentation:NGW/Newbie/Detailed IO Tutorial

From AVRFreaks Wiki

Jump to: navigation, search
NGW100 Layout
NGW100 Layout
NGW100 Layout
NGW100 Layout
NGW100 with 40 IDC
NGW100 with 40 IDC
DEV Board with 4 Push Buttons
DEV Board with 4 Push Buttons
PushButton Design
PushButton Design

THIS IS STILL UNDER DEVELOPMENT

THIS IS STILL UNDER DEVELOPMENT

THIS IS STILL UNDER DEVELOPMENT

Please comment or amend if you like

Contents

[edit] 4 IO Project Demo

This is a Project by a Newbie, for Newbie's

The Project is a Simple IO Demo

4 Pushbuttons or Switches wired to port E

The Pushbuttons will turn the LED's on the NGW100 on and off.

Look at Reading a Switched Input for GPIO Switch Info

Other Newbie INFO at Newbie

[edit] NGW100 Header

The first thing I had to do was solder a header onto the board.

I chose to use a 40 pin IDC header with a Key (Same as your old PATA Hard drive Cable)

Using pointy-noised pliers I pulled out 2 pins at each end. (pin 1, 2, 39,40) So now its a 36 way IDE Header.

Line up the key so Pin 1 lines up with Pin 1 on the NGW100 (Do the same to your DEV board. This way you can't cross the wires over and blow things up (maybe :) )

I chose to solder a 40way header to J7 & J5 (You Can't solder a 40way header into J6 & J7 at the same time, its one or the other. Just use a normal 36 way Dual in-line header on the other).

See here for board layout Mechanical dimensions


[edit] PushButton Input Design

I have created a 4 pushbutton IO Board with a limited debounce circuit.

Pushbutton A is wired to PE01 (J7 Pin 25)

Pushbutton B is wired to PE02 (J7 Pin 26)

Pushbutton C is wired to PE03 (J7 Pin 1)

Pushbutton D is wired to PE04 (J7 Pin 2)

See the Schematics page 10


[edit] Setting up the GPIO

Setting the pin to be an input pin

see PushButton Information create this file

vi switch

copy and paste this into the switch file

mkdir /config/gpio/switch0
cd /config/gpio/switch0
echo 4 > gpio_id
echo 0x00000002 > pin_mask
echo 0x00000000 > oe_mask
echo 1 > enabled
mkdir /config/gpio/switch1
cd /config/gpio/switch1
echo 4 > gpio_id
echo 0x00000008 > pin_mask
echo 0x00000000 > oe_mask
echo 1 > enabled
mkdir /config/gpio/switch2
cd /config/gpio/switch2
echo 4 > gpio_id
echo 0x00000004 > pin_mask
echo 0x00000000 > oe_mask
echo 1 > enabled
mkdir /config/gpio/switch3
cd /config/gpio/switch3
echo 4 > gpio_id
echo 0x00000010 > pin_mask
echo 0x00000000 > oe_mask

Now make it executable

chmod +x switch

Now run switch

./switch

[edit] Testing IO from Command line

Testing the pushbutton using the command line see PushButton Information

Run this command and then push the Pushbutton A a couple of times

less /dev/gpio3

You should see some garbage characters when you press the button

do the same for Pushbutton B

less /dev/gpio4

do the same for Pushbutton C

less /dev/gpio5

do the same for Pushbutton D

less /dev/gpio6

[edit] Testing IO from C Program

Compile this Program

 #include <errno.h>
 #include <fcntl.h>
 #include <poll.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 static int fd;
 static unsigned long old_state, new_state;
 static int use_nonblock;
 static int use_async;
 static int use_poll;
 /*
  * When the -a option is given, this handler will be called whenever
  * the pin state changes.
  */
 static void sigio_handler(int sig, siginfo_t *info, void *context)
 {
	struct pollfd fds = {
		.fd = fd,
		.events = POLLIN,
	};
	unsigned long pin_state;
	int ret;
	if (use_poll) {
		/* There should be data available immediately */
		ret = poll(&fds, 1, 0);
		if (ret < 0) {
			perror("sigio_handler: poll:");
			return;
		} else if (ret == 0) {
			fprintf(stderr,
				"No data available in sigio_handler!\n");
			return;
		} else {
			fprintf(stderr, "sigio_handler: poll() returned %d\n",
				ret);
		}
	}
	/*
	 * Even if use_nonblock is set, this should never fail as we
	 * shouldn't be here if no new data is available.
	 */
	if (read(fd, &pin_state, sizeof(pin_state)) < 0)
		perror("read error in sigio_handler");
	else
 		new_state = pin_state;
 }
 static void display_usage(const char *cmd)
 {
	fprintf(stderr, "Usage: %s [-ahnp] [gpio-device]\n\n", cmd);
	fprintf(stderr, "  -a     Use asynchronous I/O (O_ASYNC)\n");
	fprintf(stderr, "  -h     Display usage information (this message)\n");
	fprintf(stderr, "  -n     Use nonblocking I/O (O_NONBLOCK)\n");
	fprintf(stderr, "  -p     Use poll() to wait for I/O\n");
	fprintf(stderr,	"\nIf no gpio-device is specified, /dev/gpio0 is used\n");
 }
 int main(int argc, char **argv)
 {
	const char *dev_name = "/dev/gpio0";
	while (1) {
		int c;
		c = getopt(argc, argv, "ahnp");
		if (c == -1)
			break;
		switch (c) {
		case 'a':
			use_async = 1;
			break;
		case 'n':
			use_nonblock = 1;
			break;
		case 'p':
			use_poll = 1;
			break;
		case 'h':
		case '?':
			display_usage(argv[0]);
			return 1;
		default:
			abort();
		}
	}
	if (optind < argc)
		dev_name = argv[optind++];
	fd = open(dev_name, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "failed to open %s: %s\n",
			dev_name, strerror(errno));
		return 1;
	}
	if (use_async) {
		struct sigaction sigio_action = {
			.sa_sigaction = sigio_handler,
			.sa_flags = SA_SIGINFO,
		};
		int flags;
		/*
		 * Don't mask any signals when handling SIGIO (except
		 * SIGIO itself, which is masked by default.)
		 */
		sigemptyset(&sigio_action.sa_mask);
		if (sigaction(SIGIO, &sigio_action, NULL)) {
			perror("failed to install SIGIO handler");
			return 1;
		}
		/* Tell the kernel that our process will take care of SIGIO */
		if (fcntl(fd, F_SETOWN, getpid())) {
			perror("failed to set fd owner");
			return 1;
		}
		/* Enable asynchronous I/O */
		flags = fcntl(fd, F_GETFL);
		if (fcntl(fd, F_SETFL, flags | O_ASYNC) < 0) {
			perror("failed to set O_ASYNC");
			return 1;
		}
	}
	if (use_nonblock) {
		int flags;
		/* Enable non-blocking I/O */
		flags = fcntl(fd, F_GETFL);
		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
			perror("failed to set O_NONBLOCK");
			return 1;
		}
	}
	if (read(fd, &old_state, sizeof(old_state)) < 0) {
		perror("failed to read initial pin state");
		return 1;
	}
	new_state = old_state;
	printf("0x%08lx\n", old_state);
	if (use_async) {
		sigset_t sigio_mask, saved_mask;

		sigemptyset(&sigio_mask);
		sigaddset(&sigio_mask, SIGIO);
		/*
		 * In order to avoid race conditions with
		 * sigio_handler, we need to mask SIGIO while checking
		 * for updates to the pin state. sigsuspend() will
		 * atomically restore the sigmask (i.e. unmask SIGIO)
		 * and suspend the process until a signal comes along.
		 */
		sigprocmask(SIG_BLOCK, &sigio_mask, &saved_mask);
		while (1) {
			if (new_state != old_state) {
				printf("0x%08lx\n", new_state);
				old_state = new_state;
			}
			/*
			 * If SIGIO comes along here, we would miss an
			 * update.  However, that won't happen since
			 * we've masked it.
			 */
			sigsuspend(&saved_mask);

			/*
			 * sigsuspend() always returns with an
			 * error. If everything is normal, errno will
			 * be set to EINTR because we received a
			 * signal, and "Interrupted system call" will
			 * be displayed here.
			 */
			perror("sigsuspend");
		}
	} else {
		struct pollfd fds = {
			.fd = fd,
			.events = POLLIN,
		};
		while (1) {
			if (use_poll) {
				int ret;

				ret = poll(&fds, 1, 1000);
				if (ret < 0) {
					perror("poll");
					return 1;
				} else if (ret == 0) {
					/*
					 * This is normal if no
					 * buttons are pushed for one
					 * second.
					 */
					fprintf(stderr, "poll() timed out\n");
					continue;
				} else {
					/* ret should always be 1 here */
					fprintf(stderr, "poll() returned %d\n",
						ret);
				}
			}
			if (read(fd, &new_state, sizeof(new_state)) < 0) {
				/*
				 * If -n is given and not -p or -a,
				 * read() will fail with EAGAIN, and
				 * "Resource temporarily unavailable"
				 * will be printed regularly. This is
				 * normal.
				 *
				 * However, if -p is given, no errors
				 * should ever happen here, even with
				 * -n, as poll() will ensure that we
				 * never get here unless data is
				 * available for reading.
				 */
				perror("read error");
				sleep(1);
			} else {
				printf("0x%08lx\n", new_state);
				old_state = new_state;
			}
		}
	}
 }

I got it from GPIO Demo

run this for each GPIO

/media/mmcblk0p1/GPIOc.elf /dev/gpio4

Test Pushbutton output should look like this

0x00000008
0x00000000 Push Button B Pressed
0x00000008 Push Button B Released
0x00000000 Push Button B Pressed
0x00000008 Push Button B Released

Congratulation you have test all 4 push button switches independently

[edit] The END of Push Button TESTING

Now that we have tested each input we can bring it all together

Reboot to remove all the gpio configs

Create this file

vi SwitchPortE

copy and paste this into the SwitchPortE file

mkdir /config/gpio/SwitchPortE
cd /config/gpio/SwitchPortE
echo 4 > gpio_id
echo 0x0000001E > pin_mask
echo 0x00000000 > oe_mask
echo 1 > enabled
cd /

Now make it executable

chmod +x SwitchPortE

Now run SwitchPortE

./SwitchPortE

NOTE: When we are happy with all the code you can add it to /etc/init.d/S99gpio and delete SwitchPortE & switch

Run this

/media/mmcblk0p1/GPIOc.elf /dev/gpio3

Test Pushbutton output should look like this

0x0000001e Push Button Released
0x0000001c Push Button A Pressed
0x0000001e Push Button Released
0x00000016 Push Button B Pressed
0x0000001e Push Button Released
0x0000001a Push Button C Pressed
0x0000001e Push Button Released
0x0000000e Push Button D Pressed
0x0000001e Push Button Released

Press Push Button A & B (Together)

0x0000001e Push Button Released
0x0000001c Push Button A Pressed and Held
0x00000014 Push Button B Pressed
0x0000001c Push Button B Released
0x0000001e Push Button Released


Congratulation you have test all 4 push button switches

[edit] Make the Push Button turn LED's on & off

Ok this program will toggle the LED A on Press and toggle on release

Going to add more code to make it interesting

Compile this Program

#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

#define BUFFERSIZE 257
#define LED_OFFSET 19

static int fd;
static unsigned long old_state, new_state;

static void display_usage(const char *cmd)
{
	fprintf(stderr, "Usage: %s  [gpio-device]\n\n", cmd);
	fprintf(stderr, "  -h     Display usage information (this message)\n");
	fprintf(stderr,	"\nIf no gpio-device is specified, /dev/gpio0 is used\n");
}

int main(int argc, char **argv)
{
		int led_on = -1;
		unsigned int pio_buffer;	
		int pio = 0;
		int retval = 0;
	
	const char *dev_name = "/dev/gpio3";

	while (1) {
		int c;
		c = getopt(argc, argv, "ahnp");
		if (c == -1)
			break;
		switch (c) {
		case 'h':
		case '?':
			display_usage(argv[0]);
			return 1;
		default:
			abort();
		}
	}

	if (optind < argc)
		dev_name = argv[optind++];

	fd = open(dev_name, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "failed to open %s: %s\n",
			dev_name, strerror(errno));
		return 1;
	}

	if (read(fd, &old_state, sizeof(old_state)) < 0) {
		perror("failed to read initial pin state");
		return 1;
	}
	new_state = old_state;
	printf("0x%08lx\n", old_state);

	while (1) {
		if (read(fd, &new_state, sizeof(new_state)) < 0) {
			perror("read error");
			sleep(1);
		} else {
			printf("0x%08lx\n", new_state);
			old_state = new_state;
			
	/* Get status on LED */
	pio = open("/dev/gpio1", O_RDWR|O_NONBLOCK);
	if (pio < 0) {
		printf("Error: I could not open the GPIO device.</p>\n");
		return 1;
	} else {
		retval = read(pio, &pio_buffer, 4);
		if (retval == 4) {
			led_on = pio_buffer & (1<<LED_OFFSET) ? 0 : 1;
		} else {
			if (retval >= 0) {
				printf("Error: I could only read %d bytes from the GPIO device.</p>\n", retval);
			} else {
				if (errno != EAGAIN) {
					printf("Error: I could not read from the GPIO device (%d).</p>\n", errno);
				}
			}
		}
	}

	if (led_on) {
		printf("LED is on => ");
		unsigned int off = 1<<LED_OFFSET;
		write(pio, &off, 4);
		printf("turning LED off => ");
	} else {
		printf("LED is off => ");
		unsigned int on = 0;
		write(pio, &on, 4);
		printf("turning LED on => ");
	}
	close(pio);
		}
	}
}

The LED should now react with the 4 Push Buttons

Special:Imagelist

Personal tools