Program Ethernut with tcps.hex and enter
on a command prompt, replacing x.x.x.x with the IP address of your ethernut board. Enter help for a list of available commands.
00001 /* 00002 * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 * 00032 */ 00033 00083 #include <cfg/os.h> 00084 #include <string.h> 00085 #include <stdio.h> 00086 #include <io.h> 00087 00088 #include <dev/board.h> 00089 00090 #include <sys/version.h> 00091 #include <sys/heap.h> 00092 #include <sys/thread.h> 00093 #include <sys/timer.h> 00094 #include <sys/socket.h> 00095 00096 #include <arpa/inet.h> 00097 #include <pro/dhcp.h> 00098 00099 #ifdef NUTDEBUG 00100 #include <sys/osdebug.h> 00101 #include <net/netdebug.h> 00102 #endif 00103 00104 #include <sys/confnet.h> 00105 00106 static char buff[128]; 00107 00108 /* 00109 * To save RAM, we store large strings in program space. With AVRGCC we 00110 * would be able to use the PSTR() macro and put the text directly in 00111 * the statement that uses it. But ICCAVR doesn't support anything like 00112 * this. Sigh. 00113 */ 00114 #if defined(__IMAGECRAFT__) 00115 #define CC_STRING "ICCAVR" 00116 #elif defined(__GNUC__) 00117 #define CC_STRING "AVRGCC" 00118 #else 00119 #define CC_STRING "Compiler unknown" 00120 #endif 00121 00122 prog_char vbanner_P[] = "\n\nTCP Server Sample - Nut/OS %s - " CC_STRING "\n"; 00123 prog_char banner_P[] = "200 Welcome to tcps. Type help to get help.\r\n"; 00124 prog_char help_P[] = "400 List of commands follows\r\n" 00125 "m[emory]\tQueries number of RAM bytes free.\r\n" 00126 "t[hreads]\tLists all created threads.\r\n" 00127 "ti[mers]\tLists all running timers.\r\n" "q[uit]\t\tTerminates connection.\r\n" ".\r\n"; 00128 prog_char thread_intro_P[] = "220 List of threads with name,state,prio,stack,mem,timeout follows\r\n"; 00129 prog_char timer_intro_P[] = "221 List of timers with ticks left and interval follows\r\n"; 00130 prog_char mem_fmt_P[] = "210 %u bytes RAM free\r\n"; 00131 00132 /* 00133 * Process client requests. 00134 */ 00135 void ProcessRequests(FILE * stream) 00136 { 00137 int got; 00138 char *cp; 00139 00140 /* 00141 * Send a welcome banner. 00142 */ 00143 fputs_P(banner_P, stream); 00144 for (;;) { 00145 00146 /* 00147 * Flush output and read a line. 00148 */ 00149 fflush(stream); 00150 if (fgets(buff, sizeof(buff), stream) == 0) 00151 break; 00152 00153 /* 00154 * Chop off EOL. 00155 */ 00156 if ((cp = strchr(buff, '\r')) != 0) 00157 *cp = 0; 00158 if ((cp = strchr(buff, '\n')) != 0) 00159 *cp = 0; 00160 00161 /* 00162 * Ignore blank lines. 00163 */ 00164 got = strlen(buff); 00165 if (got == 0) 00166 continue; 00167 00168 /* 00169 * Memory info. 00170 */ 00171 if (strncmp(buff, "memory", got) == 0) { 00172 fprintf_P(stream, mem_fmt_P, (u_int)NutHeapAvailable()); 00173 continue; 00174 } 00175 00176 /* 00177 * List threads. 00178 */ 00179 if (strncmp(buff, "threads", got) == 0) { 00180 NUTTHREADINFO *tdp; 00181 NUTTIMERINFO *tnp; 00182 00183 fputs_P(thread_intro_P, stream); 00184 for (tdp = nutThreadList; tdp; tdp = tdp->td_next) { 00185 fputs(tdp->td_name, stream); 00186 switch (tdp->td_state) { 00187 case TDS_TERM: 00188 fputs("\tTerm\t", stream); 00189 break; 00190 case TDS_RUNNING: 00191 fputs("\tRun\t", stream); 00192 break; 00193 case TDS_READY: 00194 fputs("\tReady\t", stream); 00195 break; 00196 case TDS_SLEEP: 00197 fputs("\tSleep\t", stream); 00198 break; 00199 } 00200 fprintf(stream, "%u\t%u", tdp->td_priority, (u_int) tdp->td_sp - (u_int) tdp->td_memory); 00201 if (*((u_long *) tdp->td_memory) != DEADBEEF) 00202 fputs("\tCorrupted\t", stream); 00203 else 00204 fputs("\tOK\t", stream); 00205 00206 if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0) 00207 fprintf(stream, "%lu\r\n", tnp->tn_ticks_left); 00208 else 00209 fputs("None\r\n", stream); 00210 } 00211 fputs(".\r\n", stream); 00212 continue; 00213 } 00214 00215 /* 00216 * List timers. 00217 */ 00218 if (strncmp("timers", buff, got) == 0) { 00219 NUTTIMERINFO *tnp; 00220 00221 fputs_P(timer_intro_P, stream); 00222 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) { 00223 fprintf(stream, "%lu\t", tnp->tn_ticks_left); 00224 if (tnp->tn_ticks) 00225 fprintf(stream, "%lu\r\n", tnp->tn_ticks); 00226 else 00227 fputs("Oneshot\r\n", stream); 00228 } 00229 fputs(".\r\n", stream); 00230 continue; 00231 } 00232 00233 /* 00234 * Quit connection. 00235 */ 00236 if (strncmp("quit", buff, got) == 0) { 00237 break; 00238 } 00239 00240 /* 00241 * Display help text on any unknown command. 00242 */ 00243 fputs_P(help_P, stream); 00244 } 00245 } 00246 00247 /* 00248 * Main application routine. 00249 * 00250 * Nut/OS automatically calls this entry after initialization. 00251 */ 00252 int main(void) 00253 { 00254 TCPSOCKET *sock; 00255 FILE *stream; 00256 u_long baud = 115200; 00257 u_char mac[6] = { 0x00, 0x06, 0x98, 0x00, 0x00, 0x55 }; 00258 00259 /* 00260 * Register all devices used in our application. 00261 */ 00262 NutRegisterDevice(&DEV_DEBUG, 0, 0); 00263 NutRegisterDevice(&DEV_ETHER, 0x8300, 5); 00264 00265 /* 00266 * Assign stdout to the UART device. 00267 */ 00268 freopen(DEV_DEBUG_NAME, "w", stdout); 00269 _ioctl(_fileno(stdout), UART_SETSPEED, &baud); 00270 printf_P(vbanner_P, NutVersionString()); 00271 #ifdef NUTDEBUG 00272 NutTraceTcp(stdout, 1); 00273 NutTraceOs(stdout, 0); 00274 NutTraceHeap(stdout, 0); 00275 NutTracePPP(stdout, 0); 00276 #endif 00277 00278 NutNetLoadConfig(DEV_ETHER_NAME); 00279 memcpy(confnet.cdn_mac, mac, 6); 00280 NutNetSaveConfig(); 00281 00282 /* 00283 * Setup the ethernet device. Try DHCP first. If this is 00284 * the first time boot with empty EEPROM and no DHCP server 00285 * was found, use hardcoded values. 00286 */ 00287 printf("Configure eth0..."); 00288 if (NutDhcpIfConfig("eth0", 0, 60000)) { 00289 printf("initial boot..."); 00290 if (NutDhcpIfConfig("eth0", mac, 60000)) { 00291 u_long ip_addr = inet_addr("192.168.192.100"); 00292 u_long ip_mask = inet_addr("255.255.255.0"); 00293 00294 printf("no DHCP..."); 00295 NutNetIfConfig("eth0", mac, ip_addr, ip_mask); 00296 /* If not in a local network, we must also call 00297 NutIpRouteAdd() to configure the routing. */ 00298 } 00299 } 00300 puts("OK"); 00301 printf("IP: %s\n", inet_ntoa(confnet.cdn_ip_addr)); 00302 00303 /* 00304 * Now loop endless for connections. 00305 */ 00306 for (;;) { 00307 /* 00308 * Create a socket. 00309 */ 00310 if ((sock = NutTcpCreateSocket()) != 0) { 00311 /* 00312 * Listen on port 23. If we return, we got a client. 00313 */ 00314 printf("Waiting for a telnet client..."); 00315 if (NutTcpAccept(sock, 23) == 0) { 00316 puts("connected"); 00317 00318 /* 00319 * Open a stream and associate it with the socket, so 00320 * we can use standard I/O. Note, that socket streams 00321 * currently do support text mode. 00322 */ 00323 if ((stream = _fdopen((int) sock, "r+b")) != 0) { 00324 /* 00325 * Process client requests. 00326 */ 00327 ProcessRequests(stream); 00328 puts("Disconnected"); 00329 00330 /* 00331 * Close the stream. 00332 */ 00333 fclose(stream); 00334 } else 00335 puts("Assigning a stream failed"); 00336 } else 00337 puts("failed"); 00338 00339 /* 00340 * Close our socket. 00341 */ 00342 NutTcpCloseSocket(sock); 00343 } 00344 } 00345 }