Copyright (C) 2001-2008 by egnite Software GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For additional information see http://www.ethernut.de/
TCP server for Port D I/O.
Program Ethernut with portdio.hex and enter
telnet x.x.x.x 12345
two times on two command prompts, replacing x.x.x.x with the IP address of your ethernut board. This will start two telnet session.
Enter help for a list of available commands.
Enter query on the first will show the current port status.
Then enter wait on this session, which will hang until the port status changes.
On the second telnet session enter set1 to set the first output bit.
#define MY_MAC {0x00,0x06,0x98,0x20,0x00,0x00} #define MY_IP "192.168.192.100" #define MY_MASK "255.255.255.0" #define MY_PORT 12345 #include <string.h> #include <stdio.h> #include <dev/board.h> #include <dev/gpio.h> #include <sys/heap.h> #include <sys/thread.h> #include <sys/timer.h> #include <sys/socket.h> #include <arpa/inet.h> #include <net/route.h> #include <netdb.h> #include <pro/dhcp.h> #if defined(ETHERNUT1) || defined(ETHERNUT2) #define INBANK 2 /* PORTB */ #define INPIN1 0 #define INPIN2 1 #define INPIN3 2 #define INPIN4 3 #define OUTBANK 2 /* PORTB */ #define OUTPIN1 4 #define OUTPIN2 5 #define OUTPIN3 6 #define OUTPIN4 7 #elif defined(ETHERNUT3) /* Uses same expansion port pins as Ethernut 1/2. */ #define INBANK 0 /* PIO */ #define INPIN1 0 #define INPIN2 1 #define INPIN3 2 #define INPIN4 3 #define OUTBANK 0 /* PIO */ #define OUTPIN1 4 #define OUTPIN2 5 #define OUTPIN3 6 #define OUTPIN4 7 #elif defined(AT91SAM7X_EK) #define INBANK 1 /* PIOA Joystick */ #define INPIN1 21 #define INPIN2 22 #define INPIN3 23 #define INPIN4 24 #define OUTBANK 2 /* PIOB User LEDs */ #define OUTPIN1 19 #define OUTPIN2 20 #define OUTPIN3 21 #define OUTPIN4 22 #elif defined(AT91SAM9260_EK) #define INBANK 1 /* PIOA */ #define INPIN1 30 /* Push button 3 */ #define INPIN2 31 /* Push button 4 */ #define OUTBANK 1 /* PIOA */ #define OUTPIN1 6 /* User LED */ #define OUTPIN2 9 /* Power LED */ #elif defined(EVK1100) #define INBANK 0 /* PA Joystick */ #define INPIN1 25 #define INPIN2 26 #define INPIN3 27 #define INPIN4 28 #define OUTBANK 1 /* PIOB User LEDs */ #define OUTPIN1 27 #define OUTPIN2 28 #define OUTPIN3 29 #define OUTPIN4 30 #endif /* * Previous AVR versions read the full PIN register. Now each input * and output pin is freely configurable (within a single port bank). * This routine collects all pins as they would have been read * from a single 8-bit register. */ #ifdef INBANK static int PortStatus(void) { int stat = 0; #ifdef INPIN1 stat |= GpioPinGet(INBANK, INPIN1); #endif #ifdef INPIN2 stat |= GpioPinGet(INBANK, INPIN2) << 1; #endif #ifdef INPIN3 stat |= GpioPinGet(INBANK, INPIN3) << 2; #endif #ifdef INPIN4 stat |= GpioPinGet(INBANK, INPIN4) << 3; #endif #ifdef OUTBANK #ifdef OUTPIN1 stat |= GpioPinGet(OUTBANK, OUTPIN1) << 4; #endif #ifdef OUTPIN2 stat |= GpioPinGet(OUTBANK, OUTPIN2) << 5; #endif #ifdef OUTPIN3 stat |= GpioPinGet(OUTBANK, OUTPIN3) << 6; #endif #ifdef OUTPIN4 stat |= GpioPinGet(OUTBANK, OUTPIN4) << 7; #endif #endif /* OUTBANK */ return stat; } #endif /* * Process client requests. */ void ProcessRequests(FILE * stream) { char buff[128]; char *cp; int stat = -1; fputs("200 Welcome to portdio. Type help to get help.\r\n", stream); for (;;) { fflush(stream); /* * Read a line from the client. Ignore * blank lines. */ if (fgets(buff, sizeof(buff), stream) == 0) break; if ((cp = strchr(buff, '\r')) != 0) *cp = 0; if ((cp = strchr(buff, '\n')) != 0) *cp = 0; if (buff[0] == 0) continue; /* * Memory info. */ if (strncmp(buff, "memory", strlen(buff)) == 0) { fprintf(stream, "210 %u bytes RAM free\r\n", (unsigned int)NutHeapAvailable()); continue; } #ifdef OUTBANK /* * Reset output bit. */ if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) { int ok = 1; switch (buff[strlen(buff) - 1]) { #ifdef OUTPIN1 case '1': GpioPinSetLow(OUTBANK, OUTPIN1); break; #endif #ifdef OUTPIN2 case '2': GpioPinSetLow(OUTBANK, OUTPIN2); break; #endif #ifdef OUTPIN3 case '3': GpioPinSetLow(OUTBANK, OUTPIN3); break; #endif #ifdef OUTPIN4 case '4': GpioPinSetLow(OUTBANK, OUTPIN4); break; #endif default: ok = 0; break; } if (ok) { fputs("210 OK\r\n", stream); } else fputs("410 Bad pin\r\n", stream); continue; } /* * Set output bit. */ if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) { int ok = 1; switch (buff[strlen(buff) - 1]) { #ifdef OUTPIN1 case '1': GpioPinSetHigh(OUTBANK, OUTPIN1); break; #endif #ifdef OUTPIN2 case '2': GpioPinSetHigh(OUTBANK, OUTPIN2); break; #endif #ifdef OUTPIN3 case '3': GpioPinSetHigh(OUTBANK, OUTPIN3); break; #endif #ifdef OUTPIN4 case '4': GpioPinSetHigh(OUTBANK, OUTPIN4); break; #endif default: ok = 0; break; } if (ok) { fputs("210 OK\r\n", stream); } else fputs("410 Bad pin\r\n", stream); continue; } #endif /* OUTBANK */ #ifdef INBANK /* * Port status. */ if (strncmp(buff, "query", strlen(buff)) == 0) { stat = PortStatus(); fprintf(stream, "210 %02X\r\n", stat); continue; } /* * wait for status change. */ if (strncmp(buff, "wait", strlen(buff)) == 0) { while (stat == PortStatus()) NutThreadYield(); stat = PortStatus(); fprintf(stream, "210 %02X\r\n", stat); continue; } #endif /* INBANK */ /* * Help. */ fputs("400 List of commands follows\r\n", stream); fputs("memory\tQueries number of RAM bytes free\r\n", stream); #if OUTBANK fputs("reset#\tSet output bit 1..4 low\r\n", stream); fputs("set#\tSet output bit 1..4 high\r\n", stream); #endif #if INBANK fputs("query\tQuery digital i/o status\r\n", stream); fputs("wait\tWaits for digital i/o change\r\n", stream); #endif fputs(".\r\n", stream); } } /* * Init Port D */ void init_dio(void) { /* Configure input pins, enable pull up. */ #ifdef INBANK #ifdef INPIN1 GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP); #endif #ifdef INPIN2 GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP); #endif #ifdef INPIN3 GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP); #endif #ifdef INPIN4 GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP); #endif #endif /* INBANK */ /* Configure output pins, set to low. */ #ifdef OUTBANK #ifdef OUTPIN1 GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN1); #endif #ifdef OUTPIN2 GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN2); #endif #ifdef OUTPIN3 GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN3); #endif #ifdef OUTPIN4 GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT); GpioPinSetLow(OUTBANK, OUTPIN4); #endif #endif /* OUTBANK */ } #ifdef DEV_ETHER void service(void) { TCPSOCKET *sock; FILE *stream; /* * Loop endless for connections. */ for (;;) { /* * Create a socket. */ sock = NutTcpCreateSocket(); /* * Listen at the configured port. If we return, we got a client. */ NutTcpAccept(sock, MY_PORT); /* * Create a stream from the socket. */ stream = _fdopen((int) sock, "r+b"); /* * Process client requests. */ ProcessRequests(stream); /* * Destroy our device. */ fclose(stream); /* * Close our socket. */ NutTcpCloseSocket(sock); } } THREAD(service_thread, arg) { for (;;) service(); } #endif /* DEV_ETHER */ /* * Main application routine. * * Nut/OS automatically calls this entry after initialization. */ int main(void) { uint8_t my_mac[] = MY_MAC; /* * Initialize digital I/O. */ init_dio(); #ifdef DEV_ETHER /* * Register Realtek controller at address 8300 hex * and interrupt 5. */ NutRegisterDevice(&DEV_ETHER, 0x8300, 5); /* * Configure lan interface. */ if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) { /* * No DHCP server available. Use hard coded values. */ uint32_t ip_addr = inet_addr(MY_IP); /* ICCAVR fix. */ NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK)); } /* * Start another service thread to allow * two concurrent connections. */ NutThreadCreate("sback", service_thread, 0, 1384); for (;;) service(); #endif /* DEV_ETHER */ return 0; }