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 00090 #define MY_MAC {0x00,0x06,0x98,0x20,0x00,0x00} 00091 #define MY_IP "192.168.192.100" 00092 #define MY_MASK "255.255.255.0" 00093 00094 #include <string.h> 00095 #include <stdio.h> 00096 00097 #include <dev/board.h> 00098 00099 #include <sys/heap.h> 00100 #include <sys/thread.h> 00101 #include <sys/timer.h> 00102 #include <sys/socket.h> 00103 00104 #include <arpa/inet.h> 00105 #include <net/route.h> 00106 #include <netdb.h> 00107 00108 #include <pro/dhcp.h> 00109 00110 00111 /* 00112 * Process client requests. 00113 */ 00114 void ProcessRequests(FILE * stream) 00115 { 00116 u_char buff[128]; 00117 u_char *cp; 00118 int stat = -1; 00119 00120 fputs("200 Welcome to portdio. Type help to get help.\r\n", stream); 00121 for (;;) { 00122 fflush(stream); 00123 00124 /* 00125 * Read a line from the client. Ignore 00126 * blank lines. 00127 */ 00128 if (fgets(buff, sizeof(buff), stream) == 0) 00129 break; 00130 if ((cp = strchr(buff, '\r')) != 0) 00131 *cp = 0; 00132 if ((cp = strchr(buff, '\n')) != 0) 00133 *cp = 0; 00134 if (buff[0] == 0) 00135 continue; 00136 00137 /* 00138 * Memory info. 00139 */ 00140 if (strncmp(buff, "memory", strlen(buff)) == 0) { 00141 fprintf(stream, "210 %u bytes RAM free\r\n", (u_int)NutHeapAvailable()); 00142 continue; 00143 } 00144 00145 /* 00146 * List threads. 00147 */ 00148 if (strncmp(buff, "threads", strlen(buff)) == 0) { 00149 NUTTHREADINFO *tdp; 00150 NUTTIMERINFO *tnp; 00151 00152 fputs("220 List of threads with name,state,prio,stack,mem,timeout follows\r\n", stream); 00153 for (tdp = nutThreadList; tdp; tdp = tdp->td_next) { 00154 fputs(tdp->td_name, stream); 00155 fputs("\t", stream); 00156 switch (tdp->td_state) { 00157 case TDS_TERM: 00158 fputs("\tTerm\t", stream); 00159 break; 00160 case TDS_RUNNING: 00161 fputs("\tRun\t", stream); 00162 break; 00163 case TDS_READY: 00164 fputs("\tReady\t", stream); 00165 break; 00166 case TDS_SLEEP: 00167 fputs("\tSleep\t", stream); 00168 break; 00169 } 00170 fprintf(stream, "%u\t%u", tdp->td_priority, (u_int) tdp->td_sp - (u_int) tdp->td_memory); 00171 if (*((u_long *) tdp->td_memory) != DEADBEEF) 00172 fputs("\tCorrupted\t", stream); 00173 else 00174 fputs("\tOK\t", stream); 00175 00176 if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0) 00177 fprintf(stream, "%lu", tnp->tn_ticks_left); 00178 else 00179 fputs("None", stream); 00180 fputs("\r\n", stream); 00181 } 00182 fputs(".\r\n", stream); 00183 continue; 00184 } 00185 00186 /* 00187 * List timer. 00188 */ 00189 if (strncmp(buff, "timers", strlen(buff)) == 0) { 00190 NUTTIMERINFO *tnp; 00191 00192 fputs("221 List of timers with ticks left and interval follows\r\n", stream); 00193 for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) { 00194 fprintf(stream, "%lu", tnp->tn_ticks_left); 00195 if (tnp->tn_ticks) 00196 fprintf(stream, "\t%lu\r\n", tnp->tn_ticks); 00197 else 00198 fputs("\tOneshot\r\n", stream); 00199 } 00200 fputs(".\r\n", stream); 00201 continue; 00202 } 00203 00204 /* 00205 * Port status. 00206 */ 00207 if (strncmp(buff, "query", strlen(buff)) == 0) { 00208 #ifdef __AVR__ 00209 stat = inb(PIND); 00210 #endif 00211 fprintf(stream, "210 %02X\r\n", stat); 00212 continue; 00213 } 00214 00215 /* 00216 * Reset output bit. 00217 */ 00218 if (strlen(buff) > 1 && strncmp(buff, "reset", strlen(buff) - 1) == 0) { 00219 int mask = 0; 00220 switch (buff[strlen(buff) - 1]) { 00221 case '1': 00222 mask = 0x10; 00223 break; 00224 case '2': 00225 mask = 0x20; 00226 break; 00227 case '3': 00228 mask = 0x40; 00229 break; 00230 case '4': 00231 mask = 0x80; 00232 break; 00233 } 00234 if (mask) { 00235 #ifdef __AVR__ 00236 outb(PORTD, inb(PORTD) & ~mask); 00237 #endif 00238 fputs("210 OK\r\n", stream); 00239 } else 00240 fputs("410 Bad pin\r\n", stream); 00241 continue; 00242 } 00243 00244 /* 00245 * Set output bit. 00246 */ 00247 if (strlen(buff) > 1 && strncmp(buff, "set", strlen(buff) - 1) == 0) { 00248 int mask = 0; 00249 switch (buff[strlen(buff) - 1]) { 00250 case '1': 00251 mask = 0x10; 00252 break; 00253 case '2': 00254 mask = 0x20; 00255 break; 00256 case '3': 00257 mask = 0x40; 00258 break; 00259 case '4': 00260 mask = 0x80; 00261 break; 00262 } 00263 if (mask) { 00264 #ifdef __AVR__ 00265 outb(PORTD, inb(PORTD) | mask); 00266 #endif 00267 fputs("210 OK\r\n", stream); 00268 } else 00269 fputs("410 Bad pin\r\n", stream); 00270 continue; 00271 } 00272 00273 /* 00274 * wait for status change. 00275 */ 00276 if (strncmp(buff, "wait", strlen(buff)) == 0) { 00277 #ifdef __AVR__ 00278 while (stat == inb(PIND)) 00279 NutThreadYield(); 00280 stat = inb(PIND); 00281 #endif 00282 fprintf(stream, "210 %02X\r\n", stat); 00283 continue; 00284 } 00285 00286 /* 00287 * Help. 00288 */ 00289 fputs("400 List of commands follows\r\n", stream); 00290 fputs("memory\tQueries number of RAM bytes free\r\n", stream); 00291 fputs("query\tQuery digital i/o status\r\n", stream); 00292 fputs("reset#\tSet output bit 1..4 low\r\n", stream); 00293 fputs("set#\tSet output bit 1..4 high\r\n", stream); 00294 fputs("threads\tLists all created threads\r\n", stream); 00295 fputs("timers\tLists all running timers\r\n", stream); 00296 fputs("wait\tWaits for digital i/o change\r\n", stream); 00297 fputs(".\r\n", stream); 00298 } 00299 } 00300 00301 /* 00302 * Init Port D 00303 */ 00304 void init_dio(void) 00305 { 00306 #ifdef __AVR__ 00307 /* 00308 * Upper four pins are output pins. 00309 */ 00310 outb(DDRD, 0xf0); 00311 00312 /* 00313 * Outputs to low and inputs pulled up. 00314 */ 00315 outb(PORTD, 0x0f); 00316 #endif 00317 } 00318 00319 void service(void) 00320 { 00321 TCPSOCKET *sock; 00322 FILE *stream; 00323 00324 /* 00325 * Loop endless for connections. 00326 */ 00327 for (;;) { 00328 /* 00329 * Create a socket. 00330 */ 00331 sock = NutTcpCreateSocket(); 00332 00333 /* 00334 * Listen on port 12345. If we return, 00335 * we got a client. 00336 */ 00337 NutTcpAccept(sock, 12345); 00338 00339 /* 00340 * Create a stream from the socket. 00341 */ 00342 stream = _fdopen((int) sock, "r+b"); 00343 00344 /* 00345 * Process client requests. 00346 */ 00347 ProcessRequests(stream); 00348 00349 /* 00350 * Destroy our device. 00351 */ 00352 fclose(stream); 00353 00354 /* 00355 * Close our socket. 00356 */ 00357 NutTcpCloseSocket(sock); 00358 } 00359 } 00360 00361 THREAD(service_thread, arg) 00362 { 00363 for (;;) 00364 service(); 00365 } 00366 00367 /* 00368 * Main application routine. 00369 * 00370 * Nut/OS automatically calls this entry after initialization. 00371 */ 00372 int main(void) 00373 { 00374 u_char my_mac[] = MY_MAC; 00375 00376 /* 00377 * Initialize digital I/O. 00378 */ 00379 init_dio(); 00380 00381 /* 00382 * Register Realtek controller at address 8300 hex 00383 * and interrupt 5. 00384 */ 00385 NutRegisterDevice(&DEV_ETHER, 0x8300, 5); 00386 00387 /* 00388 * Configure lan interface. 00389 */ 00390 if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000) && NutDhcpIfConfig("eth0", my_mac, 60000)) { 00391 /* 00392 * No DHCP server available. Use hard coded values. 00393 */ 00394 u_long ip_addr = inet_addr(MY_IP); /* ICCAVR fix. */ 00395 NutNetIfConfig("eth0", my_mac, ip_addr, inet_addr(MY_MASK)); 00396 } 00397 00398 /* 00399 * Start another service thread to allow 00400 * two concurrent connections. 00401 */ 00402 NutThreadCreate("sback", service_thread, 0, 1384); 00403 00404 for (;;) 00405 service(); 00406 }