[En-Nut-Discussion] Reboot, when receiving Data with gets() over RS232

Bernd Faulstich bernd.faulstich at philips.com
Fri Oct 21 16:28:10 CEST 2005


Hy to all Ethernut-User.

I have a question about using stdio with RS232.

I use the Ethernut 2.1b and modify the tcps-example.
After TCP-connect, i would receive commands over RS232.
So i changed the fgets-command to the gets line (line 162). 

/*
 * Process client requests.
 */
void ProcessRequests(FILE * stream)
{
    int got;
    char *cp;

    /*
     * Send a welcome banner.
     */
    fputs_P(banner_P, stream);
    for (;;) {
        /*
         * Flush output and read a line.
         */
        fflush(stream);
 
//              if ((fgets(buff, sizeof(buff), stream) == 0)){
//                      break;
//              }

        gets(buff);
        /*
         * Chop off EOL.
         */




In the main-function i configurate the UART like this

    /*
     * Register all devices used in our application.
     */
    NutRegisterDevice(&devDebug0, 0, 0);
    NutRegisterDevice(&DEV_ETHER, 0x8300, 5);
        NutRegisterDevice(&devUsartAvr0, 0, 0);
    /*
     * Assign stdin / stdout to the UART device.
     */
        freopen("uart0", "w", stdout);
        freopen("uart0", "r", stdin);
        _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
        _ioctl(_fileno(stdin), UART_SETSPEED, &baud);
    printf_P(vbanner_P, NutVersionString());




My problem is, that the Ethernut reboots at the gets(buff)-line.

WHY?
WHAT'S WRONG?
I have no idea...

Please write me, whats wrong at the Code above.


If you would test it: Here's the full c-Source:


/*
 * Copyright (C) 2001-2005 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 EGNITE SOFTWARE GMBH 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 EGNITE
 * SOFTWARE GMBH 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/
 *
 */

/*!
 * $Log: tcps.c,v $
 * Revision 1.4  2005/04/30 16:42:41  chaac
 * Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If 
NUTDEBUG
 * is defined in NutConf, it will make effect where it is used.
 *
 * Revision 1.3  2005/04/19 08:55:29  haraldkipp
 * Description updated
 *
 * 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.8  2003/02/04 16:24:35  harald
 * Adapted to version 3
 *
 * Revision 1.7  2002/06/26 17:29:06  harald
 * First pre-release with 2.4 stack
 *
 * Revision 1.6  2002/06/12 10:59:05  harald
 * *** empty log message ***
 *
 * Revision 1.5  2002/06/04 19:12:55  harald
 * *** empty log message ***
 *
 * Revision 1.4  2002/05/08 16:02:32  harald
 * First Imagecraft compilation
 *
 */

/*!
 * \example tcps/tcps.c
 *
 * Simple TCP server.
 *
 * Program Ethernut with tcps.hex and enter
 *
 * \code telnet x.x.x.x \endcode
 *
 * 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.
 */

#include <cfg/os.h>
#include <string.h>
#include <stdio.h>
#include <io.h>
#include <usartavr.h>
#include <stdlib.h>
#include <fcntl.h>

#ifdef ETHERNUT2
#include <dev/lanc111.h>
#else
#include <dev/nicrtl.h>
#endif
#include <dev/debug.h>

#include <sys/version.h>
#include <sys/heap.h>
#include <sys/thread.h>
#include <sys/timer.h>
#include <sys/socket.h>

#include <arpa/inet.h>
#include <pro/dhcp.h>

#ifdef NUTDEBUG
#include <sys/osdebug.h>
#include <net/netdebug.h>
#endif

#include <sys/confnet.h>

static char buff[128];

/*
 * To save RAM, we store large strings in program space. With AVRGCC we
 * would be able to use the PSTR() macro and put the text directly in
 * the statement that uses it. But ICCAVR doesn't support anything like 
 * this. Sigh.
 */
#if defined(__IMAGECRAFT__)
#define CC_STRING   "ICCAVR"
#elif defined(__GNUC__)
#define CC_STRING   "AVRGCC"
#else
#define CC_STRING   "Compiler unknown"
#endif

prog_char vbanner_P[] = "\n\nTCP Server Sample - Nut/OS %s - " CC_STRING 
"\n";
prog_char banner_P[] = "200 Welcome to tcps. Type help to get help.\r\n";
prog_char help_P[] = "400 List of commands follows\r\n"
    "m[emory]\tQueries number of RAM bytes free.\r\n"
    "t[hreads]\tLists all created threads.\r\n"
    "ti[mers]\tLists all running timers.\r\n" "q[uit]\t\tTerminates 
connection.\r\n" ".\r\n";
prog_char thread_intro_P[] = "220 List of threads with 
name,state,prio,stack,mem,timeout follows\r\n";
prog_char timer_intro_P[] = "221 List of timers with ticks left and 
interval follows\r\n";
prog_char mem_fmt_P[] = "210 %u bytes RAM free\r\n";





/*
 * Process client requests.
 */
void ProcessRequests(FILE * stream)
{
    int got;
    char *cp;

    /*
     * Send a welcome banner.
     */
    fputs_P(banner_P, stream);
    for (;;) {
        /*
         * Flush output and read a line.
         */
        fflush(stream);
 
//              if ((fgets(buff, sizeof(buff), stream) == 0)){
//                      break;
//              }
                gets(buff);
        /*
         * Chop off EOL.
         */
        if ((cp = strchr(buff, '\r')) != 0)
            *cp = 0;
        if ((cp = strchr(buff, '\n')) != 0)
            *cp = 0;
        /*
         * Ignore blank lines.
         */
        got = strlen(buff);
        if (got == 0)
            continue;
        /*
         * Memory info.
         */
        if (strncmp(buff, "memory", got) == 0) {
            fprintf_P(stream, mem_fmt_P, NutHeapAvailable());
            continue;
        }
        /*
         * List threads.
         */
        if (strncmp(buff, "threads", got) == 0) {
            NUTTHREADINFO *tdp;
            NUTTIMERINFO *tnp;
            fputs_P(thread_intro_P, stream);
            for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
                fputs(tdp->td_name, stream);
                switch (tdp->td_state) {
                case TDS_TERM:
                    fputs("\tTerm\t", stream);
                    break;
                case TDS_RUNNING:
                    fputs("\tRun\t", stream);
                    break;
                case TDS_READY:
                    fputs("\tReady\t", stream);
                    break;
                case TDS_SLEEP:
                    fputs("\tSleep\t", stream);
                    break;
                }
                fprintf(stream, "%u\t%u", tdp->td_priority, (u_short) 
tdp->td_sp - (u_short) tdp->td_memory);
                if (*((u_long *) tdp->td_memory) != DEADBEEF)
                    fputs("\tCorrupted\t", stream);
                else
                    fputs("\tOK\t", stream);

                if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0)
                    fprintf(stream, "%lu\r\n", tnp->tn_ticks_left);
                else
                    fputs("None\r\n", stream);
            }
            fputs(".\r\n", stream);
            continue;
        }

        /*
         * List timers.
         */
        if (strncmp("timers", buff, got) == 0) {
            NUTTIMERINFO *tnp;

            fputs_P(timer_intro_P, stream);
            for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
                fprintf(stream, "%lu\t", tnp->tn_ticks_left);
                if (tnp->tn_ticks)
                    fprintf(stream, "%lu\r\n", tnp->tn_ticks);
                else
                    fputs("Oneshot\r\n", stream);
            }
            fputs(".\r\n", stream);
            continue;
        }

                /*
         * 1.Aktion 
         */
        if (strncmp(buff, "1.Aktion", got) == 0) {
            fputs("Aktion 1 via TCP\r\n",stream);
                printf("Aktion 1 via RS232\r\n");
            continue;
        }
                /*
         * 2.Aktion
         */
        if (strncmp(buff, "2.Aktion", got) == 0) {
            fputs("Aktion 2\r\n",stream);
            continue;
        }
                /*
         * 3.Aktion
         */
        if (strncmp(buff, "3.Aktion", got) == 0) {
            fputs("Aktion 3\r\n",stream);
            continue;
        }
                /*
         * 4.Aktion
         */
        if (strncmp(buff, "4.Aktion", got) == 0) {
            fputs("Aktion 4\r\n",stream);
            continue;
        }
        /*
         * Quit connection.
         */
        if (strncmp("quit", buff, got) == 0) {
            break;
        }

        /*
         * Display help text on any unknown command.
         */
        fputs_P(help_P, stream);
    }
}

