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.

Compiler/TMS320F28335: Created a template buffer class: question about memory allocation

Part Number: TMS320F28335


Tool/software: TI C/C++ Compiler

Dear all, forum, TI,

We are currently working on a project that involves multiple microcontrollers. To minimize code work, me and my colleague are trying to reuse some code. My colleague wrote the attached buffer class (CircularBuffer implemented.h). The idea is to store incoming data from SCI or CAN in the interrupt service routine, and read from the buffer again when the CPU has 'time left' (ie not busy with an interrupt). The function push(data) pushes the new element into the buffer. With pop(), we read an element from the buffer. Before popping an element, we manually check if there is an element available by using the size() function. If the buffer is full, it just overwrites the first element again.

Now the issue: it seems that, when initializing multiple buffers in one class, the allocated memory is the same. At least, that is what is seems to do. What I did is the follwing: sending cyclically a known value over CANB to one mailbox, while sending zeros to the other mailboxes (all a unique ID). Then: reading using the interrupt and pushing in the separate buffers. Then, main pops the values from the seperate buffers and sends them over CANA using different mailboxes (and thus ID's again).

The issue: the data over CANA has sometimes the known value, sometimes the unwanted 0.

Related to this behaviour seems the following: all buffers seems to have the same address. I see the following for every buffer when halting the program during runtime with a breakpoint. The whole program is ran from flash.

Name : *(array)
    Default:-4283498321
    Hex:0xFFFFFFFF00AF00AF
    Decimal:-4283498321
    Octal:053600257
    Binary:1111111111111111111111111111111100000000101011110000000010101111b

The buffers in the class are initialized as follows:

.h file:

    CircularBuffer<int64_t, 100> IVTcurrentBuffer;
    CircularBuffer<int64_t, 100> IVTvolt1Buffer;
    CircularBuffer<int64_t, 100> IVTvolt2Buffer;
    CircularBuffer<int64_t, 100> IVTvolt3Buffer;
    CircularBuffer<int64_t, 100> IVTtempBuffer;
    CircularBuffer<int64_t, 100> IVTpowerBuffer;
    CircularBuffer<int64_t, 100> IVTenergyCntBuffer;

.cpp file:

    IVTcurrentBuffer = CircularBuffer<int64_t, 100>();
    IVTvolt1Buffer = CircularBuffer<int64_t, 100>();
    IVTvolt2Buffer = CircularBuffer<int64_t, 100>();
    IVTvolt3Buffer = CircularBuffer<int64_t, 100>();
    IVTtempBuffer = CircularBuffer<int64_t, 100>();
    IVTpowerBuffer = CircularBuffer<int64_t, 100>();
    IVTenergyCntBuffer = CircularBuffer<int64_t, 100>();

My question is: can anyone see what is going on here with the memory allocation for different buffers that are using the same template? Otherwise, any other suggestions where this problem can be? I checked the ISRs from the CAN mailboxes, but they operate fine (tested with other sequences without the use of these type of buffers).

One final thing: my colleague is using an NXP MCP5744 and ran into an problem using malloc or calloc, so his version is included as well (CircularBuffer alternative.h), but running that code runs into an ILLEGAL_ISR. Any ideas why that would differ between the two microcontrollers (I am using the TMS320F28335).

Any idea would be appreciated! Jeroen

CircularBuffer implemented.h

CircularBuffer alternative.h

  • Hi Jeroen--Someone will look into this and get back to you soon. Thanks for your patience.

    Regarding the ILLEGAL_ISR, this page has some tips on causes and ways to debug it:
    processors.wiki.ti.com/.../Interrupt_FAQ_for_C2000

    Whitney
  • You are probably running out of heap memory.  The code you show requires 5600 words of heap.  

    These lines ...

    Jeroen Goudswaard said:

    .h file:

        CircularBuffer<int64_t, 100> IVTcurrentBuffer;
        CircularBuffer<int64_t, 100> IVTvolt1Buffer;
        CircularBuffer<int64_t, 100> IVTvolt2Buffer;
        CircularBuffer<int64_t, 100> IVTvolt3Buffer;
        CircularBuffer<int64_t, 100> IVTtempBuffer;
        CircularBuffer<int64_t, 100> IVTpowerBuffer;
        CircularBuffer<int64_t, 100> IVTenergyCntBuffer;

    ... are not just declarations of those buffers.  These lines create and initialize them, including calling the constructor, which in turn calls calloc.  All that initialization occurs during system startup, before main starts.  So, before main starts, you have used up 2800 words of heap.

    These lines ...

    Jeroen Goudswaard said:

    .cpp file:

        IVTcurrentBuffer = CircularBuffer<int64_t, 100>();
        IVTvolt1Buffer = CircularBuffer<int64_t, 100>();
        IVTvolt2Buffer = CircularBuffer<int64_t, 100>();
        IVTvolt3Buffer = CircularBuffer<int64_t, 100>();
        IVTtempBuffer = CircularBuffer<int64_t, 100>();
        IVTpowerBuffer = CircularBuffer<int64_t, 100>();
        IVTenergyCntBuffer = CircularBuffer<int64_t, 100>();

    ... invoke the constructor (with the call to calloc) yet again.  This takes up another 2800 words of heap.  

    What you should do instead is declare the buffers, and supply one definition in one source file.  Do not explicitly call the constructor.  Here is an example using one buffer ...

    // In the header file
    extern CircularBuffer<int64_t, 100> IVTcurrentBuffer;
    
    // In ONE source file
    CircularBuffer<int64_t, 100> IVTcurrentBuffer;

    With that fix, you will lower heap usage to 2800 words.  Be sure you allocate more heap than that.

    It would be ideal if you added code in the constructor to check if calloc returns NULL.  If it does, then perform some error handling.

    Thanks and regards,

    -George

  • Hi George,

    thank you for your reply! I have not yet had time to look into your solution, but I will certainly next week. ATM I removed the buffering and now store data in my data class directly upon an CAN interrupt. Thinking of it, these buffers still require quite some heap-space...but I will look at it!

    Thanks again,

    Jeroen