heinbali01 wrote on Monday, November 23, 2015:
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.
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
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
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:
As a simple example:
#define UART_DMA_BUFFER_SIZE 2048
size_t uxLength = UART_DMA_BUFFER_SIZE;
/* 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;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uxStreamBufferAdd( pxBuffer, 0, &xDMA[ dma_index ], sizeof( xDMA[ dma_index ] ) );
vTaskNotifyGiveFromISR( xDMATask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
for( ;; )
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
for( ;; )
uxCount = uxStreamBufferGet( pxBuffer, 0, uart_buffer, sizeof( uart_buffer ), pdFALSE );
if( uxCount == 0 )
/* All data ave been read. */
/* Process uxCount bytes. */
I hope that the example is clear and useful.