/*
 * Main application routine. 
 *
 * Nut/OS automatically calls this entry after initialization.
 */
int main(void)
{
    TCPSOCKET *sock;
    FILE *stream;
    u_long baud = 115200;
    u_char mac[6] = { 0x00, 0x06, 0x98, 0x21, 0x09, 0x15 };

    /*
     * Register all devices used in our application.
     */
    NutRegisterDevice(&devDebug0, 0, 0);
    NutRegisterDevice(&DEV_ETHER, 0x8300, 5);
        NutRegisterDevice(&devUsartAvr0, 0, 0);
    /*
     * Assign stdin / stdout to the UART device.
     */
        freopen("uart0", "w", stdout);
        freopen("uart0", "r", stdin);
        _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
        _ioctl(_fileno(stdin), UART_SETSPEED, &baud);
    printf_P(vbanner_P, NutVersionString());
#ifdef NUTDEBUG
    NutTraceTcp(stdout, 1);
    NutTraceOs(stdout, 0);
    NutTraceHeap(stdout, 0);
    NutTracePPP(stdout, 0);
#endif

    NutNetLoadConfig("eth0");
    memcpy(confnet.cdn_mac, mac, 6);
    NutNetSaveConfig();

    /*
     * Setup the ethernet device. Try DHCP first. If this is
     * the first time boot with empty EEPROM and no DHCP server
     * was found, use hardcoded values.
     */
    printf("Configure eth0...");
    if (NutDhcpIfConfig("eth0", 0, 5000)) {
        printf("initial boot...");
        if (NutDhcpIfConfig("eth0", mac, 5000)) {
            u_long ip_addr = inet_addr("192.168.0.169");
            u_long ip_mask = inet_addr("255.255.255.0");

            printf("no DHCP...");
            NutNetIfConfig("eth0", mac, ip_addr, ip_mask);
            /* If not in a local network, we must also call 
               NutIpRouteAdd() to configure the routing. */
        }
    }
    puts("OK");
    printf("IP: %s\n", inet_ntoa(confnet.cdn_ip_addr));

    /*
     * Now loop endless for connections.
     */
    for (;;) {
        /*
         * Create a socket.
         */
        if ((sock = NutTcpCreateSocket()) != 0) {
            /*
             * Listen on port 3357. If we return, we got a client.
             */
            printf("Waiting for a telnet client...");
            if (NutTcpAccept(sock, 3357) == 0) {
                puts("connected with Port 3357 (FELP)");
 
                /*
                 * Open a stream and associate it with the socket, so 
                 * we can use standard I/O. Note, that socket streams
                 * currently do support text mode.
                 */
 
                                if ((stream = _fdopen((int) sock, "r+b")) 
!= 0) {
                    /*
                     * Process client requests.
                     */
                    ProcessRequests(stream);
                    puts("Disconnected");

                    /*
                     * Close the stream.
                     */
                    fclose(stream);
                } else
                    puts("Assigning a stream failed");
            } else
                puts("failed");

            /*
             * Close our socket.
             */
            NutTcpCloseSocket(sock);
        }
    }
}


With kind regards, 

Bernd Faulstich


More information about the En-Nut-Discussion mailing list