Especially for dynamic memory allocation within UART callback, does anyone have an idea how to implement Re alloc function for RTOS? (Like PvPortRealloc(.,.))
It is because, let’s say I want to increment the allocation for a buffer each and every time one byte received by UART.
i.e.
//global variables
uint32_t bufferSize = 1;
uint8_t *rxBuffer = pvPortMalloc (bufferSize);
uint8_t incomingByte;
//trigger UART callback when 1 byte is received
HAL_UART_Receive_IT(&huart3, &incomingByte, 1);
//UART callback function, enters per byte received
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == UART3)
{
rxBuffer[bufferSize - 1] = incomingByte;
bufferSize++;
rxBuffer = pvPortReAlloc (bufferSize);//we need this function :)
HAL_UART_Receive_IT(&huart3, &incomingByte, 1);//trig again
}
}
Note: To use freeRTOS heap effectively, freeRTOS pvPortM… functions are supposed to be used instead of malloc, realloc and calloc functions. Otherwise, system heap will be used where freeRTOS memory will be partially useless.
Let me have your kind response at your earliest convenience.
Note: There are some pvPortRealloc functions on the web, github etc. However, they are creating new spaces before freeing the older ones, that makes duplicate memory usage…
If your environment is using newlib, with the multi-threaded option compiled in, then defining the malloc_lock and malloc_unlock functions is the best, at which point malloc/free/realloc/etc are now all thread safe and can be directly used.
The next option would be to extend heap3.c to include a wrapped version of realloc.
You could also rewrite heap4 or heap5 to include a realloc version, the simplest will just always create the new block as you saw, a smarter version would check of the block is followed by some free space and use it (which is basically what the library realloc does).
// ******************************************************************************************************
// * *
// * pvPortRealloc *
// * *
// * Funzione per riallocare dimensione memoria in heap region *
// * *
// * Parameter : (void *) Pointer to a memory block previously allocated with malloc, calloc or realloc *
// * (size_t) Number of byte to resize section *
// * *
// * Return : (void *) Pointer to allocate region, NULL if error on allocation *
// * *
// ******************************************************************************************************
void *pvPortRealloc( void *pv, size_t xWantedSize )
{
// Local variable
size_t move_size;
size_t block_size;
BlockLink_t *pxLink;
void *pvReturn = NULL;
uint8_t *puc = ( uint8_t * ) pv;
// Se NULL, exit
if (xWantedSize > 0)
{
// Controllo se buffer valido
if (pv != NULL)
{
// The memory being freed will have an BlockLink_t structure immediately before it.
puc -= xHeapStructSize;
// This casting is to keep the compiler from issuing warnings.
pxLink = ( void * ) puc;
// Check allocate block
if ((pxLink->xBlockSize & xBlockAllocatedBit) != 0)
{
// The block is being returned to the heap - it is no longer allocated.
block_size = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize;
// Alloco nuovo spazio di memoria
pvReturn = pvPortCalloc(1, xWantedSize);
// Check creation
if (pvReturn != NULL)
{
// Sposta soltanto fino al limite
if (block_size < xWantedSize)
{
// Il nuovo posto disponibile è inferiore
move_size = block_size;
}
else
{
// Il nuovo posto disponibile è maggiore
move_size = xWantedSize;
}
// Copio dati nel nuovo spazio di memoria
memcpy(pvReturn, pv, move_size);
// Libero vecchio blocco di memoria
vPortFree(pv);
}
}
else
{
// Puntatore nullo, alloca memoria come fosse nuova
pvReturn = pvPortCalloc(1, xWantedSize);
}
}
else
{
// Puntatore nullo, alloca memoria come fosse nuova
pvReturn = pvPortCalloc(1, xWantedSize);
}
}
else
{
// Exit without memory block
pvReturn = NULL;
}
// Exit with memory block
return pvReturn;
}