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/
Revision 1.3 2005/11/22 09:16:31 haraldkipp Replaced specific device names by generalized macros. Casting size_t to int to avoid compiler warnings about printf format specifiers. Excluded hardware specific statements for non-AVR targets. This way it will not work on other targets, but at least compile without error.
Revision 1.2 2003/11/04 17:46:52 haraldkipp Adapted to Ethernut 2
Revision 1.1 2003/08/05 18:59:05 haraldkipp Release 3.3 update
Revision 1.7 2003/02/04 18:19:38 harald Version 3 released
Revision 1.6 2003/02/04 16:24:33 harald Adapted to version 3
Revision 1.5 2002/06/26 17:29:03 harald First pre-release with 2.4 stack
Revision 1.4 2002/06/12 10:56:16 harald *** empty log message ***
Revision 1.3 2002/06/04 19:12:37 harald *** empty log message ***
Revision 1.2 2002/05/08 16:02:31 harald First Imagecraft compilation
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.
00001 00099 #define MY_MAC {0x00,0x06,0x98,0x20,0x00,0x00} 00100 #define MY_IP "192.168.192.100" 00101 #define MY_MASK "255.255.255.0" 00102 #define MY_PORT 12345 00103 00104 #include <string.h> 00105 #include <stdio.h> 00106 00107 #include <dev/board.h> 00108 #include <dev/gpio.h> 00109 00110 #include <sys/heap.h> 00111 #include <sys/thread.h> 00112 #include <sys/timer.h> 00113 #include <sys/socket.h> 00114 00115 #include <arpa/inet.h> 00116 #include <net/route.h> 00117 #include <netdb.h> 00118 00119 #include <pro/dhcp.h> 00120 00121 #if defined(ETHERNUT1) || defined(ETHERNUT2) 00122 #define INBANK 2 /* PORTB */ 00123 #define INPIN1 0 00124 #define INPIN2 1 00125 #define INPIN3 2 00126 #define INPIN4 3 00127 #define OUTBANK 2 /* PORTB */ 00128 #define OUTPIN1 4 00129 #define OUTPIN2 5 00130 #define OUTPIN3 6 00131 #define OUTPIN4 7 00132 #elif defined(ETHERNUT3) 00133 /* Uses same expansion port pins as Ethernut 1/2. */ 00134 #define INBANK 0 /* PIO */ 00135 #define INPIN1 0 00136 #define INPIN2 1 00137 #define INPIN3 2 00138 #define INPIN4 3 00139 #define OUTBANK 0 /* PIO */ 00140 #define OUTPIN1 4 00141 #define OUTPIN2 5 00142 #define OUTPIN3 6 00143 #define OUTPIN4 7 00144 #elif defined(AT91SAM7X_EK) 00145 #define INBANK 1 /* PIOA Joystick */ 00146 #define INPIN1 21 00147 #define INPIN2 22 00148 #define INPIN3 23 00149 #define INPIN4 24 00150 #define OUTBANK 2 /* PIOB User LEDs */ 00151 #define OUTPIN1 19 00152 #define OUTPIN2 20 00153 #define OUTPIN3 21 00154 #define OUTPIN4 22 00155 #elif defined(AT91SAM9260_EK) 00156 #define INBANK 1 /* PIOA */ 00157 #define INPIN1 30 /* Push button 3 */ 00158 #define INPIN2 31 /* Push button 4 */ 00159 #define OUTBANK 1 /* PIOA */ 00160 #define OUTPIN1 6 /* User LED */ 00161 #define OUTPIN2 9 /* Power LED */ 00162 #endif 00163 00164 /* 00165 * Previous AVR versions read the full PIN register. Now each input 00166 * and output pin is freely configurable (within a single port bank). 00167 * This routine collects all pins as they would have been read 00168 * from a single 8-bit register. 00169 */ 00170 static int PortStatus(void) 00171 { 00172 int stat = 0; 00173 #ifdef INBANK 00174 #ifdef INPIN1 00175 stat |= GpioPinGet(INBANK, INPIN1); 00176 #endif 00177 #ifdef INPIN2 00178 stat |= GpioPinGet(INBANK, INPIN2) << 1; 00179 #endif 00180 #ifdef INPIN3 00181 stat |= GpioPinGet(INBANK, INPIN3) << 2; 00182 #endif 00183 #ifdef INPIN4 00184 stat |= GpioPinGet(INBANK, INPIN4) << 3; 00185 #endif 00186 #endif /* INBANK */ 00187 00188 #ifdef OUTBANK 00189 #ifdef OUTPIN1 00190 stat |= GpioPinGet(OUTBANK, OUTPIN1) << 4; 00191 #endif 00192 #ifdef OUTPIN2 00193 stat |= GpioPinGet(OUTBANK, OUTPIN2) << 5; 00194 #endif 00195 #ifdef OUTPIN3 00196 stat |= GpioPinGet(OUTBANK, OUTPIN3) << 6; 00197 #endif 00198 #ifdef OUTPIN4 00199 stat |= GpioPinGet(OUTBANK, OUTPIN4) << 7; 00200 #endif 00201 #endif /* OUTBANK */ 00202 00203 return stat; 00204 } 00205 00206 /* 00207 * Process client requests. 00208 */ 00209 void ProcessRequests(FILE * stream) 00210 { 00211 char buff[128]; 00212 char *cp; 00213 int stat = -1; 00214 00215 fputs("200 Welcome to portdio. Type help to get help.\r\n", stream); 00216 for (;;) { 00217 fflush(stream); 00218 00219 /* 00220 * Read a line from the client. Ignore 00221 * blank lines. 00222 */ 00223 if (fgets(buff, sizeof(buff), stream) == 0) 00224 break; 00225 if ((cp = strchr(buff, '\r')) != 0) 00226 *cp = 0; 00227 if ((cp = strchr(buff, '\n')) != 0) 00228 *cp = 0; 00229 if (buff[0] == 0) 00230 continue; 00231 00232 /* 00233 * Memory info. 00234 */ 00235 if (strncmp(buff, "memory", strlen(buff)) == 0) { 00236 fprintf(stream, "210 %u bytes RAM free\r\n", (u_int)NutHeapAvailable()); 00237 continue; 00238 } 00239 00240 #ifdef OUTBANK 00241 /* 00242 * Reset output bit. 00243 */ 00244 if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) { 00245 int ok = 1; 00246 switch (buff[strlen(buff) - 1]) { 00247 #ifdef OUTPIN1 00248 case '1': 00249 GpioPinSetLow(OUTBANK, OUTPIN1); 00250 break; 00251 #endif 00252 #ifdef OUTPIN2 00253 case '2': 00254 GpioPinSetLow(OUTBANK, OUTPIN2); 00255 break; 00256 #endif 00257 #ifdef OUTPIN3 00258 case '3': 00259 GpioPinSetLow(OUTBANK, OUTPIN3); 00260 break; 00261 #endif 00262 #ifdef OUTPIN4 00263 case '4': 00264 GpioPinSetLow(OUTBANK, OUTPIN4); 00265 break; 00266 #endif 00267 default: 00268 ok = 0; 00269 break; 00270 } 00271 if (ok) { 00272 fputs("210 OK\r\n", stream); 00273 } else 00274 fputs("410 Bad pin\r\n", stream); 00275 continue; 00276 } 00277 00278 /* 00279 * Set output bit. 00280 */ 00281 if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) { 00282 int ok = 1; 00283 switch (buff[strlen(buff) - 1]) { 00284 #ifdef OUTPIN1 00285 case '1': 00286 GpioPinSetHigh(OUTBANK, OUTPIN1); 00287 break; 00288 #endif 00289 #ifdef OUTPIN2 00290 case '2': 00291 GpioPinSetHigh(OUTBANK, OUTPIN2); 00292 break; 00293 #endif 00294 #ifdef OUTPIN3 00295 case '3': 00296 GpioPinSetHigh(OUTBANK, OUTPIN3); 00297 break; 00298 #endif 00299 #ifdef OUTPIN4 00300 case '4': 00301 GpioPinSetHigh(OUTBANK, OUTPIN4); 00302 break; 00303 #endif 00304 default: 00305 ok = 0; 00306 break; 00307 } 00308 if (ok) { 00309 fputs("210 OK\r\n", stream); 00310 } else 00311 fputs("410 Bad pin\r\n", stream); 00312 continue; 00313 } 00314 #endif /* OUTBANK */ 00315 00316 #ifdef INBANK 00317 /* 00318 * Port status. 00319 */ 00320 if (strncmp(buff, "query", strlen(buff)) == 0) { 00321 stat = PortStatus(); 00322 fprintf(stream, "210 %02X\r\n", stat); 00323 continue; 00324 } 00325 00326 /* 00327 * wait for status change. 00328 */ 00329 if (strncmp(buff, "wait", strlen(buff)) == 0) { 00330 while (stat == PortStatus()) 00331 NutThreadYield(); 00332 stat = PortStatus(); 00333 fprintf(stream, "210 %02X\r\n", stat); 00334 continue; 00335 } 00336 #endif /* INBANK */ 00337 00338 /* 00339 * Help. 00340 */ 00341 fputs("400 List of commands follows\r\n", stream); 00342 fputs("memory\tQueries number of RAM bytes free\r\n", stream); 00343 #if OUTBANK 00344 fputs("reset#\tSet output bit 1..4 low\r\n", stream); 00345 fputs("set#\tSet output bit 1..4 high\r\n", stream); 00346 #endif 00347 #if INBANK 00348 fputs("query\tQuery digital i/o status\r\n", stream); 00349 fputs("wait\tWaits for digital i/o change\r\n", stream); 00350 #endif 00351 fputs(".\r\n", stream); 00352 } 00353 } 00354 00355 /* 00356 * Init Port D 00357 */ 00358 void init_dio(void) 00359 { 00360 /* Configure input pins, enable pull up. */ 00361 #ifdef INBANK 00362 #ifdef INPIN1 00363 GpioPinConfigSet(INBANK, INPIN1, GPIO_CFG_PULLUP); 00364 #endif 00365 #ifdef INPIN2 00366 GpioPinConfigSet(INBANK, INPIN2, GPIO_CFG_PULLUP); 00367 #endif 00368 #ifdef INPIN3 00369 GpioPinConfigSet(INBANK, INPIN3, GPIO_CFG_PULLUP); 00370 #endif 00371 #ifdef INPIN4 00372 GpioPinConfigSet(INBANK, INPIN4, GPIO_CFG_PULLUP); 00373 #endif 00374 #endif /* INBANK */ 00375 00376 /* Configure output pins, set to low. */ 00377 #ifdef OUTBANK 00378 #ifdef OUTPIN1 00379 GpioPinConfigSet(OUTBANK, OUTPIN1, GPIO_CFG_OUTPUT); 00380 GpioPinSetLow(OUTBANK, OUTPIN1); 00381 #endif 00382 #ifdef OUTPIN2 00383 GpioPinConfigSet(OUTBANK, OUTPIN2, GPIO_CFG_OUTPUT); 00384 GpioPinSetLow(OUTBANK, OUTPIN2); 00385 #endif 00386 #ifdef OUTPIN3 00387 GpioPinConfigSet(OUTBANK, OUTPIN3, GPIO_CFG_OUTPUT); 00388 GpioPinSetLow(OUTBANK, OUTPIN3); 00389 #endif 00390 #ifdef OUTPIN4 00391 GpioPinConfigSet(OUTBANK, OUTPIN4, GPIO_CFG_OUTPUT); 00392 GpioPinSetLow(OUTBANK, OUTPIN4); 00393 #endif 00394 #endif /* OUTBANK */ 00395 } 00396 00397 void service(void) 00398 { 00399 TCPSOCKET *sock; 00400 FILE *stream; 00401 00402 /* 00403 * Loop endless for connections. 00404 */ 00405 for (;;) { 00406 /* 00407 * Create a socket. 00408 */ 00409 sock = NutTcpCreateSocket(); 00410 00411 /* 00412 * Listen at the configured port. If we return, we got a client. 00413 */ 00414 NutTcpAccept(sock, MY_PORT); 00415 00416 /* 00417 * Create a stream from the socket. 00418 */ 00419 stream = _fdopen((int) sock, "r+b"); 00420 00421 /* 00422 * Process client requests. 00423 */ 00424 ProcessRequests(stream); 00425 00426 /* 00427 * Destroy our device. 00428 */ 00429 fclose(stream); 00430 00431 /* 00432 * Close our socket. 00433 */ 00434 NutTcpCloseSocket(sock); 00435 } 00436 } 00437 00438 THREAD(service_thread, arg) 00439 { 00440 for (;;) 00441 service(); 00442 } 00443 00444 /* 00445 * Main application routine. 00446 * 00447 * Nut/OS automatically calls this entry after initialization. 00448 */ 00449 int main(void) 00450 { 00451 u_char my_mac[] = MY_MAC; 00452 00453 /* 00454 * Initialize digital I/O. 00455 */ 00456 init_dio(); 00457 00458 /* 00459 * Register Realtek controller at address 8300 hex 00460 * and interrupt 5. 00461 */ 00462 NutRegisterDevice(&DEV_ETHER, 0x8300, 5); 00463 00464 /* 00465 * Configure lan interface. 00466 */ 00467 if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) { 00468 /* 00469 * No DHCP server available. Use hard coded values. 00470 */ 00471 u_long ip_addr = inet_addr(MY_IP); /* ICCAVR fix. */ 00472 NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK)); 00473 } 00474 00475 /* 00476 * Start another service thread to allow 00477 * two concurrent connections. 00478 */ 00479 NutThreadCreate("sback", service_thread, 0, 1384); 00480 00481 for (;;) 00482 service(); 00483 00484 return 0; 00485 }