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.

dm648 amd ndk2.0.0

I'm using dm648 ndk v2.0.0 to send  raw image(size : 1200*1600*2,frame rate: 3 frames/sec,tcp protocol), but meet some problems:

   By calling socket function send,every time we send NET_MAX_PACKET_SIZE bytes(maximum),

the code  as follows:

    while(nLeft > 0)
    {
        if(nLeft < NET_MAX_PACKET_SIZE)
            nSent = nLeft;
        else
            nSent = NET_MAX_PACKET_SIZE;
       
        if((nSent = send(nSock, (void *)pBuf, nSent, nFlags)) < 0)
        {
            NetLog_error1("sendn, send data error: %d.", fdError());
            return NET_API_EFAIL;
        }
        else if(nSent > nLeft)
        {
            NetLog_error("sendn, Send Data Error, send size > left.");
            return NET_API_EFAIL;
        }

        nLeft -= nSent;
        pBuf += nSent;

    }

 

1、if NET_MAX_PACKET_SIZE = 1664, the send will go wrong in 1 minutes ,  we can't ping the  bord !  when  NET_MAX_PACKET_SIZE = 1024, the code can run correctly!

2、if the send buf pBuf is in  cache, the send can't runing 8 hours, it maybe disconnect in some time,and we can't ping the bord again. if the send buf is in nocache, the dsp can

run more than 24 hours without connect error!

3、by using socket api function setsockopt( pInfo->nSocket, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size) ) to set the sendbuf to 16K,the send will go wrong in 1 minutes!

Has anyone ever had such problems, or know a way to solve it.

Thanks for your help!

  • Yongjia,

    I'm not the networking expert, but I believe that the NDK's packet buffer manager is limited to packets of 1500 bytes.  To exceed that limit, you would need to utilize the jumbo packet feature, which is not supported by all hardware.

    Dave

  • David Friedland:

            thanks for your  answer !   

           Another question: why can't call the function  setsockopt( pInfo->nSocket, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size) ) to change the sendbuf size?

           I read the driver codes of ndk , I found the follows:

          #pragma DATA_ALIGN(pBufMem, 128);
          #pragma DATA_SECTION(pBufMem, ".far:NDK_PACKETMEM");
          static UINT8 pBufMem[PKT_NUM_FRAMEBUF*PKT_SIZE_FRAMEBUF];

     

     

        // Initialize Free Queue
        PBMQ_init(&PBMQ_free);

        // Get temp pointers
        pBufTmp = pBufMem;
        pHdrTmp = pHdrMem;

        // Break memory array into packet buffers and push onto free queue
        for( i=0; i<PKT_NUM_FRAMEBUF; i++ )
        {
            pPkt = (PBM_Pkt *)pHdrTmp;
            pHdrTmp += sizeof(PBM_Pkt);

            pPkt->Type        = PBM_MAGIC_POOL;
            pPkt->BufferLen   = PKT_SIZE_FRAMEBUF;
            pPkt->pDataBuffer = pBufTmp;
            pPkt->pTimestampFxn = 0;
            pBufTmp += PKT_SIZE_FRAMEBUF;

            PBMQ_enq( &PBMQ_free, pPkt );
        }

     

      I want to know :

      1/  when i call the send function,   is the data copy directly to   pBufMem ?  Is sendbuf  same to pBufMem?

      2/  whether dm648 don't support  jumbo packet?   

  • Hi yongjia bi,

    yongjia bi said:

    1/  when i call the send function,   is the data copy directly to   pBufMem ?  Is sendbuf  same to pBufMem?

    No, pBufMem is the packet buffer pool, which is part of the NDK's Packet Buffer Manager (PBM).

    When you create a socket 'nSock', it will have an associated "socket buffer."  This buffer, as well the buffers associated with any other socket created in the program, will be allocated from pBufMem.

    So, when you call the send() function:

    if((nSent = send(nSock, (void *)pBuf, nSent, nFlags)) < 0)

    the data in pBuf will be copied into the socket nSock's buffer.

    If you are concerned about the effect that copying of data has on performance, there is a "no-copy" version of the receive API, however for TCP send, a "no-copy" version doesn't exist (this is because of the need to re-transmit, among other things).

    UDP and raw sockets both have "no-copy" send and receive functions, however.

    yongjia bi said:

      2/  whether dm648 don't support  jumbo packet?   

    I don't know of any restrictions for jumbo support for the DM648, but I do see the following in the NDK Programmer's Guide (spru5424_pg.pdf):

    A sample implementation of the Jumbo PBM is provided in the NDK OS abstraction layer (OS AL). The
    customer is expected to customize this implementation according to their application needs and
    system's memory constraints.The memory section sizes, block sizes, and the allocation method is all
    up for customization.

    So, you may need to customize the Jumbo PBM in order to tailor it to your needs.  You can find it in \SRC\OS
    \JUMBO_PBM.C

    yongjia bi said:

    2、if the send buf pBuf is in  cache, the send can't runing 8 hours, it maybe disconnect in some time,and we can't ping the bord again. if the send buf is in nocache, the dsp can

     

    run more than 24 hours without connect error!

    When you place the buffer in cache memory, is it in L2 cache?  If so, is the buffer using all of the L2 cache?  Here's some info from the NDK user's guide (spru523_ug.pdf):

    The NDK assumes there is some L2 cache. If the DSP is configured to all internal memory with
    nothing left for L2 cache, the NDK drivers will not function properly.

    Steve

     

     

  • yongjia bi,

    It turns out there is a hardware limitation for the DM648.  I just saw the following in our NDK FAQ regarding the DM648 hardware:

    "the hardware does not support Jumbo Frames (typically around 9000 bytes but can assume any value), since the DM648 EMAC peripheral has a limitation to receive frames up to 2047 bytes (headers included). This is still above the standard value of 1518 bytes."

    You can find the full FAQ here:

    http://processors.wiki.ti.com/index.php/Network_Developers_Kit_FAQ#Q:_Does_DM648_EVM_support_Gigabit_Ethernet.3F_What_about_Jumbo_Packets.3F

    Sorry for the confusion.

    Steve

  •  

    No, pBufMem is the packet buffer pool, which is part of the NDK's Packet Buffer Manager (PBM).

    When you create a socket 'nSock', it will have an associated "socket buffer."  This buffer, as well the buffers associated with any other socket created in the program, will be allocated from pBufMem.

    Do you mean : the socket buffer is allocated from pBufMem? 

    Another question is

    1/ why i can't increase the size of socket buffer to 16K?( if i set the socket buffer size to 16K,  The data can be sent more quickly,

                                                                                                                             but the send can't run long time( no more than 10 minutes) ! )

    2/In my code ,i create 8 sockets ! is there any conflict?

  • yongjia bi said:

    Do you mean : the socket buffer is allocated from pBufMem? 

    yes.

    yongjia bi said:

    Another question is

    1/ why i can't increase the size of socket buffer to 16K?( if i set the socket buffer size to 16K,  The data can be sent more quickly,

                                                                                                                             but the send can't run long time( no more than 10 minutes) ! )

    2/In my code ,i create 8 sockets ! is there any conflict?

    Just for my own understanding, are you sending/receiving on all of the sockets simultaneously?

    Have you played with different socket buffer sizes?  Does it work for 12K buffer size for example?

    Steve

  • There are two sockets which are used to send and receive message  simultaneously!

    other sockets include one socket(tcp) used to send image data , one socket (tcp) used to send video data and a socket used to send udp packets.

    I just set  one socket buffer size( this socket may go wrong! other socket run ok  ), the others use the  default value! and if the buffer size is set more than

    8192 bytes, it will go wrong!

  • yongjia bi,

    I'm trying to reproduce your problem here.  Do you have the NDK client example?

    The NDK client example contains a data server which will echo back data to the PC that is sent to it via the Windows program "send.exe".

    I've modified this data server to increase the TCP socket buffer to 16K and I am then able to run the send.exe program without any issue.  Can you try this and see if it works for you?

    FYI, I've updated the file to have the following lines in bold type:

    int dtask_tcp_nullsrv( SOCKET s, UINT32 unused )
    {
        struct timeval to;
        int            i;
        char           *pBuf;
        HANDLE         hBuffer;
        int x, size;
        int status = 0;

       
        (void)unused;

        // Configure our socket timeout to be 5 seconds
        to.tv_sec  = 5;
        to.tv_usec = 0;
        x = 16384;
        setsockopt( s, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof( to ) );
        setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof( to ) );
        setsockopt( s, SOL_SOCKET, SO_SNDBUF, &x, sizeof(x) );
       
        size = sizeof(size);
        getsockopt( s, SOL_SOCKET, SO_SNDBUF, &status, &size);
        printf("\nsend buffer size is %d\n", status);

       

    Please open the client example in CCS and then add the file "newservers.c" to the client example project and then rebuild.  Note that you may need to remove the newservers.c file from the project first if it is already part of the project.

    After you've added it, please rebuild and run the DSP side NDK program.  Then on Windows, from a DOS shell, run the send program.  For example, I'm running it on my machine from here:

    C:\Program Files\Texas Instruments\ndk_2_21_00_00_eng\packages\ti\ndk\winapps>send.exe 146.252.161.85

    8400.newservers.zip

     

    Are you able to run the send program for a long time, or does it crash like your other program does?

    Steve

  • Steven,

    I try to test the example of client,but it can't work on my board!

        x = 16384;
        setsockopt( s, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof( to ) );
        setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof( to ) );
        setsockopt( s, SOL_SOCKET, SO_SNDBUF, &x, sizeof(x) );

        The x = 16324*2!

    would you change the buffersize to 32K, and test it with large data sending  ?

    if you can run more than 1 hour, there is maybe some bug in my program!

     

    I copy my configure code of socket as follows, would you help me to review it?

    static void NetworkOpen()
    {   
        printf("Net open.\n");
        s_hNetVideoSend = TaskCreate(TaskNetVideoSend, "VideoSend", OS_TASKPRIHIGH_DEF, 0x10000, 0, 0, 0);
        s_hNetUpload = TaskCreate(TaskNetUpload, "NetUpload", OS_TASKPRIHIGH_DEF, 0x400000, 0, 0, 0);
        s_hNetServer = TaskCreate(TaskNetServer, "NetServer", OS_TASKPRINORM_DEF, 0x4000, 0, 0, 0);
        s_hNetUDP = TaskCreate(TaskNetUDP, "UDP", OS_TASKPRILOW_DEF, 0x4000, 0, 0, 0);   
        s_hNetLog = TaskCreate(TaskNetLog, "NetLog", OS_TASKPRINORM_DEF, 0x10000, 0, 0, 0);
    }


    void TaskNetworkSetup()
    {
        Int32           rc;
        HANDLE          hCfg;
        Uint8            cMainCfgBuf[512];
        Int32            nMainCfgSize;

        /* Wati net param be inited */
        while(!s_bIsParamInited)
            TSK_sleep(50);
       
        //
        // THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION!!
        //
        rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT);
        if( rc )
        {

            printf("NC_SystemOpen Failed (%d)\n",rc);

            for(;;);
        }   
       
        //set external heap for network
        //_mmBulkAllocSeg( extHeap );
       
        // Print out our banner
        #ifdef _DEBUG
        printf(DSP_VERSION_STRING);
        printf("\n-------------------\n");
        #endif
       
        //
        // Create and build the system configuration from scratch.
        //
       
        hCfg = CfgNew();
        if(!hCfg )
        {
            printf("Unable to create configuration\n");
            goto main_exit;
        } 

        // The evaluation version of TCP/IP Stack restricts usage of stack
        // to maximum of 24 Hours. If application wants to be notified 5 min
        // before the timeout, it can register a callback function by using
        // the following configuration code section.
        {
            void (*pFxn)() = &ShutdownCallBack;
            CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_SYSINFO_EVALCALLBACK, 0,
                        sizeof(void(*)()), (UINT8*) &pFxn, 0 );
        }

        // We better validate the length of the supplied names
        if( strlen( s_stNetParam.szDomainName ) >= CFG_DOMAIN_MAX ||
            strlen(s_stNetParam.szHostName) >= CFG_HOSTNAME_MAX )
        {
            printf("Names too long\n");
            goto main_exit;
        }
       
        // Add our global hostname to hCfg (to be claimed in all connected domains)
        if(CfgAddEntry(hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0, strlen(s_stNetParam.szHostName),
                        (unsigned char*)s_stNetParam.szHostName, 0) < 0)
            goto main_exit;
        AddWebFiles();
         
        //Config http service
        {
            CI_SERVICE_HTTP http;

            bzero(&http, sizeof(http));
            http.cisargs.IPAddr = INADDR_ANY;
            http.cisargs.pCbSrv = &ServiceReport;
            if(CfgAddEntry(hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_HTTP, 0, sizeof(http), (unsigned char*)&http, 0) < 0)
                goto main_exit;
        }
       
        //
        // Configure IPStack/OS Options
        //
        // We don't want to see debug messages less than WARNINGS
        rc = DBG_WARN;
        if(CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL, CFG_ADDMODE_UNIQUE, sizeof(unsigned int), (unsigned char*)&rc, 0 ) < 0)
            goto main_exit;
       
        // Change our socket Tx buffer size to 16K bytes
        rc = 8192*4;
        if(CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF, CFG_ADDMODE_UNIQUE, sizeof(unsigned int), (unsigned char*)&rc, 0) < 0)
            goto main_exit;
        // Change our socket Rx buffer size to 8K bytes            
        rc = 8192;
        if(CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXBUF, CFG_ADDMODE_UNIQUE, sizeof(unsigned int), (unsigned char*)&rc, 0 ) < 0)
            goto main_exit;
        // UDP Receive limit
        rc = 8192;
        CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,
                     CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
       
        //Save the configuration to a linear buffer
        nMainCfgSize = 0;
        CfgSave(hCfg, &nMainCfgSize, 0);
        if(nMainCfgSize > sizeof(cMainCfgBuf))
        {
            printf("FATAL: Config buffer too small\n");

            CfgFree(hCfg);
            goto main_exit;
        }
        else
        {
            if(CfgSave(hCfg, &nMainCfgSize, cMainCfgBuf) <= 0)
                goto main_exit;
            CfgFree(hCfg);
        }
           
        //Start to config ip address 
        {
            CI_IPNET NA;
            CI_ROUTE RT;
            IPN      IPTmp;
            HANDLE      hCfg2;

            if(inet_addr(s_stNetParam.szLocalIPAddr))
                s_nDhcpEnable = 0;
            else
                s_nDhcpEnable = 1;
           
            do
            {   
                hCfg2 = CfgNew();
                if(!hCfg2 )
                {
                    printf("Unable to create configuration\n");
                    goto main_exit;
                } 
                if(CfgLoad(hCfg2, nMainCfgSize, cMainCfgBuf) != nMainCfgSize)
                    goto main_exit;
               
                if(s_nDhcpEnable == 1)
                {
                       CI_SERVICE_DHCPC dhcpc;
                      
                    //Specify DHCP Service on IF-1
                    bzero(&dhcpc, sizeof(dhcpc));
                    dhcpc.cisargs.Mode   = CIS_FLG_IFIDXVALID;
                    dhcpc.cisargs.IfIdx  = 1;
                    dhcpc.cisargs.pCbSrv = &ServiceReport;
                    if(CfgAddEntry(hCfg2, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0, sizeof(dhcpc), (UINT8 *)&dhcpc, 0) < 0)
                        goto main_exit;
                }
                else
                {
                    // If the IP address is specified, manually configure IP and Gateway
                    // Setup manual IP address
                    bzero(&NA, sizeof(NA));
                    NA.IPAddr  = inet_addr(s_stNetParam.szLocalIPAddr);
                    NA.IPMask  = inet_addr(s_stNetParam.szLocalIPMask);
                    strcpy(NA.Domain, s_stNetParam.szDomainName);
                    NA.NetType = 0;

                    //Add the address to interface 1
                    if(CfgAddEntry(hCfg2, CFGTAG_IPNET, 1, 0, sizeof(CI_IPNET), (unsigned char *)&NA, 0) < 0)
                        goto main_exit;

                    // Add the default gateway. Since it is the default, the
                    // destination address and mask are both zero (we go ahead
                    // and show the assignment for clarity).
                    bzero( &RT, sizeof(RT) );
                    RT.IPDestAddr = 0;
                    RT.IPDestMask = 0;
                    RT.IPGateAddr = inet_addr(s_stNetParam.szGatewayIP);
                    if(CfgAddEntry(hCfg2, CFGTAG_ROUTE, 0, 0, sizeof(CI_ROUTE), (unsigned char*)&RT, 0) < 0)
                        goto main_exit;
                   
                    // Manually add the DNS server when specified
                    IPTmp = inet_addr(s_stNetParam.szDNSServer);
                    if(IPTmp)
                        if(CfgAddEntry(hCfg2, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER, 0, sizeof(IPTmp), (unsigned char*)&IPTmp, 0) < 0)
                            goto main_exit;
                   }              
                   rc = NC_NetStart(hCfg2, NetworkOpen, NetworkClose, NetworkIPAddr);
                // Delete Configuration
                CfgFree(hCfg2);   
            } while( rc > 0 );
        }
        // Free the WEB files
        RemoveWebFiles();
    // Close the OS
    main_exit:
        NC_SystemClose();
        return;

    }

  • yongjia bi,

    I'm a bit confused on what you actually tried... Did you run the *original* client example, that shipped with your NDK product?  Or did you run your program?

    If so, please try again but with the client example.

    I'm currently running the client example with the socket buffer increased to 32K and it's running well.  I will run it overnight just to be sure.

    Also ...

    I reviewed your code above and I think it should be OK. But, I have a question about this:

       // Change our socket Tx buffer size to 16K bytes
        rc = 8192*4;
        if(CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF, CFG_ADDMODE_UNIQUE, sizeof(unsigned int), (unsigned char*)&rc, 0) < 0)
            goto main_exit;

    Is this how you are trying to increase the socket buffer size?  Please note that that won't increase the socket buffer size.  You need something like the following to be added to your code where you create the actual socket:

        x = 16384 * 2;
        setsockopt( s, SOL_SOCKET, SO_SNDBUF, &x, sizeof(x) );

     

    Steve

  • Steve,

    I have been running the ndk on our board  not on the evm board!  if you can runing more than one night, there  maybe are some bug in my board! I will check it by comparing to

    evm board!

    I call this function  only to set the default socket buffer size!(if(CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF, CFG_ADDMODE_UNIQUE, sizeof(unsigned int), (unsigned char*)&rc, 0) < 0))

    I also called this function(setsockopt( s, SOL_SOCKET, SO_SNDBUF, &x, sizeof(x) ))to set my send buffer in my program!

     

    thanks for your help!

  • yongjia bi,

    Ok, yes this is a good idea.  If you have the EVM board still, please try running on that in comparison with your custom hardware. If everything works OK on the EVM board, then this eliminates the NDK core stack code (which is hardware platform independent) as the culprit.

    If everything does work OK with the EVM board, then the problem could be in the driver code, or like you mention within the custom hardware itself.

    Thanks

    Steve

    P.S. I was able to run the client example on the EVMOMAPL138 board overnight, while continuously running the send.exe Windows side application.  The send program is still transferring data, and I am still able to ping the board.