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.

RTOS/DK-TM4C129X: Need memory for NDK, as in MakingHTTPServer: settings ignored by XGCONF

Part Number: DK-TM4C129X
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

I am attempting to stream out of the MCU to a remote UDP socket, but I get ENOBUFS.  I assume this means that I need more memory for the streaming task and the concurrent HTTP server.  When I attempt to increase the BIOS heap size, as outlined on page 18 of TI's HTTP server document MakingHTTPServer.ppt, the settings are ignored by XGCONF.  After saving the file and reloading it with XGCONF, the settings are still "null".  I also tried setting BIOS.heap* using a text editor, as detailed in post "Heap size configuration", but the change was not visible in XGCONF.

How do I increase the size of the heap for NDK?

  • What version of TI-RTOS are you using? Can you attach your .cfg file (please attach and not copy/paste).

    Fyi...there is a write-up on the memory usage of the NDK here: processors.wiki.ti.com/.../TI-RTOS_Networking_Stack_Memory_Usage

    Todd
  • I am using C:\ti\tirtos_tivac_2_16_01_14.  Attached below is the configuration file.  Sorry about the icon size.  It doesn't seem to be adjustable.ni.cfg

  • Leo,

    The file looks fine and it worked for me. I could graphically change the bios.heapSize. What versions of TI-RTOS, CCS and XDCtools are you using? Also, what host OS (Windows, Linux or MacOS) are you using?

    When you text edit the file and build, does the change show up. You can confirm by looking at the mapfile and search for ti_sysbios_heaps_HeapMem_Instance_State_0_buf__A in the .bss section.

    Todd
  • Here are the versions:

    TI-RTOS TivaC: 2.16.01.14

    CCS: 7.1.0.00016

    XDCtools: 3.32.00.06.core

    Windows 7

    NDK: 2.25.01.11

    The good news is that I see the following line in the .map file:

    20018b40 00005800 (.common:ti_sysbios_heaps_HeapMem_Instance_State_0_buf__A)

    I'm fine with knowing that XGCONF has trouble putting BIOS.heapSize in its menus.  I didn't know whether or not the requested heap size was actually being implemented, but, now that I do, I know I have no configuration troubles.  I will stop using XGCONF.

    I have a little HTTP cgi server running in parallel with a continuous 31 Mb/second UDP transmit stream.  The server responds just fine, but I notice that, often, when I service an HTTP request, the UDP stream still sees ENOMEM, even with the heap proven to be bigger.  This is with the following settings:

    Global.memRawPageCount = 24;
    Global.pktNumFrameBufs = 24;
    Udp.receiveBufSize = 16000;
    BIOS.heapSize = 22528;

    When there is no HTTP activity, I see no ENOMEM.

  • Does everything recovery after the ENOMEM? Where exact are you seeing the ENOMEM?
  • Everything recovers just fine, and my buffering scheme may even be succeeding at a retry with no datagrams lost.  But I would rather have no memory problems.

    Here's the code which fails in sendto():

          if
          ( // Host has not set itself and us up for transfer
            (!csc.configuration.nhReceiving)
          ||
            // Can't get status on socket
            fdStatus(pollItems[POLL_COIL_DATA].fd, FDSTATUS_SEND, &resultCoilSend) == -1
          ||
            // Not enough buffer space for message
            resultCoilSend < sizeof(coilInput[ci])
          ||
            // Sendto() failed
            (
             sendto(
                pollItems[POLL_COIL_DATA].fd,
                &(coilInput[ci]),
                sizeof(coilInput[ci]),
                0,
                (struct sockaddr *)&nhCoilAddr,
                sizeof(nhCoilAddr)
              )
            !=
              sizeof(coilInput[ci])
            )
          ) {
            // Record dropped packet, but don't close UDP socket.
            ++csc.status.ipMessagesDropped;
            csc.status.lastIpErrno = fdError();
          } else {
            ++csc.status.ipMessagesSent;
          }
    

    Maybe the stack is telling me that there is enough space for sendto(), but the HTTP server is stealing the space in the interim.  This code runs right after fdPoll().

  • I'm bringing up another task which sends infrequent, periodic UDP messages. At the very start of the task function, the call to fdOpenSession() prints "00000.000 fdOpenSession: OOM," meaning, I assume, "out of memory." I imagine this is related to my other memory problem. FdOpenSession()'s first mmAlloc() attempt fails because PITCount is zero.
  • Please ignore the last message. I was trying to start an NDK-managed task before NDK was running.
  • Hi Leo,


    sendto() shouldn't set errno to ENOMEM.  When it can't allocate a PBM buffer (needed in order to send the UDP packet), it sets errno to ENOBUFS.  I'm wondering if the ENOMEM reported from fdError() in your code is from a failure somewhere else.  Can you try calling fdError() before you call sendto?  Not sure how easy/hard this might be to catch ...

    Leo Bredehoft58 said:
    Udp.receiveBufSize = 16000

    It sounds like you are sending a log of UDP data.  But, are you receiving a lot of data?  Just wanted to check that you need to have the RX buffer for each UDP socket be 16K.

    If not, you could try lowering that size which would free up space and allow you to increase the size of the NDK memory pool (i.e. increase value set for Global.memRawPageCount in your *.cfg file [looks like it's currently set to 24]).

    Steve

  • Hi Steve:

    Sorry, I started out this post saying ENOBUFS (55), which is actually what I am seeing, then I made an error and started saying ENOMEM. I'm not receiving any UDP data. I don't expect to do so, even when I have the application completed. I have let Udp.receiveBufSize return to a default what looks in XGCONF to be 2048 bytes. Here are the current stack memory settings:

    Global.memRawPageCount = 24;//8;
    Global.pktNumFrameBufs = 32;//16;

    //var Udp = xdc.useModule('ti.ndk.config.Udp');
    //Udp.receiveBufSize = 16000;

    var Ip = xdc.useModule('ti.ndk.config.Ip');
    Ip.socketMaxConnections = 16;

    BIOS.heapSize = 22528;

    I think you have put me on to the right track. With this setup, ENOBUFS is much rarer. I think Global.pktNumFrameBufs = 32; did the trick. I will pursue that avenue when tuning.

    Best regards,
    Leo
  • OK, great.

    Do you know if you're ever sending an amount of data > 3016 bytes? (in a single sendto call)

    If so, then you may be hitting a limitation within the NDK's implementation of UDP.

    See here for more details:

    e2e.ti.com/.../2072168

    Steve
  • I'm only sending about 1475 bytes per sendto() call, so that probably isn't a problem. I see the data at the receiving end, at about the right bit rate.

    This isn't a fix request, but, interestingly, at 30 Mbits/second, the stack spends about 1/4 of real time generating checksums for the UDP data. I looked at the code, and the generated assembly, and I didn't see any glaring inefficiency, so the only improvement there will be a faster clock speed. Heroic effort in the checksum code might yield some improvement, but nothing really great. At some point off in the future, I will probably want to shut off UDP checksums entirely, since the data is already checked on the physical layer.

    This is, by the way, a good embedded stack implementation. None of the difficulties I have experienced is anything which couldn't be expected. Fine job!