[/quote]
Yes, with kernel privileges, you CAN configure the pins from the user
Linux environment.
The following is a complete TCP server program in c that sets up a
group of GPIO pins
(avoiding some necessary pins in the same bank that will kill the
system if you
change their settings. Note I skip over pins 142 and 143.) It
compiles under a debian derived OS that has all the necessary
functions for GPIO access already built into it. I found this
necessary include stuff
was missing from angstrom, however.
Pretty much all the magic is done here by memory-mapped access
directly to the hardware
registers.
/*******server.c*********/
/*******Using select() for I/O multiplexing */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
/* port we're listening on */
#define PORT 2020
//following are bit masks for low 16 bit word of GPIO5
#define CS0 0x100 // chip select to first Mux
#define CS1 0x200 // chip select to second Mux
// following are bit masks for high 16-bit word of GPIO5
#define STROBE 0x1 // strobe mux latches
#define RESET 0x2 // Reset the Muxes
int main(int argc, char *argv[])
{
/* master file descriptor list */
fd_set master; /* temp file descriptor list for select() */
fd_set read_fds; /* server address */
struct sockaddr_in serveraddr; /* client address */
struct sockaddr_in clientaddr; /* maximum file descriptor number */
int fdmax; /* listening socket descriptor */
int listener; /* newly accept()ed socket
descriptor */
int newfd; /* buffer for client data */
char buf[1024];
int nbytes; /* for setsockopt() SO_REUSEADDR, below
*/
int yes = 1;
int addrlen, bufoffset;
int i, j, k, l, m, n, x, gpio_addr, gpio_addrH_set,
gpio_addrH_clr;
// int addrmap[16] = {0,1,2,3,4,5,8,9,10,
// 11,12,13,6, 7, 14, 15};
int addrmap[16] = {0,1,2,3,4,5,12, 13, 6,
7, 8, 9, 10, 11, 14, 15};
/* clear the master and temp sets */
FD_ZERO(&master);
FD_ZERO(&read_fds);
/* first, set up mapping and configure GPIO pads */
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
printf("Could not open memory\n");
return 0;
}
// Pad configuration
volatile ulong *pinconf;
pinconf = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0x48000000);
if (pinconf == MAP_FAILED) {
printf("Pinconf Mapping failed\n");
close(fd);
return 0;
}
// Configure Expansion header pins as I/O (GPIO 154..144) gap (GPIO
139 .. 130)
pinconf[0x2158/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 130,131
pinconf[0x215C/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 132,133
pinconf[0x2160/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 134,135
pinconf[0x2164/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 136,137
pinconf[0x2168/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 138,139
pinconf[0x216C/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 140,141
pinconf[0x2174/4] = 0x011C011C; // set pulltype, bi-dir and
mux mode 4, GPIO 144,145
close(fd);
printf("Pinconf completed.\n");
fd = open("/dev/mem", O_RDWR | O_SYNC);
// GPIO Configuration: configure are input
volatile ulong *gpio;
gpio = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0x49050000);
if (gpio == MAP_FAILED) {
printf("Gpio Mapping failed\n");
close(fd);
}
printf("GPIO mmap complete\n");
// Configure GPIO 5 bits 17,16 and 11..2 as output.
x = gpio[6034/4];
printf("gpio[6034/4] = %x\n",x);
// x = x & 0xfffcf003; // change bits 17, 16 and 11..2 to
zero
x = x & 0xfffc0003; // change bits 17, 16 and 11..2 to zero
gpio[0x6034/4] = x;
printf("config pads GPIO_139..130 to output\n");
fd = open("/dev/mem", O_RDWR | O_SYNC);
// GPIO Configuration: configure are input
volatile ushort *gpios;
gpios = (ushort*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0x49050000);
if (gpios == MAP_FAILED) {
printf("Gpios Mapping failed\n");
close(fd);
}
// parallel byte I/O on GPIO_137 .. GPIO_130
/* pin map is as follows :
Bit GPIO pad Expansion Header Pin #
Reset GPIO_145 10
Strobe GPIO_144 4
CS1 GPIO_139 3
CS0 GPIO_138 5
MSB GPIO_137 7
6 GPIO_136 9
5 GPIO_135 11
4 GPIO_134 13
3 GPIO_133 15
2 GPIO_132 17
1 GPIO_131 19
LSB GPIO_130 21
*/
int c=0;
gpio_addr = 0x603c/2; // addr of gpio data out reg
gpio_addrH_set = 0x6096/2; // addr of high 16-bit word of GPIO5
gpio_addrH_clr = 0x6092/2; // addr of high 16-bit word of GPIO5
/* now set up the server */
/* get the listener */
if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
/*just exit lol!*/
exit(1);
}
printf("Server-socket() is OK...\n");
/*"address already in use" error message */
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))
== -1)
{
perror("Server-setsockopt() error lol!");
exit(1);
}
printf("Server-setsockopt() is OK...\n");
/* bind */
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_port = htons(PORT);
memset(&(serveraddr.sin_zero), '\0', 8);
if(bind(listener, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) == -1)
{
perror("Server-bind() error lol!");
exit(1);
}
printf("Server-bind() is OK...\n");
/* listen */
if(listen(listener, 10) == -1)
{
perror("Server-listen() error lol!");
exit(1);
}
printf("Server-listen() is OK...\n");
/* add the listener to the master set */
FD_SET(listener, &master);
/* keep track of the biggest file descriptor */
fdmax = listener; /* so far, it's this one*/
/* loop */
for(;
{
/* copy it */
read_fds = master;
if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
{
perror("Server-select() error lol!");
exit(1);
}
printf("Server-select() is OK...\n");
/*run through the existing connections looking for data to be
read*/
for(i = 0; i <= fdmax; i++)
{
if(FD_ISSET(i, &read_fds))
{ /* we got one... */
if(i == listener)
{
/* handle new connections */
addrlen = sizeof(clientaddr);
if((newfd = accept(listener, (struct sockaddr
*)&clientaddr, &addrlen)) == -1)
{
perror("Server-accept() error lol!");
}
else
{
printf("Server-accept() is OK...\n");
FD_SET(newfd, &master); /* add to master set */
if(newfd > fdmax)
{ /* keep track of the maximum */
fdmax = newfd;
}
printf("%s: New connection from %s on socket %d
\n", argv[0], inet_ntoa(clientaddr.sin_addr), newfd);
}
}
else
{
/* handle data from a client */
if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0)
{
/* got error or connection closed by client */
if(nbytes == 0)
/* connection closed */
printf("%s: socket %d hung up\n", argv[0], i);
else
perror("recv() error lol!");
/* close it... */
close(i);
/* remove from master set */
FD_CLR(i, &master);
}
else
{
gpios[ gpio_addrH_set] = RESET;
gpios[ gpio_addrH_clr] = RESET;
/* we got some data from a client*/
if (nbytes >= 10) {
for (j=0; j < 16; j++) printf("%x ",buf[j]);
printf("\n");
bufoffset = 0;
for (j=0; j < 10; j++) {
if ((buf[j] == 0xff) && (buf[j+1] == 0xff))
bufoffset = j+2;
}
printf("offset to first data is %d
\n",bufoffset);
printf("message is %x, Length is %d
\n",i,nbytes);
for (j=0;j< 8;j++) {
printf("byte %x is %x\n",j,buf[j
+bufoffset]);
m = CS0; // clear control bits
printf("data = ");
for (k=0; k<16; k++) { // loop through
first 16 switches
if ((buf[j+bufoffset]) == addrmap[k]) {l =
0x80;}
else {l = 0;}
n = ((k & 0x0f) | ((j << 4) & 0x70) | l |
m) & 0x3ff;
printf("%x ",n);
gpios[gpio_addr] = (n & 0x3ff) << 2;
gpios[ gpio_addrH_set] = STROBE;
gpios[ gpio_addrH_clr] = STROBE;
// need to clear CS0 bit
n = n & (!CS0);
gpios[gpio_addr] = (n & 0x3ff ) << 2;
}
printf("\n");
m = CS1; // clear control bits
for (k=0; k<16; k++) { // loop through
second 16 switches
if ((buf[j+bufoffset]) == (addrmap[k]+16))
{l = 0x80;}
else {l = 0;}
n = ((k & 0x0f) | ((j << 4) & 0x70) | l |
m) & 0x3ff;
gpios[gpio_addr] = (n & 0x3ff) << 2;
gpios[ gpio_addrH_set] = STROBE;
gpios[ gpio_addrH_clr] = STROBE;
n = n & (!CS1);
gpios[gpio_addr] = (n & 0x3ff ) << 2;
}
}
}
}
}
}
}
}
return 0;
}