Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Calling malloc in FreeRTOS inside and outside of ISR

Posted by pugglewuggle on November 23, 2015

I need to dynamically allocate some memory 1) from in a task, and 2) from in an ISR.

Should I always use pvPortMalloc or is there any instance where I should used regular malloc from stdlib?

Also, I need to dynamically allocate some memory in an ISR to create an item for a queue. Is it okay/a good idea to call some form of malloc/pvPortMalloc (depending on ths answer to my first question) inside an ISR? (is it thread-safe, too slow, etc?). I'm using heap_4 right now.


Calling malloc in FreeRTOS inside and outside of ISR

Posted by heinbali01 on November 23, 2015

Hi Pugglewuggle

I need to dynamically allocate some memory 1) from in a task, and 2) from in an ISR.

Personally I would not recommend dynamically allocate memory from an ISR because:

  • Most allocators are not written to be called from an ISR.
  • ISR's must be fast and most calls to [pvPort]malloc() have a variable processing time

Most people will use a queue and feed it with xQueueSendFromISR(). That will also wake-up a task which is waiting for data.

Volume data:

If the ISR produces bigger quantities of data, and if there is only one consumer-task of that data, then I would prefer to use a circular buffer, such as FreeRTOS-Plus-TCP\FreeRTOS_Stream_Buffer.c. This can be accompanied with a call to vTaskNotifyGiveFromISR() (or xSemaphoreGiveFromISR() etc) which will wake-up the task.

Should I always use pvPortMalloc or is there any instance where I should used regular malloc from stdlib?

I would not mix the use of both allocators. But if you want you can use the malloc() and free() from stdlib, and make those thread-aware with the wrap-arounds.

I tend to prefer using:

  • heap_4.c In case I have 1 block of contiguous RAM data available
  • heap_5.c In case there are several non-contiguous blocks of RAM

The algorithm used is safe and very fast.

Also, I need to dynamically allocate some memory in an ISR to create an item for a queue. Is it okay/a good idea to call some form of malloc/pvPortMalloc (depending on ths answer to my first question) inside an ISR? (is it thread-safe, too slow, etc?). I'm using heap_4 right now.

Please have a look at:

FreeRTOS-Plus-TCP\include\FreeRTOS_Stream_Buffer.h

As a simple example:

~~~~~

define UARTDMABUFFER_SIZE 2048

StreamBuffer_t *pxBuffer;

void createbuffer() { sizet uxLength = UARTDMABUFFERSIZE; sizet uxSize;

/* Add an extra 4 (or 8) bytes. */
uxLength += sizeof( size_t );

/* And make the length a multiple of sizeof( size_t ). */
uxLength &= ~( sizeof( size_t ) - 1u );

uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;

pxBuffer = ( StreamBuffer_t * )pvPortMalloc( uxSize );

if( pxBuffer != NULL )
{
    /* Clear the header data. */
    memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
    /* Treat the 'LENGTH' member (all capitals) as a 'const member' */
    pxBuffer->LENGTH = uxLength;
}

}

void uartisr() { BaseTypet xHigherPriorityTaskWoken = pdFALSE;

reset__flags();
uxStreamBufferAdd( pxBuffer, 0, &xDMA[ dma_index ], sizeof( xDMA[ dma_index ] ) );
vTaskNotifyGiveFromISR( xDMATask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

}

void uarttask() { createbuffer(); install_isr();

for( ;; )
{
size_t uxCount;

    ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
    for( ;; )
    {
        uxCount = uxStreamBufferGet( pxBuffer, 0, uart_buffer, sizeof( uart_buffer ), pdFALSE );
        if( uxCount == 0 )
        {
            /* All data ave been read. */
            break;
        }
		/* Process uxCount bytes. */
    }
}

} ~~~~~

I hope that the example is clear and useful.

Regards.


Calling malloc in FreeRTOS inside and outside of ISR

Posted by rtel on November 23, 2015

In addition to Hein's post - when using an RTOS you can always defer the interrupt processing to a task.

Have a task block to wait for the interrupt, then unblock the task from the interrupt. If the task has a high priority it will execute immediately after the interrupt - so processing occurs contiguous in time just as if it had all happened in the interrupt. Once in the task you can call any API functions you like.

The fastest way of doing this is to use a direct to task notification. See http://www.freertos.org/RTOSTaskNotificationAsBinary_Semaphore.html for a full example.

A more restricted method that requires fewer tasks is to use the centralised deferred interrupt processing feature: http://www.freertos.org/xTimerPendFunctionCallFromISR.html


Calling malloc in FreeRTOS inside and outside of ISR

Posted by heinbali01 on November 23, 2015

I showed the stream buffer as an example of how to "allocate memory" from within an ISR, but the method described by Richard is better, more efficient.

The function uxStreamBufferAdd() will call memcpy() one or two times, depending on the position within the buffer.


Calling malloc in FreeRTOS inside and outside of ISR

Posted by pugglewuggle on November 23, 2015

How does this work if the task also is pending on a queue? (The direct task notification)


Calling malloc in FreeRTOS inside and outside of ISR

Posted by richard_damon on November 23, 2015

If you REALLY want to use malloc in an ISR, you need to create a version of pvPortMalloc that uses a critical section (that disables interrupts) during the malloc/free call, and if interrupts nest, you need a pvPortMallocFromISR that blocks nesting during the call to malloc/free. Note, this has significant implicatons, and is really not recomended.

The alternative (and prefered method), is to use one of the methods provided in FreeRTOS to push the data allocation to a task. In my mind, whenever possible, I try to avoid using malloc once the system has completed its initialization phase, and our coding standards require this unless STRONG justification can be provided, as there are a lot of issues that need to be dealed with when you use dynamic memory in real time systems.


Calling malloc in FreeRTOS inside and outside of ISR

Posted by pugglewuggle on November 24, 2015

Honestly I have no desire to use malloc at all ;-) but how can implement the alternative solution used here: http://www.freertos.org/Pend-on-multiple-rtos-objects.html#alternativedesignpattern without malloc in an ISR? Do you have a suggestion about how to do this?


Calling malloc in FreeRTOS inside and outside of ISR

Posted by pugglewuggle on November 25, 2015

Anybody?


Calling malloc in FreeRTOS inside and outside of ISR

Posted by heinbali01 on November 26, 2015

I'm afraid that your last question isn't clear. I'm not sure why you would need to malloc() in order to use these mechanisms.

Looking at the mentioned FreeRTOS page: a server expects messages of type 'IPStackEvent_t'. Do you want to malloc() space for these messages before sending them?

In the given example, malloc is not necessary: the xNetworkEventQueue has been created with an element size of 'sizeof( IPStackEvent_t )'. An interrupt will declare one IPStackEvent_t on stack, fill it, and send it (in fact copying it) to the queue.

If this is not the answer that you're looking for, please explain more, or give an example which does use malloc()

Regards.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS