0
\$\begingroup\$

I am using a PIC32MX795F512L which sends CAN messages to a WiFly module (RN-171) using UART.

I receive messages over WiFi but after a longer time (20-60 minutes), the PIC seems to be stuck and I have to reset it. Below is the code for the UART initialisation, the message queuing and message sending.

TCPSending() is called every 200ms in an interrupt routine and PutInTXBuffer() is called whenever a CAN message is received (and then the ID and data are passed to the PutInTXBuffer function).

void InitUART()
{
    UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
    UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
    UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
    UARTSetDataRate(UART1, GetPeripheralClock(), 57600);
    UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
}

void TCPSending()
{
    if(UARTTransmitterIsReady(UART1) && U1STAbits.UTXBF == 0)
    {
        int i;
        for (i = 0; i < TXelements; i++)
        {
                putcUART1(WiFiTXBuffer[i].id >> 8);
                putcUART1(WiFiTXBuffer[i].id);
                putcUART1(WiFiTXBuffer[i].data >> 56);
                putcUART1(WiFiTXBuffer[i].data >> 48);
                putcUART1(WiFiTXBuffer[i].data >> 40);
                putcUART1(WiFiTXBuffer[i].data >> 32);
                putcUART1(WiFiTXBuffer[i].data >> 24);
                putcUART1(WiFiTXBuffer[i].data >> 16);
                putcUART1(WiFiTXBuffer[i].data >> 8);
                putcUART1(WiFiTXBuffer[i].data);
        }
        free(WiFiTXBuffer);                 // Deallocate the buffers memory
        WiFiTXBuffer = NULL;                // Re-initialize the buffer
        TXelements = 0;                     // Keeps track of the number of elements used
        TXallocated = 0;                    // This is essentially how large the array is
    }
}

void PutInTXBuffer(WORD id, QWORD data)
{
    int MoreAllocation = 50;

    WiFiTXPacket packet;
    packet.id = id;
    packet.data = data;
    if(TXelements == TXallocated)                               // Are more refs required?
    {
        TXallocated += MoreAllocation;
        // Make the reallocation transactional by using a temporary variable first

        void* temp = realloc(WiFiTXBuffer, (TXallocated * sizeof(WiFiTXPacket))); 

        // If the reallocation fails:
        if (!temp)
        {
            TXallocated -= MoreAllocation;
        }

        WiFiTXBuffer = (WiFiTXPacket*)temp;


        free(temp);
        temp = NULL;

    }

    WiFiTXBuffer[TXelements] = packet;
    TXelements++;
}

I think the problem has to do with a memory leak but I can't seem to find it.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ This isn't an answer but I've never had a good reason to use dynamic memory allocation in a small embedded system. Any reason not to use a fixed sized global buffer, or local variables as appropriate? \$\endgroup\$
    – PeterJ
    Aug 7, 2013 at 12:37
  • \$\begingroup\$ I will try to rewrite the code to have a global buffer. I wrote it with dynamic memory because there are a lot of messages on the CAN network which all need to be buffered. \$\endgroup\$
    – JoGe
    Aug 7, 2013 at 12:58
  • \$\begingroup\$ If the MCU gets stuck and you have to reset it, because of dynamic memory allocation, then another fundamental problem is also that you haven't enabled the watchdog. \$\endgroup\$
    – Lundin
    Aug 13, 2013 at 11:58

1 Answer 1

2
\$\begingroup\$

It turned out the dynamic memory was indeed the problem. I ended up using the ringbuffer implementation documented here: http://www.piconomic.co.za/fwlib/ring__buffer_8c_source.html

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.