This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP432E401Y: configure telnet services using (udpecho)sample code with static IP?

Part Number: MSP432E401Y

Tool/software: Code Composer Studio

I've followed the instructions in a related post for successfully establishing a static IP for the device based on the udpecho example code.   Now I would like to implement a simple telnet service as well.  Is anyone able to point me in the right direction for setting this up, I'm not finding a lot of documentation on the net or in the forums.

To be clear, I just want an idea of the necessary framework for a telnet service that I can build upon for displaying basic serial output to a (Putty) terminal as opposed to using the TI boards UART.

Thanks

  • Patrick,
    I will need to reach out to one of my colleagues, but I will try an get an answer to you by the end of the week.

    Chris
  • Hello Patrick,

    Did you refer the "telnet" utility in the folder "./sourceti/ndk/nettools/telnet/" of the SimpleLink MSP432E4 SDK?

    I have not used it yet, but is that something that works for you?

    Thanks,
    Sai
  • Hello Sai,

    Thank you. I have started to refer to the telnet utility, and I've also located the NDK API Guide which I'll study. I'll try seeing if these can help me get something configured for my purposes and get back to you later this week if I need any help.

    Thanks,
    Patrick
  • Hello Sai,

    so I did some review, and some digging.   I decided to try using XGCONF to configure a telnet operation.  

    I opened the graphical interface and enabled the NDK Global Network Settings, along with IP, TCP, and TELNET layers.    I then went in and added some custom code to power a couple PWMs and ADCs as well as push some terminal output to a UART display.   Everything compiles nicely, but I can't get a telnet terminal to open.

    I look back into XGCONF and see that there's the "Instance" tab, where I assume you can add a new telnet instance, however when I go to the tab all options and dialogs are disabled.     How do I add a telnet instance?

    I found this older thread (/support/embedded/tirtos/f/355/t/327369) which nicely covers the topic but for an older version of CCS and the NDK, still, everything looks reasonably unchanged.  It seems to imply that I should be able to use the Instance tab of the .cfg file telnet layer to create an instance and callback function.    But obviously something is wrong on my end as I don't have that ability.    Are there some additional steps I should be taking?

    I've used the 'empty_MSP_EXP432E401Y_tirtos_ccs' example as my starting point.   I've made some changes to the board.h files to add in features, but nothing substantive.  The main program I have running now is in empty.c

    /*
     *  ======== empty.c ========
     */
    
    /* For usleep() */
    #include <unistd.h>
    #include <stdint.h>
    #include <stddef.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/ADC.h>
    #include <ti/display/Display.h>
    #include <ti/drivers/PWM.h>
    // #include <ti/drivers/I2C.h>
    // #include <ti/drivers/SDSPI.h>
    // #include <ti/drivers/SPI.h>
    // #include <ti/drivers/UART.h>
    // #include <ti/drivers/Watchdog.h>
    
    /* Board Header file */
    #include "Board.h"
    //#include <ti/devices/msp432e4/driverlib/driverlib.h>
    
    /* global variableS FOR GUI COMPOSER */
    uint16_t adcValue = 0;
    uint16_t threshold = 2048;
    uint16_t trigger = 0;
    uint8_t cycleCount = 0;
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        /* 1 second delay */
        uint32_t    time = 100;     // update 8/sec
        uint16_t     statusTimer = 100;    // number of cycles per status LED toggle
        //[ PWM variables
        uint16_t   pwm1Period = 3000;
        uint16_t   pwm1duty = 0;
        uint16_t   pwm1dutyInc = 100;
    
        uint16_t   pwm2Period = 3000;
        uint16_t   pwm2duty = 0;
        uint16_t   pwm2dutyInc = 100;
    
        uint16_t    pwmtimer = statusTimer;
        //]
    
        /* Call driver init functions */
        GPIO_init();
        ADC_init();
        Display_init();
        PWM_init();
        // I2C_init();
        // SDSPI_init();
        // SPI_init();
        // UART_init();
        // Watchdog_init();
    
        //[ LEDs
        /* Configure the LED pin */
        GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);   // status LED
        GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);   // ADC threshold LED
    
        /* Turn on status LED */
        GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
        //]
    
        //[ Open the PWM Driver
        PWM_Handle pwm1 = NULL;
        PWM_Params pwm1params;
    
        PWM_Handle pwm2 = NULL;
        PWM_Params pwm2params;
    
        PWM_Params_init(&pwm1params);
        pwm1params.dutyUnits = PWM_DUTY_US;
        pwm1params.dutyValue = 0;
        pwm1params.periodUnits = PWM_PERIOD_US;
        pwm1params.periodValue = pwm1Period;
        pwm1 = PWM_open(Board_PWM0, &pwm1params);
        if (pwm1 == NULL) {
            /* Board_PWM0 did not open */
            while (1);
        }
    
        PWM_Params_init(&pwm2params);
        pwm2params.dutyUnits = PWM_DUTY_US;
        pwm2params.dutyValue = 0;
        pwm2params.periodUnits = PWM_PERIOD_US;
        pwm2params.periodValue = pwm2Period;
        pwm2 = PWM_open(Board_PWM1, &pwm2params);
        if (pwm2 == NULL) {
            /* Board_PWM1 did not open */
            while (1);
        }
    
        PWM_start(pwm1);
        PWM_start(pwm2);
        //]
    
        //[ Open the ADC Driver
        ADC_Handle adc0;
        ADC_Params adc0Params;
        ADC_Params_init(&adc0Params);
        adc0 = ADC_open(Board_ADC0, &adc0Params);
        if (adc0 == NULL)
        {
            // Error initializing ADC channel 0
            while(1);
        }
        //]
    
        //[ Open the display Driver
        Display_Handle    displayHandle;
        Display_Params    displayParams;
        Display_Params_init(&displayParams);
        displayHandle = Display_open(Display_Type_UART, NULL);
        //]
    
        /* Run the main routine */
        while(1) {
            int_fast16_t res;
            uint16_t adc0Value;
            //Display_printf(displayHandle, 1, 0, "In main");
    
            res = ADC_convert(adc0, &adc0Value);
            if(res == ADC_STATUS_SUCCESS) {
                Display_printf(displayHandle, 1, 0, "ADC Reading %d", adc0Value);
                if(adc0Value >= threshold) {        // arbitrary threshold
                    GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
                    trigger = 1;
                }
                else {
                    GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_OFF);
                    trigger = 0;
                }
            }
            cycleCount++;
    
            if(cycleCount == pwmtimer) {
                PWM_setDuty(pwm1, pwm1duty);
                pwm1duty = (pwm1duty + pwm1dutyInc);
                if (pwm1duty == pwm1Period || (!pwm1duty)) {
                    pwm1dutyInc = - pwm1dutyInc;
                }
    
                PWM_setDuty(pwm2, pwm2duty);
                pwm2duty = (pwm2duty + pwm2dutyInc);
                if (pwm2duty == pwm2Period || (!pwm2duty)) {
                    pwm2dutyInc = - pwm2dutyInc;
                }
            }
    
            if(cycleCount == statusTimer) {
                GPIO_toggle(Board_GPIO_LED0);
                cycleCount = 0;
            }
    
            usleep(time);
        }
    }
    

  • Okay, well I figured out how to create the telnet instance, so that's no longer the problem.   But now I'm having trouble understanding how to define the callback function.   Is there a good demo or example somewhere on how to define this for a telnet service?   I don't have a lot of experience with this, so any help is appreciated.\

    Patrick.

  • Hello Sai,

    Sorry for this running commentary. I think I figured out the callback function. I'm having the telnet service call the ndk default ConsoleOpen function. But now I get this error on build that tells me there's something incorrect in the way the console is being instantiated, I think.

    unresolved symbol VerStr, first referenced in C:\ti\simplelink_msp432e4_sdk_2_20_00_20\source\ti\ndk\tools\console\lib\console_min_ipv4.aem4f<console.oem4f>

    I traced this to what I think is something in .\source\ti\ndk\tools\console\console.c But now I'm stuck. Why would it be giving this error? Is there some additional #include i need to put into my empty.c file? I see that VerStr is a char pointer "extern char *VerStr;" but not sure what to do with it.

    Thanks for any help you can provide.

    Patrick.
  • Hi Patrick,

    You've pretty much figured it out. The ConsoleOpen function is the correct function to set for Telnet.

    The "VerStr" issue is a known one, you just need to define it as a global variable somewhere in your app. This was typically done in the 'netHooks.c' file in older examples:

    char *VerStr = "\nNDK Telnet Console\n"; // you can set this to say whatever you want ...

    Steve
  • Steve,

    Thank you very much for your help with this, but I'm seemingly still running into problems getting the telnet service to run consistently.  Using the stock udpecho example I defined a telnet instance but when I initialize the program I get a "failed" status for the telnet.

    Here is what the UART display terminal displays:

    the main changes I've made to the udpecho sample code are to define an initTelnet function which I call in the ndkStackThread along with the other initialization functions for IP, TCP and UDP.   I also created a second serviceReport function to have the telnet service call which is exactly identical to the existing serviceReport function in the example code.  

    Here is the initTelnet function:

    /*
     *  ===== initTelnet =====
     *  Configure a telnet instance
     *  see spru524k_ndk_api_ref p.96
     */
    static void initTelnet(void *hCfg)
    {
        CI_SERVICE_TELNET telnet;
    
        //bzero(&telnet, sizeof(telnet));
        memset(&telnet, NULL, sizeof(telnet));
        telnet.cisargs.Mode   = CIS_FLG_CALLBYIP | CIS_FLG_RESTARTIPTERM;
        telnet.cisargs.IfIdx  = 2;
        telnet.cisargs.IPAddr = INADDR_ANY;
        telnet.cisargs.pCbSrv = &serviceReportTelnet;
        telnet.param.MaxCon = 2;
        telnet.param.Port   = 23;
        telnet.param.Callback = &ConsoleOpen;
        CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_TELNET, 0,
                    sizeof(telnet), (unsigned char *)&telnet, NULL);
    
    }

    here is the serviceReportTelnet function:

    /*
     *  ======== serviceReportTelnet ========
     *  Function for reporting service status updates.
     */
    static char *taskNameTelnet[] = {"Telnet", "HTTP", "NAT", "DHCPS", "DHCPC", "DNS"};
    static char *reportStrTelnet[] = {"", "Running", "Updated", "Complete", "Fault"};
    static char *statusStrTelnet[] =
            {"Disabled", "Waiting", "IPTerm", "Failed","Enabled"};
    static void serviceReportTelnet(uint32_t item, uint32_t status, uint32_t report,
            void *h)
    {
        Display_printf(display, 0, 0, "Service Status: %-9s: %-9s: %-9s: %03d\n",
                       taskNameTelnet[item - 1], statusStrTelnet[status], reportStrTelnet[report / 256],
                report & 0xFF);
    }

    and here is the modified ndkStackThread function:

    /*
     *  ======== ndkStackThread ========
     *  NDK stack's main thread function
     */
    static void ndkStackThread(uintptr_t arg0, uintptr_t arg1)
    {
        void *hCfg;
        int rc;
        timer_t ndkHeartBeat;
        struct sigevent sev;
        struct itimerspec its;
        struct itimerspec oldIts;
        int ndkHeartBeatCount = 0;
    
        /* create the NDK timer tick */
        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_value.sival_ptr = &ndkHeartBeatCount;
        sev.sigev_notify_attributes = NULL;
        sev.sigev_notify_function = &llTimerTick;
    
        rc = timer_create(CLOCK_MONOTONIC, &sev, &ndkHeartBeat);
        if (rc != 0) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: failed to create timer (%d)\n");
        }
    
        /* start the NDK 100ms timer */
        its.it_interval.tv_sec = 0;
        its.it_interval.tv_nsec = 100000000;
        its.it_value.tv_sec = 0;
        its.it_value.tv_nsec = 100000000;
    
        rc = timer_settime(ndkHeartBeat, 0, &its, NULL);
        if (rc != 0) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: failed to set time (%d)\n");
        }
    
        rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT);
        if (rc) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: NC_SystemOpen Failed (%d)\n");
        }
    
        /* create and build the system configuration from scratch. */
        hCfg = CfgNew();
        if (!hCfg) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: Unable to create configuration\n");
            goto main_exit;
        }
    
        /* IP, TCP, UDP, and Telnet config */
        initIp(hCfg);
        initTcp(hCfg);
        initUdp(hCfg);
        initTelnet(hCfg);
    
        /* config low priority tasks stack size */
        rc = 2048;
        CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKLOW, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&rc, NULL);
    
        /* config norm priority tasks stack size */
        rc = 2048;
        CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKNORM, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&rc, NULL);
    
        /* config high priority tasks stack size */
        rc = 2048;
        CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKHIGH, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&rc, NULL);
    
        do
        {
            rc = NC_NetStart(hCfg, networkOpen, networkClose, networkIPAddr);
        } while(rc > 0);
    
        /* Shut down the stack */
        CfgFree(hCfg);
    
    main_exit:
        NC_SystemClose();
    
        /* stop and delete the NDK heartbeat */
        its.it_value.tv_sec = 0;
        its.it_value.tv_nsec = 0;
    
        rc = timer_settime(ndkHeartBeat, 0, &its, &oldIts);
    
        rc = timer_delete(ndkHeartBeat);
    
        Display_printf(display, 0, 0, "ndkStackThread: exiting ...\n");
    }

    The remainder of the udpecho example code is unchanged.

    I'm assuming that I'm doing something wrong in either the way I've defined the telnet instance, or maybe in how I call the init routine, but I can't seem to figure it out.   

    Just in case it helps, I've attached the complete ndk_tirtos.c file.       

    /*
     * Copyright (c) 2017-2018, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  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.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its 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.
     */
    
    /*
     *  ======== ndk_tirtos.c ========
     */
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    #include <ti/ndk/inc/netmain.h>
    #include <ti/ndk/inc/os/oskern.h>
    
    #include <signal.h>
    #include <time.h>
    #include <ti\ndk\inc\tools\console.h>
    
    #include <ti/display/Display.h>
    
    /* Socket file descriptor table */
    #define MAXSOCKETS 10
    uint32_t ti_ndk_socket_max_fd = MAXSOCKETS;
    void *ti_ndk_socket_fdtable[MAXSOCKETS];
    
    extern Display_Handle display;
    
    /* NDK memory manager page size and number of pages [used by mmAlloc()] */
    #define RAW_PAGE_SIZE 3072
    #define RAW_PAGE_COUNT 6
    
    const int ti_ndk_config_Global_rawPageSize  = RAW_PAGE_SIZE;
    const int ti_ndk_config_Global_rawPageCount = RAW_PAGE_COUNT;
    
    /* P.I.T. (page information table) */
    #ifdef __ti__
    #pragma DATA_SECTION(ti_ndk_config_Global_pit, ".bss:NDK_MMBUFFER");
    #pragma DATA_SECTION(ti_ndk_config_Global_pitBuffer, ".bss:NDK_MMBUFFER");
    PITENTRY ti_ndk_config_Global_pit[RAW_PAGE_COUNT];
    unsigned char ti_ndk_config_Global_pitBuffer[RAW_PAGE_SIZE * RAW_PAGE_COUNT];
    #elif defined (__IAR_SYSTEMS_ICC__)
    PITENTRY ti_ndk_config_Global_pit[RAW_PAGE_COUNT];
    unsigned char ti_ndk_config_Global_pitBuffer[RAW_PAGE_SIZE * RAW_PAGE_COUNT];
    #else
    PITENTRY ti_ndk_config_Global_pit[RAW_PAGE_COUNT]
            __attribute__ ((section(".bss:NDK_MMBUFFER")));
    unsigned char ti_ndk_config_Global_pitBuffer[RAW_PAGE_SIZE * RAW_PAGE_COUNT]
            __attribute__ ((section(".bss:NDK_MMBUFFER")));
    #endif
    
    /* Memory bucket sizes */
    #define SMALLEST 48
    #define LARGEST (RAW_PAGE_SIZE)
    
    const int ti_ndk_config_Global_smallest = SMALLEST;
    const int ti_ndk_config_Global_largest  = LARGEST;
    
    /* define the opening console string for the telnet instance */
    char *VerStr = "\nNDK Telnet Console\n";
    
    /* Memory Slot Tracking */
    uint32_t ti_ndk_config_Global_Id2Size[] =
            {SMALLEST, 96, 128, 256, 512, 1536, LARGEST};
    
    /*
     *  Local Packet Buffer Pool Definitions
     *
     *  The below variables/defines are used to override the defaults that are set
     *  in the Packet Buffer Manager (PBM) file src/stack/pbm/pbm_data.c
     */
    
    /*
     *  Number of buffers in PBM packet buffer free pool
     *
     *  The number of buffers in the free pool can have a significant effect
     *  on performance, especially in UDP packet loss. Increasing this number
     *  will increase the size of the static packet pool use for both sending
     *  and receiving packets.
     */
    #define PKT_NUM_FRAMEBUF 10
    
    /* Size of Ethernet frame buffer */
    #define PKT_SIZE_FRAMEBUF   1536
    
    const int ti_ndk_config_Global_numFrameBuf = PKT_NUM_FRAMEBUF;
    const int ti_ndk_config_Global_sizeFrameBuf = PKT_SIZE_FRAMEBUF;
    
    /* Data space for packet buffers */
    #ifdef __ti__
    #pragma DATA_ALIGN(ti_ndk_config_Global_pBufMem, 128);
    #pragma DATA_SECTION(ti_ndk_config_Global_pBufMem, ".bss:NDK_PACKETMEM");
    unsigned char
            ti_ndk_config_Global_pBufMem[PKT_NUM_FRAMEBUF * PKT_SIZE_FRAMEBUF];
    #elif defined (__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 128
    unsigned char
            ti_ndk_config_Global_pBufMem[PKT_NUM_FRAMEBUF * PKT_SIZE_FRAMEBUF];
    #else
    unsigned char ti_ndk_config_Global_pBufMem[PKT_NUM_FRAMEBUF * PKT_SIZE_FRAMEBUF]
            __attribute__ ((aligned(128), section(".bss:NDK_PACKETMEM")));
    #endif
    
    #ifdef __ti__
    #pragma DATA_ALIGN(ti_ndk_config_Global_pHdrMem, 128);
    #pragma DATA_SECTION(ti_ndk_config_Global_pHdrMem, ".bss:NDK_PACKETMEM");
    unsigned char ti_ndk_config_Global_pHdrMem[PKT_NUM_FRAMEBUF * sizeof(PBM_Pkt)];
    #elif defined (__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 128
    unsigned char ti_ndk_config_Global_pHdrMem[PKT_NUM_FRAMEBUF * sizeof(PBM_Pkt)];
    #else
    unsigned char ti_ndk_config_Global_pHdrMem[PKT_NUM_FRAMEBUF * sizeof(PBM_Pkt)]
            __attribute__ ((aligned(128), section(".bss:NDK_PACKETMEM")));
    #endif
    
    /* Our NETCTRL callback functions */
    static void networkOpen();
    static void networkClose();
    static void networkIPAddr(uint32_t IPAddr, uint32_t IfIdx, uint32_t fAdd);
    static char *hostName = "tisoc";
    
    extern void llTimerTick();
    
    /*
     *  ======== networkOpen ========
     *  This function is called after the configuration has booted
     */
    static void networkOpen()
    {
        extern void netOpenHook();
    
        /* call user defined network open hook */
        netOpenHook();
    }
    
    /*
     *  ======== networkClose ========
     *  This function is called when the network is shutting down,
     *  or when it no longer has any IP addresses assigned to it.
     */
    static void networkClose()
    {
        /* call user defined network close hook */
    }
    
    /*
     *  ======== networkIPAddr ========
     *  This function is called whenever an IP address binding is
     *  added or removed from the system.
     */
    static void networkIPAddr(uint32_t IPAddr, uint32_t IfIdx, uint32_t fAdd)
    {
        uint32_t IPTmp;
    
        if (fAdd) {
            Display_printf(display, 0, 0, "Network Added: ");
        }
        else {
            Display_printf(display, 0, 0, "Network Removed: ");
        }
    
        /* print the IP address that was added/removed */
        IPTmp = NDK_ntohl(IPAddr);
        Display_printf(display, 0, 0, "If-%d:%d.%d.%d.%d\n", IfIdx,
                (uint8_t)(IPTmp>>24)&0xFF, (uint8_t)(IPTmp>>16)&0xFF,
                (uint8_t)(IPTmp>>8)&0xFF, (uint8_t)IPTmp&0xFF);
    
        extern void netIPAddrHook();
    
        /* call user defined network IP address hook */
        netIPAddrHook(IPAddr, IfIdx, fAdd);
    }
    
    /*
     *  ======== serviceReport ========
     *  Function for reporting service status updates.
     */
    static char *taskName[] = {"Telnet", "HTTP", "NAT", "DHCPS", "DHCPC", "DNS"};
    static char *reportStr[] = {"", "Running", "Updated", "Complete", "Fault"};
    static char *statusStr[] =
            {"Disabled", "Waiting", "IPTerm", "Failed","Enabled"};
    static void serviceReport(uint32_t item, uint32_t status, uint32_t report,
            void *h)
    {
        Display_printf(display, 0, 0, "Service Status: %-9s: %-9s: %-9s: %03d\n",
                taskName[item - 1], statusStr[status], reportStr[report / 256],
                report & 0xFF);
    }
    
    /*
     *  ======== serviceReportTelnet ========
     *  Function for reporting service status updates.
     */
    static char *taskNameTelnet[] = {"Telnet", "HTTP", "NAT", "DHCPS", "DHCPC", "DNS"};
    static char *reportStrTelnet[] = {"", "Running", "Updated", "Complete", "Fault"};
    static char *statusStrTelnet[] =
            {"Disabled", "Waiting", "IPTerm", "Failed","Enabled"};
    static void serviceReportTelnet(uint32_t item, uint32_t status, uint32_t report,
            void *h)
    {
        Display_printf(display, 0, 0, "Service Status: %-9s: %-9s: %-9s: %03d\n",
                       taskNameTelnet[item - 1], statusStrTelnet[status], reportStrTelnet[report / 256],
                report & 0xFF);
    }
    
    /*
     *  ======== initTcp ========
     *  Configure the stack's TCP settings
     */
    static void initTcp(void *hCfg)
    {
        int transmitBufSize = 1024;
        int receiveBufSize = 1024;
        int receiveBufLimit = 2048;
    
        CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&transmitBufSize, NULL);
        CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXBUF, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&receiveBufSize, NULL);
        CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXLIMIT, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&receiveBufLimit, NULL);
    }
    
    /*
     *  ======== initIp ========
     *  Configure the stack's IP settings
     */
    static void initIp(void *hCfg)
    {
        CI_SERVICE_DHCPC dhcpc;
        unsigned char DHCP_OPTIONS[] = { DHCPOPT_SUBNET_MASK };
    
        /* Add global hostname to hCfg (to be claimed in all connected domains) */
        CfgAddEntry(hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,
                    strlen(hostName), (unsigned char *)hostName, NULL);
    
        /* Use DHCP to obtain IP address on interface 1 */
        memset(&dhcpc, 0, sizeof(dhcpc));
        dhcpc.cisargs.Mode   = CIS_FLG_IFIDXVALID;
        dhcpc.cisargs.IfIdx  = 1;
        dhcpc.cisargs.pCbSrv = &serviceReport;
        dhcpc.param.pOptions = DHCP_OPTIONS;
        dhcpc.param.len = 1;
        CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
                    sizeof(dhcpc), (unsigned char *)&dhcpc, NULL);
    }
    
    /*
     *  ===== initTelnet =====
     *  Configure a telnet instance
     *  see spru524k_ndk_api_ref p.96
     */
    static void initTelnet(void *hCfg)
    {
        CI_SERVICE_TELNET telnet;
    
        //bzero(&telnet, sizeof(telnet));
        memset(&telnet, NULL, sizeof(telnet));
        telnet.cisargs.Mode   = CIS_FLG_CALLBYIP | CIS_FLG_RESTARTIPTERM;
        telnet.cisargs.IfIdx  = 2;
        telnet.cisargs.IPAddr = INADDR_ANY;
        telnet.cisargs.pCbSrv = &serviceReportTelnet;
        telnet.param.MaxCon = 2;
        telnet.param.Port   = 23;
        telnet.param.Callback = &ConsoleOpen;
        CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_TELNET, 0,
                    sizeof(telnet), (unsigned char *)&telnet, NULL);
    
    }
    
    /*
     *  ======== initUdp ========
     *  Configure the stack's UDP settings
     */
    void initUdp(void *hCfg)
    {
        int receiveBufSize = 2048;
    
        CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&receiveBufSize, NULL);
    }
    
    /*
     *  ======== ndkStackThread ========
     *  NDK stack's main thread function
     */
    static void ndkStackThread(uintptr_t arg0, uintptr_t arg1)
    {
        void *hCfg;
        int rc;
        timer_t ndkHeartBeat;
        struct sigevent sev;
        struct itimerspec its;
        struct itimerspec oldIts;
        int ndkHeartBeatCount = 0;
    
        /* create the NDK timer tick */
        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_value.sival_ptr = &ndkHeartBeatCount;
        sev.sigev_notify_attributes = NULL;
        sev.sigev_notify_function = &llTimerTick;
    
        rc = timer_create(CLOCK_MONOTONIC, &sev, &ndkHeartBeat);
        if (rc != 0) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: failed to create timer (%d)\n");
        }
    
        /* start the NDK 100ms timer */
        its.it_interval.tv_sec = 0;
        its.it_interval.tv_nsec = 100000000;
        its.it_value.tv_sec = 0;
        its.it_value.tv_nsec = 100000000;
    
        rc = timer_settime(ndkHeartBeat, 0, &its, NULL);
        if (rc != 0) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: failed to set time (%d)\n");
        }
    
        rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT);
        if (rc) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: NC_SystemOpen Failed (%d)\n");
        }
    
        /* create and build the system configuration from scratch. */
        hCfg = CfgNew();
        if (!hCfg) {
            Display_printf(display, 0, 0,
                    "ndkStackThread: Unable to create configuration\n");
            goto main_exit;
        }
    
        /* IP, TCP, UDP, and Telnet config */
        initIp(hCfg);
        initTcp(hCfg);
        initUdp(hCfg);
        initTelnet(hCfg);
    
        /* config low priority tasks stack size */
        rc = 2048;
        CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKLOW, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&rc, NULL);
    
        /* config norm priority tasks stack size */
        rc = 2048;
        CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKNORM, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&rc, NULL);
    
        /* config high priority tasks stack size */
        rc = 2048;
        CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKHIGH, CFG_ADDMODE_UNIQUE,
                sizeof(uint32_t), (unsigned char *)&rc, NULL);
    
        do
        {
            rc = NC_NetStart(hCfg, networkOpen, networkClose, networkIPAddr);
        } while(rc > 0);
    
        /* Shut down the stack */
        CfgFree(hCfg);
    
    main_exit:
        NC_SystemClose();
    
        /* stop and delete the NDK heartbeat */
        its.it_value.tv_sec = 0;
        its.it_value.tv_nsec = 0;
    
        rc = timer_settime(ndkHeartBeat, 0, &its, &oldIts);
    
        rc = timer_delete(ndkHeartBeat);
    
        Display_printf(display, 0, 0, "ndkStackThread: exiting ...\n");
    }
    
    /*
     * ======== ti_ndk_config_Global_startupFxn ========
     * Called to start up the NDK. In BIOS, this can be called as a BIOS startup
     * function, or from main(). In FreeRTOS, this should be called from main().
     */
    void ti_ndk_config_Global_startupFxn()
    {
        Task_Params params;
        Task_Handle ndkThread;
    
        Task_Params_init(&params);
        params.instance->name = "ndkStackThread";
        params.priority = 5;
        params.stackSize = 2048;
    
        ndkThread = Task_create((Task_FuncPtr)ndkStackThread, &params, NULL);
    
        if (!ndkThread) {
            /* Error: could not create NDK stack thread */
            while(1);
        }
    }
    

    I hope you can point me to whatever it is I'm still doing wrong.   

    Thank you

    Patrick

  • Well,

    I never got the telnet service to operate reliably.   I worked around the issue by defining my own connection socket and interface console.  

**Attention** This is a public forum